What's wrong with Rspec, FactoryGirl and real sample data? - ruby-on-rails

I've been leaning some of RoR, and when I got to TDD, stuff started to get more complicated. At some point of my App, I thought it would be better to run my tests over the real data.
Real Data vs Sample Data
Searching the web, I found that tests were not meant to run over real data, but over sample data. But yet I couldn't agree with that.
Let's supose my app had an Alias System. So when you access a random url it figures out what that fragment wants and redirects to the proper canonical url. And let's add that an alias dictionary is stored in some models. How would we test agains that dictionary? Hard code spec files for every alias/keyword?
Sticking with real data
The first two things I've realized, yet very unsurely, is:
Rspec testing environment wouldn't access development model's data.
FactoryGirl rules over my testing database, so it's not my option to populate it.
The best solution I could figure out, as the complete newbie I am, is that I could create some classes in spec/support folder and call them inside my factories so as to get that real data. Those classes have a short sample of my real database info, nested, and so my test can go 'real'.
What can pros around suggest to improve it?

I think you may want to look into building a seeds.rb file to populate your databases. This is usually used to initialize the development database so it can be used in your app (and queried in the rails console), but you can use it to seed your test database as described in this answer.

You certainly should not use your development database for testing. You can either seed the test database, or create factories that reflect various scenarios.
FactoryGirl rules over my testing database, so it's not my option to populate it.
You can use more than one factory to represent a business entity, depending on the scenario under test. FactoryGirl makes this easy by allowing you to nest factories. You can define a factory with a basic set of valid attributes and use that in unit tests. For integration (feature) tests, you can use a nested factory that expands on the basic attributes to implement a particular scenario. You can have as many variations of these implementation-specific factories as you need.

Related

Create fake data to use as tutorial

I want to create fake usage of my app, as a tutorial.
In order to do so, I need to create fake data (with the same structure and association in real data) to send to my templates, so it renders the same view when my users will have when using the app.
But unfortunately, I didn't find an easy way to do that, except hard coding the examples (fake usage) as a separate view, that looks like the generated view with true data. But this is not useful when you have to change the template, one day or another.
And, mixing true data with fake ones in the database (and then retrieving only fake data when needed) doesn't seem to be a good idea.
Do you have an idea or a gem to suggest?
One option to consider is to use a factory gem (such as factory_girl) or similar (I personally like machinist) and then create some form of script that initializes objects in the test environment.
This may not be the intended or ideal use for a test environment, but you'd be able to utilize your app in a non-production environment with fake data, and allows you to keep data separate from real and/or development data.
The only "gotcha" I can think of is that you'll want to ensure that any automatic testing gem (such as rspec) drops the test database before your tests run. If you don't, you could see errors in your tests due to data already existing in the database.

Cleanly Setting up multiple models in FactoryGirl for a test/spec

I have been picking up on Rails best practices and learning to write good tests for my rails application.
I am using rspec + FactoryGirl to test at the moment.
For a while I was writing basic model and controller specs which usually required to set up only a couple of models and associations.
Now I have a Model with a complex algorithm which does a lot of calculations based on different models.
To test this method, I almost need all the models of my app to exists in test database with all associated relationships built between them.
Now things are getting overwhelming. I need to keep track if all factories are correctly referencing each other. Also I need to verify if all factories have been created properly.
Also a lot of FactoryGirl.create(:model) calls in my before(:each) method.
I have a feeling that I am not doing things right. What is the best way to go about this situation? Most books and examples only cover only the very basic cases.
Any pointers ideas and approches are welcomed.(Hope this question is not too wide in scope)
Example:
My application has multiple projects. Each project has_many indexes , companies and mastertags. Each company has_many channels. Every channel has_many channel_tag_weights across different mastertags. Also every channel has_many Rawdatas.
This could be an example of a minimum model setup required.
I wrote a gem for this called stepford.
In your gemfile:
group :test do
gem 'stepford'
#...
end
Then bundle install.
Back up your factories.rb or existing multiple files containing factories. In fact, you need to move them out of the way because if it loads other factories, that can interfere.
Then: bundle exec stepford factories --path spec (if want to put factories.rb in the spec dir- there are other options to create a factory per model, etc. though).
We had problems with dependencies that needed to be created where there were foreign key constraints. In the process, I wrote the modelist gem that can help identify circular dependencies, which you might want to check out and run if you are working with legacy data. And Stepford's deep creation methods get around these issues. But, we've started to steer away from using the deep_* methods of Stepford, even though we still use it a little. It is just better to be specific about what you are doing and use factory girl directly, even though it can make test code more brittle and overly-complicated looking.
You could also look at fixtures, or machinist. It really just depends on what you need.
If you need to actually create all of the code for the models, that is a different problem. I wrote a script to generate models for the local legacy schema (which was quite large), and it did help, but it took months of iterative work. The thing is that the schema itself is not (necessarily) the definitive description of the associations or setup in the models. To give you an idea of what I'm talking about, I wrote a number of gems to assist with some of the things that legacy apps, etc. were doing/had done that we had to deal with like undeletable, activerecord-define_nils, mark_only, activerecord-custom_timestamps, activerecord-native_db_types_override, and some others in earlier attempts. And we use some great gems that already existed like composite_primary_keys and foreigner.
Some other things we grappled with was using of MTI (multiple table inheritance), which despite a few gems out there that try to help, we ended up handling it ourselves in our models via hooks, etc. And we merged some schemas (not something to take lightly, but the divisions weren't necessary, and apartment, second_base and similar gems would be adding to the complexity, not even considering inability to join, use normal queries).
Please note: in our case we had a lot of tables. If you don't have quite as many, you still might use Stepford to maybe make the first creation of factories a little easier, but then I think you will be ok.
Whenever I get into this type of situation, I try to make sure that all of my FactoryGirl models take advantage of FactoryGirl's built in association methods:
https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations
That way the associated models that are required in order for a single model to validate properly are present. FactoryGirl will go through the process of populating your database with the extra test data.
Because you are using has_many associations, you will want to study the after(:create) method of the factory definition in order to set up your associations properly. This will also allow you to create definitions specific to these deeply integrated specs, and keep simpler factories independent for the simpler specs.
If you are testing only a method, that is unit testing.
I don't think you need to setup too many things.
A method has input and output, you just feed it with examples of inputs created by you manually, and expect it to generate right output.
If a method has too much things to concern, you can split it into several methods, and unit testing each one.
When times for integration testing, the whole environment should be setup. And yes, you need to prepare all the factories needed.

Strategies for Rails development/test development with complex legacy schema

When developing a Rails app with a legacy schema that is in-use by an existing application, if tables have NOT NULL constraints on foreign id columns throughout the schema, in order to create/save models for tests, models need to exist for those associations, and their associations, etc. So, it isn't an easy as just creating one model at a time as you need it and testing with it.
As far as testing goes, this seems to be a problem if you are using FactoryGirl and want to create and save model instances to return from controllers, etc. when all of the association dependencies are involved. Another option is to mock, but mocking can be a little more time consuming and it doesn't allow you to do integration testing as easily. Another is to use fixtures, but those are time consuming and brittle. Another is to pre-populate the test database with production data, but that doesn't solve the need for factories, etc./known data to expect in tests, and Rails usually expects to start with a clean DB for the test environment.
What strategies for developing models, tests, etc. do you use when you have an existing complex schema that you are bolting a Rails app onto- not just for reading data, but also writing to the existing schema that is in use by an existing production application? (i.e. the "rebuild the ship while at sea" problem)
When we first started out on this problem, I was looking for something that could autogenerate models from the existing schema. I found Dr. Nic's magic model generator, but it only stated that worked in Rails 2.x. I got a Rails 2.x environment running (forget the specific version it worked in) but it didn't seem to help much, so I wrote a script to generate our models. However, when we started development we then had a load of models, so we started to try to move out the ones we didn't need, then needed to comment out associations to models that were no longer there, but some of those were required/NOT NULL foreign keys, so we're now having to move them back in and uncomment those more than we thought we would.
We did write and uncover some things that were helpful during the process, not all of which we've used, but they might be helpful to others:
https://github.com/influitive/apartment
https://github.com/karledurante/secondbase
https://github.com/drnic/composite_primary_keys
https://github.com/garysweaver/activerecord-define_nils
https://github.com/garysweaver/activerecord-native_db_types_override
https://github.com/garysweaver/modelist
https://github.com/garysweaver/stepford
https://github.com/garysweaver/structure_sql_to_migration
As for test data setup, I started writing a tool to automate the development of FactoryGirl factories called Stepford and wrote Modelist to help us test models, resolve circular dependencies, and identify model dependencies, so we don't have to include all automatically generated models.
So far really, the only answer I've come up with and have heard other say also is that rebuilding an existing application, even piecemeal, with different technologies is difficult, slow, and error-prone.

What are best practices to handle database data in 'test' mode?

I am using Ruby on Rails 3.2.2, cucumber-rails-1.3.0, rspec-rails-2.8.1 and capybara-1.1.2. I have this problem but I started thinking that maybe I'm doing something wrong... mostly about seeding data in the test database for testing purposes. Specifically, my issue is related to how to properly manage data in the test database when I have to test my application.
My doubt is: By seeding data (For Your Information: I use the ROOT_PATH/db/seed.rb file to inject that data) in the test database I'm doing things as they should be done? That is, how should I populate the test database since the data in that database* is required in order to make to properly work my application for testing purposes? Should I populate the test database at all?
In other words, what are best practices to handle database data in test mode (in my case)? And, generally speaking, how the situation should be handled?
***** For example, in order to work my application requires at least data related to an "anonymous" user, to "basic" articles, to "basic" article categories, etc.
You should use one of the following:
Fixtures. See corresponding Rails documentation
Factories. The most popular tool to created/manage factories is FactoryGirl. IMHO that's the best solution.
Make sure data is seeded into test database. See this StackOverflow question.
I had a similar problem, association made it necessary to have a bit of seed data:
Factories will make your tests really slow, they are perfectly OK for single objects, but not for a lot of seed data that has to be created for each test
Fixture Builder - http://github.com/rdy/fixture_builder
I created a bunch of fixtures and just load them from the DB for each test, cut my test time down by 40%. You can also load the seeds file instead.
But be careful, deleting or updating records will create unwanted side effects. Use factories for those specs.
Mock and Stub everything so that your tests rarely touch the DB.
This has become very unpopular, you will eventually get passing specs that don't pick up on your actual errors.

Rails RSpec, how does it apply in such a case?

i'm daily in the process of learning new things about Rails (started learning 2 and now migrating to 3 concepts). As a project with Rails, i'm coding a browser game. Till now, i've been using fixtures to load data to my database and i've creating a custom task to recreate the db, load fixtures etc every time i need to. I have to say that i like this approach because i can easily define my monsters with weapons, bonuses etc through active record associations in features.
However, i see that people use a testing environment like RSpec for that kind of things. Although i see that RSpec is used as a language to define proper behaviour, i don't clearly see how it could help me. But since i like to do things the correct way, i'm pretty sure that there is much more for me to understand and read about it.
Therefore, i would like to ask for a solid example of how RSpec could be helpful. For instance, let's say that a user creates an alliance. Through my code, i'm checking whether this user already has an alliance, whether an alliance with that name exists, whether he has the money to create this alliance and more. Where would RSpec fit here ? What would a nice usage example be ?
Moreover, is fixtures done using RSpec in another way ?
I already know that Rails has many great programmer conveniences and i would like to harvest this one as well. But i'm still ignorant about RSpec. That is why i would appreciate some useful insight. Thank you :)
Rspec is a testing framework. It allows you to write automated pieces of code that verify that your code is actually working. For example, you could write a test to make sure that no two alliances have the same name:
describe Alliance do
it 'should not have the same name as another alliance' do
first = Alliance.create :name => "Test Name"
second = Alliance.build :name => "Test Name"
second.should_not be_valid
end
end
This code would then verify that no two alliances can have the same name - it's a way of testing that your code is actually working.
Fixtures, Factories, Mocks and Stubs are all ways of creating temporary data that can be used in tests. RSpec can use Fixtures, but it doesn't require them either. If you want to load test data into your database you can do this in whichever method best suits your needs to perform tests.
Some other testing frameworks are Cucumber, TestUnit, MiniTest and Shoulda. You should be using one already to write tests for your code. You can also read up on the others to find out which framework best suits your needs.

Resources