1/ I have several complex yet largely independent models using rspec
to test internals and computation methods. I am about to tackle models
that have several ties to each other and to the “primitive”,
independent models.
What is the best practice for testing models with these
interdependencies? What would you recommend for Message? What about
Topic, which has_many Messages? Do I mock these? Use canonical data in
the code rather than use a fixture?
2/ Related to (1), I have not found much documentation about such
techniques. Pointers? Examples? Mentorship? Blogs?
3/ Has any documented how to run the debugger via rspec to help track
down errors?
On Tue, Sep 16, 2008 at 10:00 AM, Martin S. < [email protected]> wrote:
3/ Has any documented how to run the debugger via rspec to help track down
errors?
We TDD/BDD/Agile practitioners aren’t supposed to use a debugger, so
don’t
tell anyone I said this. But all I have to do (on a Mac system) is to
install the ruby-debug gem, then insert
require ‘ruby-debug’
debugger
at the point in my code where I want to break into the debugger. Then
running the specs via most any means (including autotest, but not
spec_server) will start up the debugger at that point. Frankly, though,
I’ll
often just stick in some p statements to show some data. Actually, I use
this little function:
def l &block
name = block.call
puts name + ’ = ’ + eval(name, block).inspect
end
which, when called like ‘l{‘foo’}’ prints 'foo = ’ followed by the value
of
foo.
But these are pretty brute-force techniques, so we’ll just keep it our
little secret.
On Tue, Sep 16, 2008 at 10:00 AM, Martin S. [email protected] wrote:
3/ Has any documented how to run the debugger via rspec to help track down
errors?
We TDD/BDD/Agile practitioners aren’t supposed to use a debugger,
Please pay no attention to that sort of bullshit
The idea is that TDD, practiced with discipline, should make you
depend less on a debugger. This is a good thing since debugging time
is impossible to estimate. But the idea that you’re not supposed to
use a debugger is religious hog-wash.
often just stick in some p statements to show some data. Actually, I use
But these are pretty brute-force techniques, so we’ll just keep it our
little secret.
The idea is that TDD, practiced with discipline, should make you
depend less on a debugger. This is a good thing since debugging time
is impossible to estimate. But the idea that you’re not supposed to
use a debugger is religious hog-wash.
Yeah - I use a debugger all the time, often using the following
snippets:
I’ll insert the following right inside the spec:
it “should do something or other” do
$debug = true
some_method.should == some_value
end
Then in the implementation, I’ll insert the following:
def some_method
require “ruby-debug”; debugger if $debug
…
end
This pops me right into the method. It’s very convenient.
But regarding the previous comments, I’m surprised at how few actually
use debuggers. As long as you are writing specs for anything you’ll
be debugging, you should be fine.
Just remember that unit testing started in smalltalk, which would automatically start a debugger when an example failed…
it’s a fairly common step for both. Your absolute best bet is going to peepcode.com and watching all the vids on speccing. it should give you
more than enough starting information about approach.
BTW - do any ‘proper’ tdd/bdd types here reccommend any specific books?
The idea is that TDD, practiced with discipline, should make you
depend less on a debugger. This is a good thing since debugging time
is impossible to estimate. But the idea that you’re not supposed to
use a debugger is religious hog-wash.
Indeed - which i counter with: i’m still pre proper tdd enough that
it’s faster than writing tests that i know are valid and making my
code bend entirely around it. It’s a fine mesh of both, i think. You
are right about it being hard to estimate - but i think that
estimation is as much to do with general experience as it is with the
type of task: a well experienced hacker will know to set aside a
number of hours for a difficult task (spiking) if they’re not sure of
the full requirement or the right approach.
I regard using the debugger as a bit of a smell. It often means my code
isn’t clear enough to just bench-step through. In a way, it’s like
commenting. Complicated code often needs comments and debugging. Code
should
avoid being complicated.
I also have found myself relying on the debugger and print statements
too
much, when a better approach is to take a step back and really ask
myself
what the problems could be. It’s so easy just to insert a breakpoint and
start examining variables, in the hopes that something will jump out at
me.
All that said, I don’t understand my coworkers who don’t know how to use
the
debugger (and who don’t use my l() function). I’ve always said that in
life,
there’s the fast hard way and the slow easy way. Learning to use tools
effectively is the fast hard way. It takes effort, just like sharpening
an
axe. But you end up cutting down a lot more trees.
The Smalltalk debugger, of course, is in a class by itself. When the
debugger comes across a missing method - say, because you wrote the test
before you wrote the method - it puts you - live! - in a skeleton of
that
method, complete with the actual passed parameters. You fill in the guts
and
continue on your way. Far too easy. No wonder it never caught on.
BTW - do any ‘proper’ tdd/bdd types here reccommend any specific
books?
The Michael Feathers book (Working with Legacy Code) is well regarded
on this list for teaching you how to write testable code, if that
helps. I don’t think there are any books out yet on BDD specifically,
although all that stuff was kind of inspired by Eric Evans’ book on
Domain Driven Design, as I understand it.
In case you wondered: The opinions expressed in this email are my own
and do not necessarily reflect the views of any former, current or
future employers of mine.
BTW - do any ‘proper’ tdd/bdd types here reccommend any specific books?
I’ve just started reading “Scripted GUI Testing with Ruby,” which has
sections on RSpec, ZenTest and StoryRunner. I haven’t read enough to
recommend it, though.
Pat M. contributed to the RSpec chapter in “The Rails Way,” and I
can
indeed recommend that.
The Feathers book is a classic, but I wouldn’t say it teaches BDD. As
the
title says, it’s about taking an existing codebase and making it
testable.
BTW - do any ‘proper’ tdd/bdd types here reccommend any specific books?
The Michael Feathers book (Working with Legacy Code) is well regarded on
this list for teaching you how to write testable code, if that helps. I
don’t think there are any books out yet on BDD specifically, although all
that stuff was kind of inspired by Eric Evans’ book on Domain Driven Design,
as I understand it.
Some, not all. The concept of Ubiquitous Language is definitely an
important part of BDD, but there are a few others as well.
We are very close to announcing a release date for our RSpec book
(Pragmatic Bookshelf), which will cover BDD at a high level, but
mostly focus directly on practical use of RSpec and friends. A BDD
slant, definitely, but not a BDD treatise.
I’ve heard rumors of other RSpec books in the works, as well as a BDD
book, but until their authors make formal announcements, they are just
rumors
In the mean time, there are a lot of great blog posts referenced from
this list.
What is the best practice for testing models with these interdependencies?
Can we all please stop talking about “best” practices? It always
depends. If people talk about best practices then others will be more
inclined to apply them without thinking.
What would you recommend for Message? What about Topic, which has_many
Messages? Do I mock these? Use canonical data in the code rather than use a
fixture?
“Testing a model” or “testing a relationship” doesn’t mean much (it
can mean anything). I recommend you focus your testing efforts on the
desired behaviour of your system, not its implementation. This is a
very central tenet of BDD.
If your Message class doesn’t have any behaviour (code in addition to
the relationships) there isn’t really much about it to test. You
should assume ActiveRecord works.
I suppose those relationships are there for a reason. Some other code
uses these relationships. What is that code? Start by testing that
code. This code is probably on the “outside” of your model, i.e. it
depends on your model. Typically a controller and/or a view - probably
both.
Nowadays I usually recommend people start by writing a test for the
system as seen from the outside. This is called “outside in” and is
what you’d use Cucumber or the story runner for. Or if you don’t use
it, at least write some kind of end to end test. Then, when you
discover edge cases, drop down to a lower level (specs that talk to
the model).
I have a feeling I might have confused you more than helped you. Maybe
you can explain a little more about what the system’s behaviour? It
would help set the context so we can recommend a good practice
I find the debugger helpful to step through the underlying Rails code
when I am perplexed about the (errant) operation of something. The
underworld is full of wonderful secrets. Plus, I do make mistakes and
misinterpret and the debugger lets me take a look around. I try to
avoid making bad smells; the debugger is like Harvey Keitel’s
character in Pulp Fiction.
What about my other questions? Directions on how to write tests when a
model has_many or belongs_to? When to mock? Pointers to examples would
be the cheap and easy answer – is there an open source application
with rspec tests?
Can we all please stop talking about “best” practices? It always
depends. If people talk about best practices then others will be more
inclined to apply them without thinking.
I prefer to call it the “Suggestion of a Bunch of Guys on a Project
called
‘Demeter’ That Is Useful to Keep in Mind in Many Situations”. But that’s
not
as catchy.
would be the cheap and easy answer – is there an open source
application with rspec tests?
Ultimately, it’s all about how comfortable you feel. Mocks will
always smell bad with rails’ associations because of the law of
demeter violations that it promotes. On the other hand, using real
objects and saving to a database can be slow, but at least they give
you some feel of the objects - that is, how they will actually be
used in a production system.
One thing that I’ve realized over the (2) years of testing that I’ve
done is that testing is just as much about accustoming you to see
relevant error message and their context as it is about getting a
suite green or anything else. When a real bug pops up when
integrating, or on staging, you’re almost immediately aware of it’s
place and cause. As I’ve replaced my test suite with mocks and stubs
I find that this is less and less true, and I have less and less
confidence that I’m shipping really solid software.
So, it’s always a tradeoff. Bend in the directly you feel more
comfortable.
Scott
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.