Live data from Hacker News

Speed Up Your Rails Specs

blog.originate.com

11–13 of 13 posts

Re: Speed Up Your Rails Specs

#11
I have a massive, and probably not entirely proportionate, negative reaction to constructor injection. It's in my mind the ultimate example of making your code more complex in service of your tests.

An approach that I've used recently (which is similar enough to parameter-style injection, is to use `class_attribute` at the top of a class to call out dependencies and explicitly provide a default value - so that consumers of your class don't need to know what exactly a WidgetFactory is supposed to be:

    class Foo
      class_attribute :some_service
      self.some_service = SomeService.new
    end
A nice advantage of this approach is that you can provide a different implementation of some_service on an individual instance of a class, which helps restore your code to a sane state when you're done with an individual test, like so:

    describe Foo
      subject(:foo) { Foo.new }
      before { foo.some_service = double(SomeService).as_null_object }
    end
On top of that, though, I think calling out dependencies really only makes sense when that dependency involves something external to the codebase itself, or is otherwise secondary to the main purpose of the class. So stub out a repository, or a logger to your hearts content - but there's little utility in stubbing out Widget in a WidgetBuilder class IMO.

Re: Speed Up Your Rails Specs

#12

speed up by 10? Move to python. Speed up by 100? Move to Go. Speed up by 1000? Move to C++.

Note: Ruby and Python have pretty nearly identical performance for most workloads these days. Other than that, it's an illustrative point - if what you really care about is execution speed, you should pick a language that focuses on it more. It's interesting that increased developer productivity is the classic trade-off for decreased execution speed, but that all these "my tests are slow" issues are basically decreas…

This is not strictly about Ruby vs Python. Having used Pyramid (+SQLAlchemy) and Rails, I think the former is plenty fast enough such that no user cares about silly optimization, while the latter is the opposite.

Loading the Rails environment is just too slow, thus you need a preloader such as Zeus or Spring. And then you need something like Guard to make unit testing semi-bearable. But running the whole test suite would still be too slow, so you need parallel_tests to spread the tests across multiple cores (and multiple databases). And finally you drink the PORO kool-aid and start decoupling your codebase from Rails stuffs, and end up debating with DHH in HN.

Re: Speed Up Your Rails Specs

#13
post #12

Earlier quoted context omitted.

Note: Ruby and Python have pretty nearly identical performance for most workloads these days. Other than that, it's an illustrative point - if what you really care about is execution speed, you should pick a language that focuses on it more. It's interesting that increased developer productivity is the classic trade-off for decreased execution speed, but that all these "my tests are slow" issues are basically decreas…

This is not strictly about Ruby vs Python. Having used Pyramid (+SQLAlchemy) and Rails, I think the former is plenty fast enough such that no user cares about silly optimization, while the latter is the opposite. Loading the Rails environment is just too slow, thus you need a preloader such as Zeus or Spring. And then you need something like Guard to make unit testing semi-bearable. But running the whole test suite w…

Great comment, I agree wholeheartedly, it's a mess. I do think using PORO's and not arguing with DHH on HN is one reasonable option that you missed though.
Post reply on HN