Ruby on rails 如何构造我的RSpec测试文件夹、文件和数据库?
我已经在RoR中开发了一年多了,但我刚刚开始使用测试,使用RSpec 对于标准模型/控制器测试,我通常没有任何问题,但问题是我想测试一些复杂的功能过程,并且不知道如何构造测试文件夹/文件/数据库 以下是我的应用程序的基本结构:Ruby on rails 如何构造我的RSpec测试文件夹、文件和数据库?,ruby-on-rails,ruby,rspec,rspec-rails,functional-testing,Ruby On Rails,Ruby,Rspec,Rspec Rails,Functional Testing,我已经在RoR中开发了一年多了,但我刚刚开始使用测试,使用RSpec 对于标准模型/控制器测试,我通常没有任何问题,但问题是我想测试一些复杂的功能过程,并且不知道如何构造测试文件夹/文件/数据库 以下是我的应用程序的基本结构: class Customer has_one :wallet has_many :orders has_many :invoices, through: :orders has_many :invoice_summaries end cla
class Customer
has_one :wallet
has_many :orders
has_many :invoices, through: :orders
has_many :invoice_summaries
end
class Wallet
belongs_to :customer
end
class Order
has_one :invoice
belongs_to :customer
end
class Invoice
belongs_to :order
belongs_to :invoice_summary
end
class InvoiceSummary
belongs_to :customer
has_many :invoices
end
主要问题是我想模拟对象的生命周期,这意味着:
- 实例化将用于所有测试的客户和钱包(无需重新初始化)
- 模拟时间流,创建和更新多个订单/发票对象和一些发票摘要
def create_order_1
# code specific to create my first order, return the created order
end
def create_order_2
# code specific to create my second order, return the created order
end
.
.
.
def create_order_n
# code specific to create my n-th order, return the created order
end
def bill_order(order_to_bill)
# generic code to do the billing of the order passed as parameter
end
def cancel_order(order_to_cancel)
# generic code to cancel the order passed as parameter
end
我已经找到了模拟时间流的宝石。因此,我希望有一个易于理解的最终测试
# Code for the initialization of customers and wallets object
describe "Wallet should be equal to 0 after first day" do
Timecop.freeze(Time.new(2015,7,1))
first_request = create_request_1
first_request.customer.wallet.value.should? == 0
end
describe "Wallet should be equal to -30 after second day" do
Timecop.freeze(Time.new(2015,7,2))
bill_order(first_request)
second_order = create_order_2
first_request.customer.wallet.value.should? == -30
end
describe "Wallet should be equal to -20 after third day" do
Timecop.freeze(Time.new(2015,7,3))
bill_order(second_request)
cancel_order(first_request)
first_request.customer.wallet.value.should? == -20
end
describe "Three first day invoice_summary should have 3 invoices" do
Timecop.freeze(Time.new(2015,7,4))
invoice_summary = InvoiceSummary.create(
begin_date: Date.new(2015,7,1),
end_date: Date.new(2015, 7,3)
) # real InvoiceSummary method
invoice_summary.invoices.count.should? == 3
end
有人已经做过这样的测试吗?在构建对象工厂、编写测试等方面是否有良好的实践
例如,有人告诉我,一个好主意是将客户/钱包创建放在db/seed.rb文件中,但我真的不知道以后如何处理它。您应该使用它来完成任务。按照文档中的说明进行配置,然后按如下方式使用:
# factories.rb
factory :order do
end
# your spec
first_order = create(:order, ...) # configure parameters of order in-place
或者让特定工厂处理不同类型的请求:
# factories.rb
factory :expensive_order, class: Order do
amount 999 # have 'amount' field of Order be equal to 999
end
# your spec
first_order = create(:expensive_order)
您可以让FactoryGirl自动处理您的关联:
factory :order do
association :user # automatically create User association
end
您所描述的正是FactoryGirl的开发人员想要解决的问题。完全回答您的问题可能会让书充满内容,因此我只能在这里概述一个答案 关于创建要测试的对象
- db/seeds.rb不是用于测试数据,而是用于静态数据,不由用户更改,这是应用程序运行所必需的,无论是在开发、测试还是生产中。此类数据的常见示例包括国家代码和用户角色
- 创建测试数据通常有两种方法:夹具和工厂
- 夹具是开箱即用的导轨方法。它们在创建测试数据库时创建一次。当您有许多测试时,它们的速度很快,因为它们只在测试套件开始时创建一次。但是,它们会扭曲测试,因为它们鼓励围绕现有装置编写测试,所以我强烈建议不要使用它们
- 工厂是对象创建实用程序。您可以在每次测试中创建所需的对象,并在测试结束时删除或回滚这些对象。大多数使用工厂的Rails项目都使用FactoryGirl。这是我的建议
date
和amount
参数中给出对象创建方法。那么您可能需要更少的方法。如果使用FactoryGirl,可能只是指定每个对象在处创建的和数量
属性的问题。还要注意,Rails有类似于1.day.from_now
的方法;如果以这种方式创建具有指定日期的对象,则可能不需要timecop
关于如何在文件系统中布局RSpec规范,在顶层,只需使布局与Rails应用程序的布局相同:
app/
controllers/
bars_controller.rb
foos_controller.rb
models/
bar.rb
foo.rb
...
...
spec/
controllers/
bars_controller_spec.rb
foos_controller_spec.rb
...
models/
bar_spec.rb
foo_spec.rb
...
...
如果单个类的规格太大,则表明该类太大。找到一些模式,将其分解,并单独测试。如果您真的无法分解类(这种情况很少见),请将类的spec文件转换为spec文件目录,如我在中所述。@HunterStevens我认为您的编辑是错误的,因为您删除了有关订单的一些逻辑<代码>定义创建订单;结束
不同于def create_order_1;结束
def创建订单2;结束
因为@vincent想表达做两件完全不同的事情的需要。在像这样编辑之前,你应该小心…@Erowlin请回滚我的编辑。我正试图清理一个很长的帖子。抱歉,下次小心点;)。顺便说一句,谢谢你的编辑,它是从一个良好的意图开始的!更多详细信息。