2

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

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

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

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

为了测试这种方法,我几乎需要我的应用程序的所有模型都存在于测试数据库中,并在它们之间建立所有关联关系。

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

我有一种感觉,我做的事情不对。解决这种情况的最佳方法是什么?大多数书籍和示例仅涵盖非常基本的案例。

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

例子:

我的应用程序有多个projects. 每个项目有_manyindexes和. 每个公司都有_many 。每个频道 has_many跨越不同的. 每个频道也都有 has_many 。companiesmastertagschannelschannel_tag_weightsmastertagsRawdatas

这可能是所需的最小模型设置的示例。

4

3 回答 3

3

我为此写了一个名为stepford的宝石。

在您的 gemfile 中:

group :test do
  gem 'stepford'
  #...
end

然后bundle install

备份您的 factory.rb 或包含工厂的现有多个文件。实际上,您需要将它们移开,因为如果它加载其他工厂,那可能会干扰。

然后:(bundle exec stepford factories --path spec如果想将 factory.rb 放在规范目录中 - 还有其他选项可以为每个模型创建一个工厂,等等)。

我们遇到了需要在存在外键约束的情况下创建依赖项的问题。在此过程中,我编写了modelist gem,它可以帮助识别循环依赖关系,如果您正在处理遗留数据,您可能需要检查并运行它。而 Stepford 的深度创作方法则绕过了这些问题。但是,我们已经开始避免使用 Stepford 的 deep_* 方法,尽管我们仍然使用了一点。最好具体说明您在做什么并直接使用工厂女孩,即使它会使测试代码更脆弱且看起来过于复杂。

您还可以查看固定装置或机械师。这真的取决于你需要什么。

如果您需要实际为模型创建所有代码,那就是另一个问题了。我编写了一个脚本来为本地遗留模式(非常大)生成模型,它确实有帮助,但需要几个月的迭代工作。问题是模式本身不是(必然)模型中关联或设置的明确描述。为了让您了解我在说什么,我写了一些 gem 来帮助遗留应用程序等正在做/已经做过的一些我们必须处理的事情,比如不可删除、activerecord-define_nils、 mark_only、activerecord-custom_timestamps、activerecord-native_db_types_override 以及早期尝试中的其他一些。我们使用了一些已经存在的很棒的 gem,比如composite_primary_keys 和foreigner。

我们努力解决的其他一些事情是使用 MTI(多表继承),尽管有一些宝石试图提供帮助,但我们最终通过钩子等在我们的模型中自己处理它。我们合并了一些模式(不是什么轻描淡写,但分区不是必需的,并且公寓、second_base 和类似的宝石会增加复杂性,甚至不考虑无法加入、使用普通查询)。

请注意:在我们的例子中,我们有很多桌子。如果你没有那么多,你仍然可以使用 Stepford 来让第一次创建工厂更容易一些,但我认为你会没事的。

于 2013-05-07T15:43:02.527 回答
1

每当我遇到这种情况时,我都会尝试确保我的所有 FactoryGirl 模型都利用了 FactoryGirl 的内置关联方法:

https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations

这样,为了使单个模型正确验证所需的关联模型就会出现。FactoryGirl 将完成使用额外测试数据填充数据库的过程。

因为您正在使用 has_many 关联,所以您需要研究工厂定义的 after(:create) 方法以正确设置您的关联。这也将允许您创建特定于这些深度集成规范的定义,并使更简单的工厂独立于更简单的规范。

于 2013-05-07T15:42:50.590 回答
0

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

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

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

如果一个方法有太多需要关心的事情,你可以将它拆分成几个方法,并对每个方法进行单元测试。

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

于 2013-05-07T15:42:58.403 回答