I think I have a fundamental misunderstanding of what 'rake test:functionals' does for me.
I assumed it did the exact same thing for me that 'rake test' did, except that it only ran the functional tests. It seems like this was a bad assumption because in the project I'm working on, when I run 'rake test', I get no failures or errors, but when I run 'rake test:functionals', I get failures.
Is there something different about what these things do in terms of fixture loading or pre-test setup that I'm not seeing?
I don't have an answer for you, Bryan, but I too am curious about
rake-related testing differences. My problem is that if I run one of
my tests as follows
ruby test/unit/box_test.rb
it all passes, but if I run "rake test" or just simply "rake" the same
test fails.
Thanks in advance, whoever can shed light on this problem!
Ben
The functional test that was failing when I ran 'rake test:functionals'
has a long list of fixtures it is using.
fixtures :f1, :f2, :f3
I looked closer at what the actual test method was doing, and realized
that it was dealing with a type of model object whose fixture did not
appear in the list of those I was including. So, I changed that line to
this:
fixtures :f1, :f2, :f3, :f4
... and all is well now.
So... that fixed my problem, but now I'm a little scared because
something else I assumed was happening a certain way seems not to be.
Since this particular functional test was passing when I simply ran
'rake test', I can deduce that one of my functional tests was including
the ':f4' fixture, and that data was still laying around in the
database, enabling that functional test to eventually pass.
This scares me because I assumed the fixtures would be loaded and wiped
away for each and every test so that the state of the database was
known. Is this a bad assumption?
The functional test that was failing when I ran 'rake
test:functionals' has a long list of fixtures it is using.
fixtures :f1, :f2, :f3
I looked closer at what the actual test method was doing, and realized
that it was dealing with a type of model object whose fixture did not
appear in the list of those I was including. So, I changed that line
to this:
fixtures :f1, :f2, :f3, :f4
... and all is well now.
So... that fixed my problem, but now I'm a little scared because
something else I assumed was happening a certain way seems not to be.
Since this particular functional test was passing when I simply ran
'rake test', I can deduce that one of my functional tests
scratch 'functional tests', should say 'unit tests'
Well for one thing, if you run 'rake test" all your unit tests run
before your functional tests. When you run 'rake test:functionals'
your unit tests don't run.
So I would suspect that your unit tests are loading something
(fixtures or whatever) that are not getting loaded when you run
functional tests alone.
That's the kind of thing I would look for first. Even try running your
tests individually and see if they pass. If they don't, you'll likely
find that your aren't loading something you need in the individual
test that is failing.
Thanks Robert. This is exactly what it turned out to be (see my
response in the thread about 3 minutes before yours). Do you have any
insight to my concern that I'm not getting a clean slate/known state
after unit tests have run?
It appears to me from my testing that the test database tables are
emptied at the beginning of tests but are not emptied after the test
completes. Running functional tests that do not load the fixture in
question does not empty the databases table in question. Therefore, a
functional test reading data from a table where the fixture is not
loaded by that specific functional test will use the data that may
have been left behind from a previous test run.
Hope that's not too confusing. It basically boils down to ensuring
that you are loading fixtures for all tables accessed by that specific
test.
Ugg. And I thought that the builtin test framework was bad enough
already.
What this means is that your tests need to do complete teardowns--
including the test database. I've had a number of cases where I
mocked behavior for a test and then had the mocking interfere with the
testing of the real function. I tend to be pretty aggressive about
creating modules to test inside now. This sounds like another time
where best practice is going to have to be learned the hard way.
You've discovered that it's fixture-related. You have a test case that
is using a fixture that you aren't explicitly loading, but that a
different test case *is* loading. When you run the test cases in
different orders, you can get strange errors.
The solution is to specify *all* your fixtures in each test case. I
have the following method in test_helper.rb:
def self.all_fixtures
Dir.glob(File.join(File.dirname(__FILE__), 'fixtures', '*.{yml,csv}')).each
do |fixture_file|
fixtures File.basename(fixture_file, '.*')
end
end
Then in each test case, instead of listing specific fixture names, I just use:
IMHO, this will land you right back in the soup. Different tests will
have different needs for fixtures. And edge testing conditions tend
(very much) to be incompatible with each other. Certainly, you might
have a base set of fixtures, or even a collection which might be
addressed as an array, but the topology is likely to be complex
overall.
YMMV and all, but you are far less likely to run into trouble if you
load precisely the fixtures that you intend for each test or set of
tests--and clean up when you are done.