2011-05-02 60 views
7

我来自Spring/Hibernate背景。我注意到Rails没有道和服务层。这确实加快了开发速度,但我不知道应该在哪里进行测试。我在哪里把我的数据库查询测试在轨道上?

现在,我一直在我的模型方法和验证测试在主模型spec。这个文件已经相当大了。

“标准”测试查询的地方在哪里?我可以想象自己制作了大量的灯具/虚拟数据,以确保我的查询能够按照预期工作(可能是因为我是rails新手而更好的想法)。这些对于基本的模型逻辑和验证测试并不是真的需要。

如果你可以提供一些建议,把这些测试放在哪里,使用rails测试查询的最佳方法(特别是带有多个连接的测试!),也许一些基本的指导方针可能与使用DBunit /春天/冬眠,那会很棒。

谢谢!

+0

不确定“查询”是什么意思。在Rails中,最好将数据库视为持久对象的地方。 ActiveRecord对象更加精确。 ORM负责所有的数据库逻辑和SQL。那些不需要被测试,除非你正在做一些违反公约的事情。 – 2011-05-04 14:29:26

+0

@Mike Farmer如果您在请求特定值之前走过对象图20次,ActiveRecord会在20个表之间创建一个复杂而有效的SQL连接? – egervari 2011-05-09 20:37:43

+0

只要你正确地设置你的关联,我真的不明白为什么不。来自数据库背景,但我明白你的观点。编写测试以确保您的查询构建正确并具有高性能是您指定的复杂性的好主意。为您的关联修改一些finder_sql,counter_sql,delete_sql和insert_sql对于更复杂的查询也可能会有所帮助。请参阅(http://j.mp/lOSBkh) – 2011-05-12 16:55:13

回答

4

我以前也用过hibernate。 ActiveRecord的方式与hibernate非常不同。你需要放下心灵,无论好坏。在java和Hibernate中,你经常拥有聚合根和对象图。通常情况下,对象图和代码库在某种程度上都比较小。我不知道你的具体情况,所以我会小心翼翼地行事,但我警告你要尝试适合ruby和rails,以符合你的java习惯。

您可以使用带有rspec的自定义目录以一种对您和您的团队有意义的方式进行组织。

#spec/queries/my_custom_search_spec.rb 

require 'spec_helper' 
describe MyModel do 
    it "should do this query and return X" do 
    subject.some_defined_scope_search.should == "something" 
    end 
end 

,你可能有子目录,由rspec的自动得到回升,像spec/models/account/..

该规范将自动被rake specrspec spec回升。我刚刚写了一个简单的例子,因为我不知道你的情况。你是用查询来定义范围还是定义专门的方法?

我强烈建议放弃固定装置(与插入相同 - 反模式,对我来说)为更可重构的东西,如工厂。我喜欢factory_girl。它让您的应用以更灵活的方式演变,IMO。

编辑: 加入我的spec_helper.rb具有用于启用/禁用自动清理

RSpec.configure do |config| 
    require 'database_cleaner' 
    config.add_setting :skip_database_clean 
    config.skip_database_clean = false 
    config.before(:suite) do 
    DatabaseCleaner.strategy = :truncation 
    end 

    config.before(:each) do 
    end 

    config.after(:each) do 
    MongoMapper.database.collections.each(&:remove) 
    DatabaseCleaner.clean unless config.skip_database_clean 
    end 

我添加变量skip_database_clean这样我可以启用/每规格后禁用autocleanup设置(每个“它”) 。

before :all do 
    @an_object = some_expensive_test_buildup 
    RSpec.configuration.skip_database_clean = true 
    end 
    after :all do 
    RSpec.configuration.skip_database_clean = false 
    DatabaseCleaner.clean 
    end 
+0

是的,我已经在使用工厂女孩了。我发现我需要制作3-4个记录以及它们的依赖关系,才能正确地测试查询以确保它们正在工作。因此,测试设置代码变得非常庞大,因为我可能需要创建一个小型数据库来使测试通过并测试所有查询可能性以确保查询逻辑正常工作。 – egervari 2011-05-10 09:05:35

+0

运行规格需要多长时间? 您可以在'before:all'中完成测试数据的构建,然后在数据上添加一堆查询规范。如果您激活了自动清理功能(如DatabaseCleaner),您必须禁用全局'before:each'。 – oma 2011-05-10 09:18:36

+0

实际上,将我的测试移动到新文件夹中似乎会导致rails无法清理干净。我需要在环境中的某个地方打开它吗? – egervari 2011-05-11 13:54:07

0

如果您使用普通导轨ORM,那么您不会创建查询,也不需要测试数据访问。

如果您确实开始编写自定义SQL查询,那么我建议您在执行查询后使用rspec并测试对象的行为。

+0

您将如何使用Rails ORM并且不会创建查询...?我不是在问我应该或不应该测试它们 - 我问“这些测试应该去哪里?”他们在模型规范中做什么?完全不同的规格?哪里?我知道如何测试它们 - 我在问哪里。 – egervari 2011-05-03 03:10:59

+0

如果您将模型定义为导轨预期,则不要编写查询。你只需:“@ account.purchases”,并返回该帐户的购买。你可以写一个规范,说明购买应该属于某个账户,但这就像我去的那样。 – 2011-05-03 13:10:13

+0

对于很长的对象图,这是一个很糟糕的做法Jesse。这不是真正的查询 - 你实际上是从数据库中删除数据。这太可怕了。如果你不得不加入20个表来获得你想要的数据,你真的会走对象图20次吗?如果每个集合中有100条记录,那么会有100条记录从数据库中抽出!不,做这件事的最好方法就是QUERY - 因此是个问题。 – egervari 2011-05-09 20:35:41

1

Rails使用阿雷尔生成你在Ruby代码通过Rails ActiveRecord关联的API定义了基于关系数据库查询的SQL(假设你使用的ActiveRecord作为ORM,它是默认的)。如果您认为可以改进自动生成的内容(可以在日志文件中看到),则可以编写自己的SQL。

通常,您将通过模型上的方法调用来调用这些查询(无论手动还是自动写入)。例如,@author.books@author.readers;这些可以体现一个连接的查询。

我不确定手写查询的问题,但生成的查询通常使用一旦完成构建的作用域即可在请求结果时实现。例如,@author.books.order('price').limit(10)。您可以定义自己的自定义范围。

我会在模型的单元测试中测试自定义查询或作用域的正确性,因为它们是模型工作不可或缺的部分。例如,@author.popular_books可能是您的模型中定义的自定义范围,您可以为您的Author模型编写单元测试,以确保它返回某些已知测试数据的预期结果。

+0

实质上,我认为你在正确的地方有你的测试。也许你可以写一些测试助手来减少代码的长度?看看Shoulda测试框架以获得助手的想法(您不需要实际使用它,但它确实有许多助手来执行常见的事情,如检查验证)。 – 2011-05-10 00:07:44

+0

这就是我目前的做法。当我需要进行多个连接时,编写这些作用域查询会变得非常痛苦,所以我需要在数据库中创建大量测试数据来验证查询是否正常工作。这经常会膨胀模型规格文件 – egervari 2011-05-10 02:21:51