Things I wish I knew when beginning testing

The following statements will save you lots of time, and most
importantly, develop a better application when beginning Rails
development.

Fixtures are faster, but conciseness is more important. Use factories
(Machinist or Factory girl). Don't worry about the speed of your test/
spec suite. Use autotest or autospec.
--- I started out with fixtures, then switched to factories. Lost
patience and switched back to fixtures. Now back to factories for
maintainability and conciseness.

Do not mock everything to make your test/spec suite "database
independent". Your tests are SUPPOSED to break when you change code in
your model or controller. Mocking everything will not allow this, and
will give you the feeling that you're developing a second application
in your test/spec suite.
--- Yes, it will speed up your tests/specs, but once again,
conciseness is more important.

Your test framework does not matter. Test/unit, Shoulda, RSpec all
produce the same outcome. Choose by what syntax you feel comfortable
with. For every great developer that uses test/unit, there is a great
developer using RSpec.
--- For whatever reason I cannot explain, RSpec feels most comfortable
to me. I started with test/unit, switched to RSpec, then shoulda, then
test/unit, and now back to RSpec. I will not switch again.

Test the entire stack. Do not just test models. Test/spec models,
controllers, and use integration tests/specs. This will give you
confidence when developing and literally makes your work 1000 times
less stressful. Yes, it takes more time, but it is the ONLY way to
develop a reliable app that works.
--- I started out just testing models. This does not catch view
errors, and my users paid for it.

If TDD or BDD does not fit your brain, don't do it. DHH doesn't do it,
and you don't have to either. This is no excuse for not testing
everything though.
--- For me, TDD/BDD does not let me test/spec comfortably. I tried
both ways, and my code always turns out better when NOT using TDD/BDD.
I support the philosophy, but it is not "necessary". Some people will
say I am "doing it wrong", but if the end outcome is exactly what I
want, why does it matter how I got there?

If I had known these things when beginning, I would have saved
countless hours trying to follow the "one golden path" that does not
exist. I hope this helps.

Thanks, but it’s too late :wink: Needed that advice a year ago. Until a few days back I had no idea how fun testing your app is. Love cucumber and the rest. It’s a good feeling when you know that you app is working well cause of all the tests you’re doing.

What’s also nice are the screencasts like peepcode.com, pragprog.com, bddcasts.com and teachmetocode.com etc. The community is just awesome.

Chris

than you iam iranin ican not speek enghlis well &iwrith not hard fram halptime wery happiy maryam

Test the entire stack. Do not just test models. Test/spec models,
controllers, and use integration tests/specs. This will give you
confidence when developing and literally makes your work 1000 times
less stressful. Yes, it takes more time, but it is the ONLY way to
develop a reliable app that works.
--- I started out just testing models. This does not catch view
errors, and my users paid for it.

Selenium is great for this, it even tests your javascripts. Things I
haven't to test with selenium is file-uploads and swf-movies. There
are hacks to test file-uploads, but I rather do controller tests for
those.

What’s also important is refactoring (the third step in red/green/refactor). There a lot of real geeky tools like:

  • flog

  • reek

  • rcov

  • roodi

  • heckle

Cheers,

Chris

Thanks for posting this -- it's some interesting food for thought.

Do not mock everything to make your test/spec suite "database
independent". Your tests are SUPPOSED to break when you change code in
your model or controller. Mocking everything will not allow this, and
will give you the feeling that you're developing a second application
in your test/spec suite.
--- Yes, it will speed up your tests/specs, but once again,
conciseness is more important.

I think this point is debatable though. The point of mocking models
in your tests is to allow the tests to run in complete isolation.
e.g., there's no reason for your Post model tests to break when you
add a new required field to your User model. Your point is valid for
integration and other high-level tests, but unit testing is equally
important in my mind and it certainly benefits from mocking.

Jeff

Jeff,

Take the opposite of your scenario. Let's say you remove a column from
the User model......your tests still pass if its mocked. Do that a
couple times and you have cruft all over the application. That right
there gives me a uncomfortable feeling.....like I'm not really testing
my MY models.

That's exactly my point! The unit tests for the Post model should be
blissfully ignorant of any and all changes to the User model. My
intent in unit testing a model is to simply verify that the behavior
stated actually occurs, *presuming that all the external factors
happen as they should.* If I have some code in the Post model that
sets a published flag only if the user is a moderator, I would rather
just say mock_model(User, :moderator => true) than go through the
process of building a moderator User model, handling validations,
required associations, etc. If a future change removed the moderator
flag from the User, then the tests I've written for the Post model
still say that the model works as it's written -- it's just that the
User no longer conforms the the Post's expectations. Thus, I expect
damaging changes to the User model not to show up in my Post unit
tests, but in some various high-level integration tests where I'm
actually observing that the interactions between models go as planned.

I agree that mocking can leave your tests a bit crufty unless you're
very skilled at mocking up front (which I definitely am not :)).
However, in my experience, when I start working with unit tests for
complex models without mocks, I find myself spending too much time
just maintaining the tests for the changes occurring in the associated
models. I find the overhead of handling mocks preferable to keeping
up with changes in other models.

Mocking is something I've spent an inordinate amount of time
considering, and I have come to terms with the pros (complete
isolation) and cons (test management overhead). I've also come to the
conclusion that this is very much like the TDD/BDD/EDD/whatever flavor
is popular argument -- there's some substance to the differences, but
at the end of the day it's a matter of personal taste.

Cheers!
Jeff