How to structure my RSpec test folders, files and database?

Vincent Algayres

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.

Dave Schweisguth

Fully answering your question could fill and has filled books, so I can only outline an answer here.

Regarding creating objects to test,

  • db/seeds.rb isn't for test data, but for static data, not changed by users, that's required for the application to run, whether in development or testing or production. Common examples of this kind of data include country codes and user roles.

  • There are two general approaches to creating test data, fixtures and factories.

    • Fixtures are the out-of-the-box Rails method. They are created once when the test database is created. They're fast when you have many tests, because they're only created once at the beginning of the test suite. However, they warp tests because they encourage writing tests around existing fixtures, so I strongly recommend against them.
    • Factories are object creation utilities. You create the objects you need in each test and delete or roll them back at the end. Most Rails projects that use factories use FactoryGirl. That's what I recommend.

    Both approaches put object creation code in its own files in a different directory than your specs, which keeps it from junking up your spec files. If you search SO for "fixtures or factories" you'll find lots more discussion of both.

Your specs will be easier to understand if you put all of the important values, which in this case include dates and amounts, in the specs where they can be seen and compared to the results that you're asserting. (Otherwise you need to memorize the dates and the amounts in your test objects to understand the specs.) You could give the object creation methods in your test date and amount parameters. You might need less methods then. If you used FactoryGirl it might just be a question of specifying each object's created_at and amount attributes. Note also that Rails has methods like 1.day.from_now; if you create objects with dates specified that way you might not need timecop.

Regarding how to lay out RSpec specs in the filesystem, at the top level, just make the layout identical to that of your Rails app:

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
    ...
  ...

If your specs for a single class get too big, it's a sign that the class is too big. Find some pattern to break it up and test the pieces individually. If you really can't break up the class (a rare situation), turn the class's spec file into a directory of spec files, as I described in How to break down super long specs in RSpec?.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How can i hide my files and folders as they can be seen as "Index of /test/admin" on my server

From Dev

How to structure my unit test?

From Dev

Rspec - How to clean the database after each test

From Dev

Organizing files and folders structure

From Dev

guard and rspec - NOT liking my postgress :test credentials in database.yml

From Dev

Test database records with rspec

From Dev

Test database records with rspec

From Dev

How to writte rspec test to test that helper method is available in my controller?

From Dev

How to structure my angularjs app and test folder

From Dev

Moving files/folders to new structure

From Dev

How to test controllers import/export csv files actions in rspec?

From Dev

How do I match this result in RSpec for my Controller test

From Dev

How can I clean my database between erroneous rspec specs?

From Dev

How can two files in one of my folders have the same name?

From Dev

How to require Javascript files for testing in my RSpec/Capybara/Selenium tests?

From Dev

How to require Javascript files for testing in my RSpec/Capybara/Selenium tests?

From Dev

Why my rspec test fail?

From Dev

rspec test that a method's input is of a certain structure

From Dev

Test a Sinatra app with RSpec - "structure" of tests

From Dev

How to sort files into folders

From Dev

Copy files from folders and sub folders without preserving directory structure

From Dev

How to unzip a zip file containing folders and files in rails, while keeping the directory structure

From Dev

How to use Powershell to list duplicate files in a folder structure that exist in one of the folders

From Dev

How to delete files and folders but keep directory structure and leave behind a empty file instead of file itself?

From Dev

how can i see my sqlite database structure in eclipse IDE

From Dev

How to mock a database table structure in my C# code

From Dev

How to set the permissions on all files and folders on my NAS drive using my Mac

From Dev

How to copy files from archive to my system, following the directory structure?

From Dev

Angularjs, how to structure my code across multiple files

Related Related

  1. 1

    How can i hide my files and folders as they can be seen as "Index of /test/admin" on my server

  2. 2

    How to structure my unit test?

  3. 3

    Rspec - How to clean the database after each test

  4. 4

    Organizing files and folders structure

  5. 5

    guard and rspec - NOT liking my postgress :test credentials in database.yml

  6. 6

    Test database records with rspec

  7. 7

    Test database records with rspec

  8. 8

    How to writte rspec test to test that helper method is available in my controller?

  9. 9

    How to structure my angularjs app and test folder

  10. 10

    Moving files/folders to new structure

  11. 11

    How to test controllers import/export csv files actions in rspec?

  12. 12

    How do I match this result in RSpec for my Controller test

  13. 13

    How can I clean my database between erroneous rspec specs?

  14. 14

    How can two files in one of my folders have the same name?

  15. 15

    How to require Javascript files for testing in my RSpec/Capybara/Selenium tests?

  16. 16

    How to require Javascript files for testing in my RSpec/Capybara/Selenium tests?

  17. 17

    Why my rspec test fail?

  18. 18

    rspec test that a method's input is of a certain structure

  19. 19

    Test a Sinatra app with RSpec - "structure" of tests

  20. 20

    How to sort files into folders

  21. 21

    Copy files from folders and sub folders without preserving directory structure

  22. 22

    How to unzip a zip file containing folders and files in rails, while keeping the directory structure

  23. 23

    How to use Powershell to list duplicate files in a folder structure that exist in one of the folders

  24. 24

    How to delete files and folders but keep directory structure and leave behind a empty file instead of file itself?

  25. 25

    how can i see my sqlite database structure in eclipse IDE

  26. 26

    How to mock a database table structure in my C# code

  27. 27

    How to set the permissions on all files and folders on my NAS drive using my Mac

  28. 28

    How to copy files from archive to my system, following the directory structure?

  29. 29

    Angularjs, how to structure my code across multiple files

HotTag

Archive