我正在开发我的第一个真实世界的Rails项目。到目前为止,我主要是从第三方库中混搭功能。那里有很多伟大的,那太好了。
我想知道围绕这些库编写单元测试是否必要/有用。例如,我只在我的一个模型周围集成了friendly_id。除了安装gem并将其添加为项目依赖项之外,此集成的这个程度还包括:
has_friendly_id :name
它刚刚工作,我几乎不认为这是“我写的代码”。那么我应该通过测试来写作呢?
我的问题有两点需要注意:
除此之外......测试第三方代码有多大意义?
答案 0 :(得分:2)
通常的做法是对其他一方的代码进行单元测试。通常,您会相信您的上游依赖项可以正常工作。
但是假设你真的相信他们。这应该有各种各样的原因。
首先,你会陷入一种近乎被抛弃的依赖关系,其中包含一些错误的错误。当您发现错误时,编写测试来执行错误并为错误运行解决方法。
另一个原因可能是因为第三方不断改变每一件该死的东西。因为你可以腾出时间,所以添加你实际使用的尘埃角落的测试是合理的,因为在新版本中你最容易改变它们。
显然,这些案例中的任何一个都会浪费你宝贵的时间,你可能会花费更多的时间来改善你的应用程序,而不是处理你无法控制的事情。如果您发现需要进行此类测试,那么您应该真正寻找一种更可信赖的替代方案来替代该特定依赖项。
答案 1 :(得分:2)
永远不要相信第三方库。我总是写一组测试,我称之为第三方库的“健全性检查”,但我只将其应用于一个模型/控制器/无论如何。因此,例如,如果我使用acts_as_paranoid gem(它使数据库记录看起来被删除但实际上没有删除它),我将为只使用扩展的模型的一个编写一组测试,并假设它适用于其余的人。这让我可以在晚上睡觉,知道我可以在新版本发布时更新gem,甚至使用“edge”版本,并且预期的功能将是可靠的。
答案 2 :(得分:1)
根据经验,以下是我的意见:
VCR.use_cassette('cassete-name') do
块,它应该与使用WebMock / Fakeweb / Artifice等非常相似。后者是我的首选。)答案 3 :(得分:0)
不,您不应该测试第三方代码,如果可能,它应该位于界面后面,以便您可以根据需要轻松更换功能。
该接口允许您在代码中使用模拟,以模拟对库的调用。
答案 4 :(得分:0)
countries
gem 的简短示例:
require 'test_helper'
class CountriesLearningTest < ActiveSupport::TestCase
def test_returns_country_name
assert_equal 'United States of America', Country.new('US').name
end
def test_returns_country_alpha2_code
assert_equal 'US', Country.new('US').alpha2
end
end
我认为可以安全地假设库的单元测试已经足够好了。但是,出于以下原因,编写所谓的学习(或发现)集成测试可能是有益的:
paper_trail
gem 的另一个示例:
require 'test_helper'
class Post < ApplicationRecord
has_paper_trail
end
class PaperTrailLearningTest < ActiveSupport::TestCase
setup do
ActiveRecord::Base.connection.create_table :posts do |t|
t.string :title
# Otherwise `touch` fails silently
t.datetime :updated_at
end
end
def test_returns_version_list
@record = Post.create!(title: 'any')
assert_equal 1, @record.versions.count
assert_respond_to @record.versions.first, :item_id
end
def test_creates_new_version_upon_update
@record = Post.create!(title: 'old title')
original_record = @record.clone
assert_difference -> { @record.versions.size } do
@record.update!(title: 'new title')
end
version = @record.versions.last
assert_equal @record.id, version.item_id
assert_equal @record.class.name, version.item_type
assert_equal version.reify, original_record
assert_equal ['old title', 'new title'], version.object_changes['title']
assert_equal 'update', version.event
end
end