Rails went from fun ActiveRecord magic tricks to a world of 'TEST
FAILED.' As a beginning Rails developer it has really taken all the fun
out of RoR development. Is TDD so much better than writing methods and
testing using a combination of the application interface and Navicat to
check the database? Because I hate it.
--
Posted via http://www.ruby-forum.com/.
It is a lot of extra work. The # of lines of code usually outnumber
my actual app. But, it's better than having a team of monkeys
clicking on every single link in my app everytime I deploy.
--
Rick Olson
http://weblog.techno-weenie.net
http://mephistoblog.com
> Rails went from fun ActiveRecord magic tricks to a world of 'TEST
> FAILED.' As a beginning Rails developer it has really taken all
> the fun
> out of RoR development.
Well, TDD *is* a choice. If it's bad for you, exercise free will!
> Is TDD so much better than writing methods and
> testing using a combination of the application interface and
> Navicat to
> check the database?
Yes, it is. No question in my mind. TDD generally will slow you down
when you start using it, like anything new. But you'll soon get into
the habbit, and you'll be writing better code.
The big boost the you cannot see since you haven't experienced it yet,
is when the application becomes more complex, and you make a change that
you KNOW works fine, and a test fails. You'll grumble and say, "You see,
THAT is why I hate TDD."
Then, while fixing the damn test, you'll realize there's nothing wrong
with it. You'll then know, without question, why TDD works. It allows
you to make not only trivial changes with confidence, but serious tear
the wires out changes, and know that when the tests pass, you're good
to go.
> Because I hate it.
That's a not insignificant part of the problem. :-)
--
-- Tom Mornini, CTO
-- Engine Yard, Ruby on Rails Hosting
-- Reliability, Ease of Use, Scalability
-- (866) 518-YARD (9273)
Rails makes test-first somewhat hard, but still much easier than Brand X.
You are lucky to have a book that gets you over the curve - and you just
recommended an otherwise boring title to me!
The fall-back is "developer-centric testing" where you alternate writing
test cases, writing code, and editing the test cases so they accept the code
you wrote. I suspect that's how Rails itself was invented, and it's a big
part of the reason why Rails is so powerful.
Tests break when you make big changes. The fix is to not make big changes.
Make very small changes and pass all tests. When requirements change,
introduce the new requirement one tiny feature at a time. If a test fails,
inspect it to see if it prevented you from making a mistake; if not, adjust
it to the new requirements.
With even a little automated testing, you will debug much less, and your
projects have much more momentum. You can make small edits and run tests
with general assurance that things you forgot about did not break.
Without that support, you get debugging and churn, where fixing bugs causes
more bugs. Yes, some of us feel nostalgia for the olden days, when the Quest
for Bugs made us feel heroic. Get over it.
Under Debugger Driven Development, you start with fun magic tricks, and
descend into a nightmare of "app failed!". And you might not even have a
clue which module to inspect.
Under TDD, if your program unexpectedly fails, you have an option that
debugging can't provide:
-> you can revert your change <-
Treat that like a magic button on your editor called "kill bug".
Debugger-driven development simply doesn't provide that simple option.
--
Phlip
http://www.greencheese.us/ZeekLand <-- NOT a blog!!!
> Rails went from fun ActiveRecord magic tricks to a world of 'TEST
> FAILED.'
This guy named DHH seems to agree with you:
http://www.43things.com/people/progress/David/16399
"I've been a test-driven developer for quite a while, but I haven't
really gotten into the religious test-first branch yet."
Who does he think he is??
--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!
some people take the approach of stubbing all the tests you can think
of before you write the code (def test_should_incinerate_pie; end),
making sure the code more or less works, then running the existing
test suite to verify that you haven't broken anyway, and last,
actually writing the contents of all those tests you stubbed out. it
isn't as pure as tdd, but it does accomplish some of the major goals
(think about what should work and how, and be able to validate that
you have no regressions).
-faisal
I'm a newbie to TDD, and ran into it slightly BEFORE I hooked up with
Rails. In my "real job", automated testing requirements came in without
the rest of the Agile approach in place, and there, it has been a real
drag to get into TDD. I was lucky to have a member of my team who was
not new to it, and he started feeding me the zen of TDD in the right
way. Not "we will now write tests for everything in the world before we
write the application".
The job before us involved creating both a new XML based GUI layer and
also the glue and support code needed to hook that to an existing set of
"middleware" (this is phone UI stuff). I was doing the glue/support
code, and he was in charge of writing the XML stuff. He helped me
realize that the easy way for him to communicate just what he needed
from my part, was to write a test. He would send me an email something
to the effect of "I just added a test for BLAH", and then I would go off
and write some stuff that makes his test pass, then he would hook that
up to his XML and goodness would happen.
Every now and then he would add to or change a test and say "I just
realized I also needed fooBah, so I just broke the test", and I would go
in and instantly see from his test exactly what I needed to add to my
code. It has been a delightful way to communicate specific requirements
for our interface.
The key here is that we didn't write "all the tests" and then write "all
the code". Instead, we developed the app one piece at a time and used
the tests as a way to communicate what the top layer needed from the
lower layer.
Now we are into the last phase of the project where we are doing
profiling and looking for things to optimize. Taking specific large
hunks of my code and rewriting it is not a scary thing, even with the
release just days away, because I can and do run all of the tests after
I make both big and small changes, and when all the tests pass,
everything just works. Magic.
So I would say that you need to look at TDD in Rails more in line with
the Agile way of developing an app, quite like the process that the
"Dave's" lay out in the Agile Rails book. The stuff about showing the
client and the client says "wow, that's great, but what about yadda
yadda", and that takes us to the next part of the development. Instead
of designing the whole thing down to the last iota of specificity before
you start, you just kind of feel your way through it, and you do the
tests as you go. Any you and the "business people" play with it a bit
and you notice something and you say, "hey, I shouldn't be able to enter
so and so in this field" - translation "write a test that fails if the
user can successfully enter so and so in the field", run it to verify
that it is breaking, then add the code that makes it pass.
It isn't about spending 40 days and 40 nights writing tests before you
start on the real app. It's just a different way of designing and
developing a product, that includes creating a "proof of the pudding" as
you go. Five minutes thinking about the state of the app and how to
take it to the next (tiny) level, followed by five minutes of writing a
few tests and five minutes of making the tests pass, and viola, we've
achieved a new level with our app, and we know it works right.
And because of the TDD approach, every little hunk of the project works
perfectly (within the limits of the requirements we have defined -- i.e.
the tests we have written) as we go, so there just isn't any of the old
way of "OK, it's feature complete -- in a few months we should have some
of it actually working right".
jp
> It forces you to think about your logic twice.
I hate that part. I just want to claw my way from the submit_tag to the
database and then collapse.
However, I don't want to have to do that again and again and again. I want
my own workflow to be DRY.
> some people take the approach of stubbing all the tests you can think
> of before you write the code (def test_should_incinerate_pie; end),
> making sure the code more or less works, then running the existing
> test suite to verify that you haven't broken anyway, and last,
> actually writing the contents of all those tests you stubbed out. it
> isn't as pure as tdd, but it does accomplish some of the major goals
> (think about what should work and how, and be able to validate that
> you have no regressions).
The goal is to make very few edits between test runs, and always predict the
result of each test run. Either predict that all the tests pass, or predict
what kind of error diagnostic you will see.
Don't edit for a long time then expect tests to pass.
Configure your editor - whatever it is - to run all your tests when you hit
F5.
> The job before us involved creating both a new XML based GUI layer and
> also the glue and support code needed to hook that to an existing set of
> "middleware" (this is phone UI stuff). I was doing the glue/support
> code, and he was in charge of writing the XML stuff. He helped me
> realize that the easy way for him to communicate just what he needed
> from my part, was to write a test. He would send me an email something
> to the effect of "I just added a test for BLAH", and then I would go off
> and write some stuff that makes his test pass, then he would hook that
> up to his XML and goodness would happen.
Nice - tests to define internal interfaces.
Note that fix requests to the Rails and related code repositories these days
typically come with failing test cases.
> And because of the TDD approach, every little hunk of the project works
> perfectly (within the limits of the requirements we have defined -- i.e.
> the tests we have written) as we go, so there just isn't any of the old
> way of "OK, it's feature complete -- in a few months we should have some
> of it actually working right".
Shhhh! We need to keep that part a secret from the competition.
The few of them without pointy-haired bosses!
> Even better... install ZenTest
>
> gem install ZenTest
>
> autotest --rails
>
> Tests run when you save the corresponding file. Makes it almost too easy.
My command line:
trigger 'rake recent' `find test -name \\*.rb` app/*/*.rb
app/views/*/*.rhtml
The utterly ugly and distastefully hacked-together contents of trigger are
below my sig.
Any editor, folks. Any editor. I don't even need to look at the console to
hear the results. If the punk rock ain't up too loud!
--
Phlip
http://www.greencheese.us/ZeekLand <-- NOT a blog!!!
#!/usr/bin/env ruby
# lazy-loop until a file changes, then run a command
def syntax()
puts 'syntax: trigger "command...args" files...'
exit 1
end
# TODO support **
syntax() if 0 == ARGV.size
command = ARGV.shift
$fileTimes = {}
def anyFileChanged()
anyChanged = false
ARGV.each do |fn| # TODO option to do Dir here
begin
mod = File.mtime(fn)
anyChanged = true if $fileTimes[fn] != mod
$fileTimes[fn] = mod
rescue
puts $!
sleep 2
end
end
return anyChanged
end
anyFileChanged() # prime the pump
while true
sleep 0.333
if anyFileChanged()
got = system(command)
sound = got ? 'drumloop.wav' : 'jaguar.wav'
weWin32 = RUBY_PLATFORM.include?('mswin32')
if weWin32
system('"C:\\Program Files\\Windows Media Player\\mplayer2.exe"
/play /close s:\\bin\\' + sound)
else
system('aplay ~/bin/' + sound)
end
end
end
#One way is to use Win32API:
SND_MEMORY = 0x00000004 # from "mmsystem.h"
SND_FILENAME = 0x00020000
def playSound()
pPlaySound = Win32API.new("winmm", "PlaySound", ['P', 'L', 'L'], 'I')
# play from file:
pPlaySound.call("C:/your/sound.wav", 0, SND_FILENAME)
# play from memory:
#wav = File.open("C:/your/sound.wav", File::RDONLY) {|f| f.binmode;
f.read }
# PlaySound.call(wav, 0, SND_MEMORY)
end
> That's pretty wild. I dig it.
With a little more work I'm going to get it to say "Ni!" when it passes and
"Bad Zoot!" when it fails.
Yes.
You are doing e-commerce, not an AJAX chat application or Blog on Rails.
So in theory there is money on the line. I haven't read the book, or any
opinions on it, but it's hardline approach to TDD in the context of
e-commerce automatically raises my opinion of it.
Thanks to TDD (and Rails, because I've spend so many years trying to
setup TDD under J2EE with tools like Cactus without any result - I
thought I was stupid) I'm still earning my money developing applications
for customers but WITH JOY !!!
PLUS : Tests are now a commercial argument I use to convince my
clients/customers to choose me !
I'm still a dwarf at Agile development and TDD but compared to most of
the others companies/individuals here I'm a step ahead. And I dare to
say "I DO AGILE DEV, I DO TDD" every time I have the opportunity...
> The more I test the less I'm afraid of having my application falling
> down like a sand castle. I've done many sand castles before, none felt
> down because I've been lucky.
>
> Thanks to TDD (and Rails, because I've spend so many years trying to
> setup TDD under J2EE with tools like Cactus without any result
Good lord I thought I was thru with this thread...
My last big project had a major issue (translation: failure) attempting to
get Cactus working on a Tomcat project. I had more success TDDing CIAO, but
its patron (a highly respected _professor_ of programming) eventually called
me a "lunatic" because I kept asking weird questions on their mailing list.
I got CIAO (an advanced form of CORBA)completely under control...
...but I couldn't even _install_ Cactus. Each time I tried to configure
things, I would get stuck in some hideous error condition. Then, for
example, I couldn't tell what the error was because I couldn't turn on
logging, because the system wasn't configured just right. That sick joke of
a system lead to this page:
http://c2.com/cgi/wiki?ConfigurationHell
That's the anti-Convention over Configuration - refusing to convene
_anything_, in fear that the user might override a default.
Someone will have to put a gun to my head to get me to write automated tests
for Tomcat again, but if they do, I am ready: With Watir...
...and with a trick or two that are currently up my sleeve, folks! ;-)
> PLUS : Tests are now a commercial argument I use to convince my
> clients/customers to choose me !
Try "I can deploy continuously and deliver daily"...
Richard Conroy wrote:
> You are doing e-commerce, not an AJAX chat application or Blog on Rails.
> So in theory there is money on the line. I haven't read the book, or any
> opinions on it, but it's hardline approach to TDD in the context of
> e-commerce automatically raises my opinion of it.
TDD-ing the GUI Layer is very hard, so we have an excuse to slack off on it.
Until someone fixes that. ;-)
I've heard of people doing TDD with Selenium. I'm not convinced that
having to use a browser to run your tests is not more trouble than it's
worth especially for TDD - but people more clever than me seems to like
it.
--
Cheers,
- Jacob Atzen
> I've heard of people doing TDD with Selenium. I'm not convinced that
> having to use a browser to run your tests is not more trouble than it's
> worth especially for TDD - but people more clever than me seems to like
> it.
Tip: Can we think of ways to TDD the GUI Layer without creating all of a web
server, browser, DOM, etc.?
I have some experience with trying to do automated testing at a higher
level than unit testing.
1 - they are much harder to write
2 - it is more difficult to get these tests to exercise all of your
code branches
3 - the tests are very brittle with regard to feature changes etc.
TDD really requires Unit Testing. Its the only cheap way to get good test
coverage, and its the good test coverage that provides the foundation for
all of the other good TDD practices.
On top of this, you can get functional tests, acceptance tests etc. The
closer you get to the user, and the further from the 'coal face', it starts
to get much more appropriate to use tools like Selenium & WATIR.
These tools *complement* your TDD arsenal, but given a choice, you
simply can't get TDD benefits without low-level unit testing.
Selenium & WATIR are great tools, but if they are your only tools,
then you are not doing TDD.
How do I make my terminal show failures in red? I am on Mac. TIA.
gem install turn
Then require 'turn' in test_helper.rb
--Greg
gem install turn
Then require 'turn' in test_helper.rb
--Greg
does this require some particular TERM setting?
-faisal
My question is, is it possible to implement Rspec on Rails for an
existing Rails project and if so how?
Have a bunch of pre-existing projects that I would like to use Rspec on
Rails on and I would hate to have to manually create all the nice
directories and files that Rspec on Rails does when you use it from the
beginning. Any help would be appreciated.
Thanks,
Nathan
I would expect so, but I don't use iterm. Try it out.
--Greg
I've only used it on an xterm, and it works just fine in that. I recommend
trying it out and, if it doesn't work, sending a message to the author
(not me!).
} -faisal
--Greg
Nathan,
I'm in a similar position - a 6 month old app that I can't just drop
all the current tests and go with rspec. I'm considering using
test/spec to start switching to BDD on a spec by spec basis. It
integrates with test/unit and doesn't require translating old tests to
specs.
- rob
--
http://www.robsanheim.com
http://www.seekingalpha.com
http://www.ajaxian.com
Working title, oh, I dunno, maybe...
--> Test First Ajax <--
;-)
Cool, thanks for the link. Looks like just what I needed.
Nathan
On Fri, 2006-12-01 at 12:44 -0600, Rob Sanheim wrote:
> My question is, is it possible to implement Rspec on Rails for an
> existing Rails project and if so how?
Give a try to the simply_bdd plugin.
http://svn.techno-weenie.net/projects/plugins/simply_bdd/README
It makes using RSpec a lot easier: you run rspec code like normal
tests (see the example in the README page), and it works fine with
autotest.
Not shown in the README example is the need to use
require 'spec'
to access the should_** magic.
Example:
file: test/unit/a_user_test.rb
require File.dirname(__FILE__) + '/../test_helper'
require 'spec'
context "A User with no name" do
def setup
@user = User.new
end
specify "should be invalid" do
# assert !@user.valid? # std way
@user.should_not_be_valid # rspec way
end
end
[Benefit #1]
The benifit of TDD is more than a thoroughly tested application.
-Reducing Under-design: When you miss the mark by not implementing
requirements (either through omissions in the requirements or not
fulfilling them). Bugs crop up as a result.
-Reducing Over-design: When you surpass the minimal work necessary to
fulfill the requirements. The more code you have the more potential
there is for additional bugs.
Both of these add time to a project -- translating to higher project
cost.
When you write a unit test first, you follow up by running it and
watching it fail. Next you write code until it passes. Then reduce the
code so it is as clean and minimalist as possible to pass the test.
[/Benefit #1]
[Benefit #2]
You are already doing unit testing in a manner of speaking. You are
just not doing it efficiently or consistently. When you write code you
it there thinking a lot about how to implement it. Then consider the
broader implications the modifications have. This consumes time --
lots of it. And you still don't know what will occur. You just have to
make your best guess.
When the coding phase begins, you write code and test it iteratively or
you wait to the end and hope it isn't too screwed up. Either way you
test it over and over. Automated Unit testing in TTD speeds things up
by taking you out of the loop and makes testing more consistent
(obviously).
You spend a lot of time writing them, but you never account for just how
many times they get executed after you're done. Trust me, That's a big
number. So, take the amount of time it takes for [you] to sit there
testing your code and multiply it by the number of times the test cases
execute. Now follow the resulting conclusion ...
[/Benefit #2]
[Benefit #3]
INSTANT FEEDBACK
Relating to the previous benefit is comfort. How many times have you
been asked if you can make a change and answered, "No Problem" while
feeling concretely certain about your answer?
When you have a robust test harness complimenting your application, you
stop worrying about what you are about to break in the code. Just make
you stinking changes and let the test harness work about the rest of the
problem.
SPEED
Not worrying about the broad implications of code modifications makes
you write write code a a break-neck speed. :o)
[/Benefit #3]
[Benefit #4]
Documenting what the code does and how it does it.
One of the unforeseen products of TDD was the documentation it produced.
It does a great job documenting how a piece of code is expected to be
used. If you think about what a repository of knowledge it becomes,
what a benefit that becomes! Nuff said!
[/Benefit #4]
Sorry folks! That should be, "When you write code you sit ther...."
One of the very first things that I encourage potential clients that
have existing developers to do is to get the output of... rake stats.
This isn't as uncommon to see as many of us would like.
Code LOC: 9473 Test LOC: 575 Code to Test Ratio: 1:0.1
(real output from a past client that came to us...)
Good luck!
-Robby
> This isn't as uncommon to see as many of us would like.
>
> Code LOC: 9473 Test LOC: 575 Code to Test Ratio: 1:0.1
Ahem:
Code LOC: 1598 Test LOC: 1577 Code to Test Ratio: 1:1.0
And note that the higher the Test LOC gets, the more ability you have to
squeeze down on the Code LOC, and keep it low.
Low line counts are good, folks!
Related and worht reading:
Related to these options:
http://weblog.techno-weenie.net/2006/11/24/test-spec-kicks-simply_bdds-ass
When you first install the RSpec on Rails plugin, your existing tests
won't run. Don't worry though, there's a very easy workaround!
http://rubyforge.org/tracker/index.php?func=detail&aid=6629&group_id=797&atid=3149
read through that, I've got a simple explanation. It's really really
easy so check it out.
You can use RSpec along with any standard Rails tests. This is nice
if you want to install something like the restful_authentication
plugin, but use RSpec to drive your design. Use my workaround above,
and rake will automatically run all your tests and specs for you.
The only thing that you'll have to create is spec files for your
existing code. I'd suggest generating an rspec_model and
rspec_controller to get the directory structure and a template spec
file to work from.
Also, we have an RSpec list that you should check out. Go to the
project page and sign up!
Pat
To get coloring you also need the facets gem:
gem install facets
From the gem description:
If you have the 'facets' gem installed, then TURN output will be
displayed in wonderful technicolor (but only if your terminal
supports ANSI color codes).