干净地在FactoryGirl中设置多个模型以获得测试/规格

时间:2013-05-07 15:04:02

标签: ruby-on-rails unit-testing rspec factory-bot

我一直在研究Rails最佳实践并学习为我的rails应用程序编写好的测试。

我现在正在使用rspec + FactoryGirl进行测试。

有一段时间我正在编写基本模型和控制器规范,通常只需要设置几个模型和关联。

现在我有一个具有复杂算法的模型,它根据不同的模型进行了大量的计算。

为了测试这个方法,我几乎需要我的app的所有模型都存在于测试数据库中,并且它们之间建立了所有相关的关系。

现在事情变得势不可挡。如果所有工厂都正确引用彼此,我需要跟踪。此外,我需要验证是否所有工厂都已正确创建。 还有很多FactoryGirl.create(:model)在我的before(:each)方法中调用。

我感觉我做得不对。这种情况的最佳方法是什么?大多数书籍和例子仅涵盖最基本的案例。

欢迎提出任何指示想法和方法。(希望这个问题的范围不是太宽)

示例:

我的应用有多个projects。每个项目都有indexescompaniesmastertags。每家公司都有_ channels。不同channel_tag_weights的每个频道都有{_ 1}个mastertags。此外,每个频道都有__ Rawdatas

这可能是所需的最低模型设置的一个例子。

3 个答案:

答案 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)

如果您只测试一种方法,那就是单元测试。

我认为你不需要设置太多东西。

一个方法有输入和输出,您只需用手动创建的输入示例来提供它,并期望它生成正确的输出。

如果某个方法有太多问题需要考虑,可以将其拆分为多个方法,并对每个方法进行单元测试。

当进行集成测试时,应该设置整个环境。是的,您需要准备所需的所有工厂。