Just in case someone is curious, I've replaced ActiveRecord models with Sequel ones and my slowest example as reported by "rspec -d" got faster from about 0.5s to 0.2s.

That is awesome! :)

It seems AR is bloated...

As if this wasn't already amazing enough, my models seem much cleaner with Sequel than with AR.

Cheers,
Rodrigo.

Em 16-04-2012 14:17, Rodrigo Rosenfeld Rosas escreveu:
Em 16-04-2012 09:27, Rodrigo Rosenfeld Rosas escreveu:
Thank you David and Matt for your comments.

Indeed I had considered using FakeWeb but I thought that maybe there could be an easier way just to mock 'open' directly since I guess it would be faster to run.

With regards to the work around to overcome the issue with mocking AR so that I could speed up my tests I think that creating helpers in the model that will restrict the use of the AR API sounds like a good balance, but that wouldn't make my specific tests faster.

Here is why: my Model class shouldn't be created or updated by any other code in my application. So I'd just have to add a new method to the Model class that would be specific to this action and I'd need to write a "unit" test for this new method. I quoted "unit" because it is actually an integration test as it will touch the database or otherwise I wouldn't be able to upgrade Rails to a new version if I'm mocking some methods from AR and they change in a future version.

So I'd need to touch the database anyway and my 9 specs would still take almost a full second to run while this specific controller spec takes about 0.7s (up to 2s depending on my system load).

Well, actually, I guess RSpec has changed the way it measure spec runs since I last used it. I'm saying that because it will report me from 0.7 to 2s when I run "rspec path/to/my_controller_spec.rb", but if I run "rspec --profile" it will run the full suite about the same time and this specific controller action will take 0.38s.

Anyway, I don't see how I would create hundreds of specs and expect them to run in a few seconds and still have a reliable test suite. I mean, I want to feel safe if I'm upgrading to a newer Rails version even if it changed its AR API.

The only real improvements I can see for my tests running fasts without changing anything in the specs is to use something like Hydra so that I could use the full power of my 6-core processor.

Does RSpec has a built-in threaded option? I guess not because I don't think it would be much effective on CRuby because it would probably lock on database access (or maybe not, I don't know how the pg driver is implemented). For my particular application I suspect it is not cpu-heavy, but io-expensive instead. So maybe a multi-thread spec runner could improve its performance when running multiple specs.

Best,
Rodrigo.


After some more investigation I could find out why it is taking so much time for the spec to run. Even for a simple model, calling a single "Model.create! name: 'Model name'" will take almost 100ms. So, here is usually what happens:

root = FactoryGirl.create :model # 2 creates:
# section = Section.create! name: 'Section'
# root = Model.create! section: section, label: 'Label'
post 'action', parent_id: root.id # another Model creation in the controller alongside with 2 other creations of a has_many association

So, without counting any assertions just for creating all records so far about 400ms were already spent. There will also be about 2 more updates and 2 "delete" statements in this spec and that will complete about 540ms of total spec run time.

Another interesting fact is that for measuring this I've mocked the user and controller authentication related methods, but if I actually create the user the time for completing the spec will be about the same, even if in the logs it is reported to spend about 70ms for executing the insert in the user's table.

But I don't think it should take so much time for creating/updating those records. See the output of the logging, for example:

Completed 200 OK in 83ms (Views: 0.6ms | ActiveRecord: 14.9ms)

This is consistent with the individual timing for each query/insert statement including validations. Even so, the first 'post' method call in the spec takes about 100ms.

So, my question is, if AR and Views are taking about 16ms what else could be taking about 70ms?

This is also hard to profile since PostgreSQL will need more time for the first queries and will be much faster for subsequent ones... This means that running all specs will take much less time than if I run each spec separately and compare to the total time.

But I don't really think I'll be able to test this action faster. I need to check for all created records including associations and fields set by the before_validation and removed by after_save so that I can get confidence in the code. And since all of this should only happen through this action, it wouldn't matter if I moved lots of those checks to the "unit" test of my Model as the total time would remain the same. It would only make my specs harder to read with lots of mocks and stubbed methods in my controller spec.

I mean, that is ok, I don't aim in having single assertions per unit test. I just need to make sure things won't break in a future refactoring or requirement changes. And of course I'd like my tests to run faster, but my current understanding is that I can't get this test to run faster because it is testing a lot of code. Of course that an in-memory AR adapter could help me speeding up my tests but using mocks here won't give me any confidence on my code base.

Usually slow tests are not a problem when I'm working in some controller as I don't need to run the full suite. But when I change some model or library it would be great to run the full suite and I'm a bit worried if that will become super slow some time in the future.

But I think I'll start to worry about this when this future becomes present because there is no easy replacement that will allow my specs to run faster. I'll still be able to try Hydra before having to resort to mocks if things get really unsustainable.

But thank you very much for your input on the subject. I was just worried if I was doing something fundamentally wrong.

Cheers,
Rodrigo.
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users


_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to