IMHO It would be a shame if we missed the opportunity to ask them to talk about "mocks returning mocks returning mocks" and the important points so effectively described by @garybernhardt in "Test Isolation Is About Avoiding Mocks" https://www.destroyallsoftware.com/blog/2014/test-isolation-is-about-avoiding-mocks.
What I want to say is this: if someone gives for granted that he does /not/ want his models to depend directly on the database; and someone else gives for granted that he wants to use ActiveRecord, then when they evaluate their results with TDD it's quite likely that they will experience very different results. At the very least, the kind of difficulties they encounter will be vastly different. When they discuss, they would probably find it more productive to start the discussion from this different worldview, rather than from TDD itself.
@garybernhardt That post is the first time that I've ever managed to directly explain the design pressure of isolation in detail. It only took seven years.
...What we have here is a three class system.
These three classes integrate in production, but in test we are removing two of the dependencies, replacing them with stubs and mocks, giving us this as our testing world.
So everything is nice and isolated.
There are several good reasons to do this. Several very big benefits that come out of it, but there is also one really terrible thing that happens when you do this.
So let's go through those.
(1) This allows you to do real test-driven design: looking at your tests, seeing that you have mocked six things and two of them are mocked three levels deep, this tells you that your design is not so good for this class.
So it gives you a form of feedback that you can't get without isolated tests. At least I don't know how to.
(2) It allows you to do outside in TDD, where you actually build the high-level pieces before the low level pieces exist. So we could TDD the sweeper using the User, using the UserMailer, before those classes exist, because we are just stubbing them out anyway. Then when we want to write the user class for real, we can look at what we stubbed and that tells us the interfaces it needs.
(3) And finally, this gives you very fast tests, it is one of the main things in the whole fast Rails tests 'meme', or, I don't want to call it a movement, people getting really excited about fast tests in the Rails world.
And we are talking about the difference between a 200 ms time from hitting return to seeing the prompt back, versus a 30 second time to run a very small test. It is a very big difference when you are really isolating.
So these are all very good things that you want, but they are balanced out by a very bad thing, and that bad thing is that in test, you are running against a stub and a mock, and in production you are running against real classes, and if you don't stub the boundaries correctly, you rtests will pass and the production system will be wrong. And this is such a big problem that for most people I think overshadows all those benefits. Even if you explain them to them , they are going to look at hits problem and say it is not worth it.
Now, there have been attempts to fix this. Various approaches to solve this problem in one way or another
So that is all background, this is how I came to the ideas that I am going to talk about for the rest of this talk. This has been a large focus of my s/w development career for the last five years is, isolated testing and thinking about how to do it well...
Hi Matteo,thanks for your input.>It seems to me that the post by Gary Bernhardt is very much concerned about "how do I test drive ActiveRecord objects"I believe he is making a more general point.Here is what he tweeted the day he wrote the blog post:@garybernhardt That post is the first time that I've ever managed to directly explain the design pressure of isolation in detail. It only took seven years.
When I read that method, I think that the method has deep knowledge about the /objects/ structure. The fact that it also has deep knowledge about the DB is a consequence of AR. The overarching theme of his piece is "isolation", by which he means "isolation from the DB". He spends a lot of energy to undo AR's primary strength, that is, having objects that are automatic, transparent reflections of the DB schema.def average_transaction_amount(user)purchases = user.purchasestotal = purchases.map(&:transaction).map(&:amount).inject(&:+)total / purchases.countendThis method has deep knowledge about the database's structure
You received this message because you are subscribed to the Google Groups "software_craftsmanship" group.
To unsubscribe from this group and stop receiving emails from it, send an email to software_craftsma...@googlegroups.com.
To post to this group, send email to software_cr...@googlegroups.com.
Visit this group at http://groups.google.com/group/software_craftsmanship.
For more options, visit https://groups.google.com/d/optout.