I have been developing in RoR for more than a year now, but I'm just starting to use tests, using RSpec.
For standard model/controller tests, I usually don't have any problem, but the issue is that I want to test some complicated functional processes, and don’t really know how to structure my testing folders/files/database.
Here is a basic structure for my application:
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
The main issue is that I want to simulate the lifecycle of my object, meaning:
Instantiating customers and wallets which will be used for all the tests (without reinitializing)
Simulating the time flow, creating and updating multiple orders/invoice objects and some invoice_summaries.
For the creation and update of the orders/invoices/invoice_summaries, I would like to have methods like
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
I’ve already found the gem Timecop for simulating the time flow. Hence, I would like to have an easy to understand final test that looks like
# 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
Does anyone already have such tests? Are there good practices for the structuring of object factories, writing tests and so on?
For example, I've been told that a good idea would be to put the Customer/Wallet creation in a db/seed.rb file, but I don't really know what to do with it afterwards.