我一直在研究Rails最佳实践并学习为我的rails应用程序编写好的测试。
我现在正在使用rspec + FactoryGirl进行测试。
有一段时间我正在编写基本模型和控制器规范,通常只需要设置几个模型和关联。
现在我有一个具有复杂算法的模型,它根据不同的模型进行了大量的计算。
为了测试这个方法,我几乎需要我的app的所有模型都存在于测试数据库中,并且它们之间建立了所有相关的关系。
现在事情变得势不可挡。如果所有工厂都正确引用彼此,我需要跟踪。此外,我需要验证是否所有工厂都已正确创建。 还有很多FactoryGirl.create(:model)在我的before(:each)方法中调用。
我感觉我做得不对。这种情况的最佳方法是什么?大多数书籍和例子仅涵盖最基本的案例。
欢迎提出任何指示想法和方法。(希望这个问题的范围不是太宽)
示例:
我的应用有多个projects
。每个项目都有indexes
,companies
和mastertags
。每家公司都有_ channels
。不同channel_tag_weights
的每个频道都有{_ 1}个mastertags
。此外,每个频道都有__ Rawdatas
。
这可能是所需的最低模型设置的一个例子。
答案 0 :(得分:3)
我为此写了一个名为stepford的宝石。
在你的gemfile中:
group :test do
gem 'stepford'
#...
end
然后bundle install
。
备份您的factories.rb或包含工厂的现有多个文件。实际上,您需要将它们移开,因为如果它加载了其他工厂,那么可能会产生干扰。
然后:bundle exec stepford factories --path spec
(如果想在工具目录中放置factories.rb-还有其他选项可以为每个模型创建一个工厂,等等。)
我们遇到了在存在外键约束的情况下需要创建的依赖项问题。在这个过程中,我编写了modelist gem,可以帮助识别循环依赖关系,如果您正在处理遗留数据,可能需要检查并运行。斯蒂福德的深层创作方法解决了这些问题。但是,我们已经开始避免使用Stepford的deep_ *方法,即使我们仍然使用它一点点。最好是具体了解你正在做什么并直接使用工厂女孩,即使它可以使测试代码更脆弱和过于复杂的外观。
您还可以查看灯具,或machinist。这实际上取决于你需要什么。
如果您需要为模型实际创建所有代码,那就是另一个问题。我编写了一个脚本来为本地遗留模式(非常大)生成模型,它确实有所帮助,但它需要数月的迭代工作。问题是模式本身不是(必然)对模型中的关联或设置的确定描述。为了让你知道我在说什么,我写了一些宝石,以协助遗留应用程序等正在做/已经完成的一些事情,我们不得不处理,如undeletable,activerecord-define_nils, mark_only,activerecord-custom_timestamps,activerecord-native_db_types_override以及之前尝试中的其他一些内容。我们使用一些已经存在的伟大宝石,如composite_primary_keys和外国人。
我们努力解决的其他一些事情是使用MTI(多表继承),尽管有一些尝试帮助的宝石,我们最终通过钩子等在我们的模型中处理它。我们合并了一些模式(不是一件容易接受的事情,但这些划分并不是必要的,而且公寓,second_base和类似的宝石会增加复杂性,甚至不考虑无法加入,使用普通查询)。
请注意:在我们的案例中,我们有很多表格。如果你没有那么多,你仍然可以使用Stepford来使第一次创建工厂变得容易一点,但是我认为你会没事的。
答案 1 :(得分:1)
每当我遇到这种情况时,我会尝试确保所有FactoryGirl模型都利用FactoryGirl的内置关联方法:
https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations
这样就存在了单个模型正确验证所需的关联模型。 FactoryGirl将使用额外的测试数据完成填充数据库的过程。
因为您使用的是has_many关联,所以您需要研究工厂定义的after(:create)方法,以便正确设置关联。这也将允许您创建特定于这些深度集成的规范的定义,并使更简单的工厂独立于更简单的规范。
答案 2 :(得分:0)
如果您只测试一种方法,那就是单元测试。
我认为你不需要设置太多东西。
一个方法有输入和输出,您只需用手动创建的输入示例来提供它,并期望它生成正确的输出。
如果某个方法有太多问题需要考虑,可以将其拆分为多个方法,并对每个方法进行单元测试。
当进行集成测试时,应该设置整个环境。是的,您需要准备所需的所有工厂。