Unit Tests of Models w/o Tables

AWDWR focuses on unit tests for models with database tables. There’s
no discussion for models w/o tables that I can see.

First attempts kept complaining about data tables not existing. I
figured out this seems to come from the :fixtures line. Comment that
out, and the test runs.

OK, but I do want to use test data, it’s just that it is not going to
come from a database table. Is there some way to declare that the
fixture file represents data that has nothing to do with database
tables? Seems something like fixtures should be adaptable for
simulating any data source.

Searching for some blog topics on this hasn’t been productive.

Certainly I can do my own setup that loads text files of sample data
or pulls from a dummy web service as the case may be, but I just want
to be sure that’s the intended solution.

– gw

Hi Greg,

I had to create unit tests for a model that was not in the database. I
will share what I did, but my model was pretty much acted as a single
object so there was not a big data requirement.

The unit test did not load any fixtures and so I just created new model
objects as I needed them using a protected function like this (I was
shown this technique in training from the BigNerd Ranch and I find it
indispensable when writing tests now):

def create_credit_card(options={})
CreditCard.new({
:type => ‘VI’,
:number => ‘4111111111111111’,
:expires => ‘05/10’
}.merge(options))
end

I created tests like normal an just instantiated objects with the data I
needed.

def test_should_require_type
card = create_credit_card(:type => ‘’)
assert !card.valid?
end

Does this make sense? I am not sure how well this would work if you
need a lot of data. Good luck!

Peer

Greg W. wrote:

AWDWR focuses on unit tests for models with database tables. There’s
no discussion for models w/o tables that I can see.

First attempts kept complaining about data tables not existing. I
figured out this seems to come from the :fixtures line. Comment that
out, and the test runs.

OK, but I do want to use test data, it’s just that it is not going to
come from a database table. Is there some way to declare that the
fixture file represents data that has nothing to do with database
tables? Seems something like fixtures should be adaptable for
simulating any data source.

Searching for some blog topics on this hasn’t been productive.

Certainly I can do my own setup that loads text files of sample data
or pulls from a dummy web service as the case may be, but I just want
to be sure that’s the intended solution.

– gw

On Nov 9, 2007, at 5:36 PM, Peer A. wrote:

…I just created new model
objects as I needed them using a protected function like this (I was
shown this technique in training from the BigNerd Ranch and I find it
indispensable when writing tests now):

Yeah that could make sense for some cases. This particular one would
need flexible data (it’s a config file parser). So, I have no problem
using setup, or simply loadding data to start with by any means, just
seemd weird that fixtures is dedicated to data table models.

Anyway, I’m having a lot more fundamental problem now in that I can’t
seem to create instances of my model class w/in the test code.

Simplified version of my model…

class ConfigData

attr_reader :configData

def initialize
@configData = ‘’
end

def loadFile(fileName)
if FileTest::exist?(fileName)
fileLines = IO.readlines(fileName)
return fileLines
end
end

…lots of other methods…
end

Even this simplified test complains…

require File.dirname(FILE) + ‘/…/test_helper’
class ConfigData < Test::Unit::TestCase
def test_loadFile
cnfgData = ConfigData.new
end
end

What I get is a complaint about initialize having a “wrong number
of arguments (0 for 1)” – but there are no arguments required.

I’m obviously missing the relationship of something somewhere, but
I’m totally stumped.

– gw

On Nov 9, 2007, at 6:42 PM, Greg W. wrote:

 @configData = ''

end

What I get is a complaint about initialize having a “wrong number
of arguments (0 for 1)” – but there are no arguments required.

After pulling nearly all my hair out (and I have a lot of it), I
found the problem.

Notice this line:
class ConfigData < Test::Unit::TestCase
should be
class ConfigDataTest < Test::Unit::TestCase

Aargh.

– gw

You might want to look into Mocha. Mocks can often put a finer point
on what you’re trying to test – particularly if it’s not db-related.
Check out: Tags - James Mead.

Consider this:

class ConfigDataTest < Test::Unit::TestCase
def LoadFileShouldOnlyReadFilesThatExist
FileTest.stub!(:exist?).and_return(false)
@config = ConfigData.new
assert what_you_expect_when_the_file_doesnt_exist,
@config.loadFile(‘abc.txt’)
end

def LoadFileShouldReadFilesWhenTheyExist
FileTest.stub!(:exist?).and_return(true)
IO.should_receive(:readlines).once.and_return([‘line1’, ‘line2’,
‘line3’])
@config = ConfigData.new
assert_equal 3, @config.LoadFile(‘test.txt’)
end
end

I’m not sure this code actually works, but if you see what I’m
driving at, you can test a lot of different scenarios with not a lot
of code.

Hope this helps.

Cool, I’ll check it out.

When I created the Unit test framework for Lasso I included a lot of
explicit assertions that made it a lot clearer what was being tested
for as well. (www.l-unit.org)

– gw

On Nov 9, 2007, at 9:05 PM, s.ross wrote:

 @config = ConfigData.new

end

attr_reader :configData
end
cnfgData = ConfigData.new
Notice this line:

– gw

D’Oh. The assert in the second test case should have been:

assert_equal 3, @config.LoadFile(‘test.txt’).size