473,322 Members | 1,538 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Unit testing - one test class/method, or test class/class


Hi,

I just found py.test[1] and converted a large unit test module to py.test
format (which is actually almost-no-format-at-all, but I won't get there
now). Having 348 test cases in the module and huge test classes, I started
to think about splitting classes. Basically you have at least three obvious
choises, if you are going for consistency in your test modules:

Choise a:

Create a single test class for the whole module to be tested, whether it
contains multiple classes or not.

....I dont think this method deserves closer inspection. It's probably rather
poor method to begin with. With py.test where no subclassing is required
(like in Python unittest, where you have to subclass unittest.TestCase)
you'd probably be better off with just writing a test method for each class
and each class method in the module.

Choise b:

Create a test class for each class in the module, plus one class for any
non-class methods defined in the module.

+ Feels clean, because each test class is mapped to one class in the module
+ It is rather easy to find all tests for given class
+ Relatively easy to create class skeleton automatically from test module
and the other way round

- Test classes get huge easily
- Missing test methods are not very easy to find[2]
- A test method may depend on other tests in the same class

Choise c:

Create a test class for each non-class method and class method in the tested
module.

+ Test classes are small, easy to find all tests for given method
+ Helps in test isolation - having separate test class for single method
makes tested class less dependent of any other methods/classes
+ Relatively easy to create test module from existing class (but then you
are not doing TDD!) but not vice versa

- Large number of classes results in more overhead; more typing, probably
requires subclassing because of common test class setup methods etc.

What do you think, any important points I'm missing?

Footnotes:
[1] In reality, this is a secret plot to advertise py.test, see
http://codespeak.net/py/current/doc/test.html

[2] However, this problem disappears if you start with writing your tests
first: with TDD, you don't have untested methods, because you start by
writing the tests first, and end up with a module that passes the tests
--
# Edvard Majakari Software Engineer
# PGP PUBLIC KEY available Soli Deo Gloria!
One day, when he was naughty, Mr Bunnsy looked over the hedge into Farmer
Fred's field and it was full of fresh green lettuces. Mr Bunnsy, however, was
not full of lettuces. This did not seem fair. --Mr Bunnsy has an adventure
Jul 18 '05 #1
4 3022
I do something more or less like your option b. I don't think there is any
orthodox structure to follow. You should use a style that fit your taste.

What I really want to bring up is your might want to look at refactoring
your module in the first place. 348 test cases for one module sounds like
a large number. That reflects you have a fairly complex module to be
tested to start with. Often the biggest benefit of doing automated unit
testing is it forces the developers to modularize and decouple their code
in order to make it testable. This action alone improve that code quality
a lot. If breaking up the module make sense in your case, the test
structure will follows.

Hi,

I just found py.test[1] and converted a large unit test module to py.test
format (which is actually almost-no-format-at-all, but I won't get there
now). Having 348 test cases in the module and huge test classes, I
started
to think about splitting classes. Basically you have at least three
obvious
choises, if you are going for consistency in your test modules:

Choise a:

Create a single test class for the whole module to be tested, whether it
contains multiple classes or not.

...I dont think this method deserves closer inspection. It's probably
rather
poor method to begin with. With py.test where no subclassing is required
(like in Python unittest, where you have to subclass unittest.TestCase)
you'd probably be better off with just writing a test method for each
class
and each class method in the module.

Choise b:

Create a test class for each class in the module, plus one class for any
non-class methods defined in the module.

+ Feels clean, because each test class is mapped to one class in the
module
+ It is rather easy to find all tests for given class
+ Relatively easy to create class skeleton automatically from test module
and the other way round

- Test classes get huge easily
- Missing test methods are not very easy to find[2]
- A test method may depend on other tests in the same class

Choise c:

Create a test class for each non-class method and class method in the
tested
module.

+ Test classes are small, easy to find all tests for given method
+ Helps in test isolation - having separate test class for single method
makes tested class less dependent of any other methods/classes
+ Relatively easy to create test module from existing class (but then you
are not doing TDD!) but not vice versa

- Large number of classes results in more overhead; more typing, probably
requires subclassing because of common test class setup methods etc.

What do you think, any important points I'm missing?

Footnotes:
[1] In reality, this is a secret plot to advertise py.test, see
http://codespeak.net/py/current/doc/test.html

[2] However, this problem disappears if you start with writing your tests
first: with TDD, you don't have untested methods, because you start
by
writing the tests first, and end up with a module that passes the
tests

--
# Edvard Majakari Software Engineer
# PGP PUBLIC KEY available Soli Deo Gloria!
One day, when he was naughty, Mr Bunnsy looked over the hedge into Farmer
Fred's field and it was full of fresh green lettuces. Mr Bunnsy,
however, was
not full of lettuces. This did not seem fair. --Mr Bunnsy has an
adventure


Jul 18 '05 #2
I tend to write one test class per class, but that's
just the way I got started. My feeling is that the
methods in a test class should tell a story if you
read the names in the order they were written,
so I'd split the tests for a class into several
classes if they had different stories to tell.

John Roth
"Edvard Majakari" <ed*********@majakari.net> wrote in message
news:87************@titan.staselog.com...

Hi,

I just found py.test[1] and converted a large unit test module to py.test
format (which is actually almost-no-format-at-all, but I won't get there
now). Having 348 test cases in the module and huge test classes, I started
to think about splitting classes. Basically you have at least three
obvious
choises, if you are going for consistency in your test modules:

Choise a:

Create a single test class for the whole module to be tested, whether it
contains multiple classes or not.

...I dont think this method deserves closer inspection. It's probably
rather
poor method to begin with. With py.test where no subclassing is required
(like in Python unittest, where you have to subclass unittest.TestCase)
you'd probably be better off with just writing a test method for each
class
and each class method in the module.

Choise b:

Create a test class for each class in the module, plus one class for any
non-class methods defined in the module.

+ Feels clean, because each test class is mapped to one class in the
module
+ It is rather easy to find all tests for given class
+ Relatively easy to create class skeleton automatically from test module
and the other way round

- Test classes get huge easily
- Missing test methods are not very easy to find[2]
- A test method may depend on other tests in the same class

Choise c:

Create a test class for each non-class method and class method in the
tested
module.

+ Test classes are small, easy to find all tests for given method
+ Helps in test isolation - having separate test class for single method
makes tested class less dependent of any other methods/classes
+ Relatively easy to create test module from existing class (but then you
are not doing TDD!) but not vice versa

- Large number of classes results in more overhead; more typing, probably
requires subclassing because of common test class setup methods etc.

What do you think, any important points I'm missing?

Footnotes:
[1] In reality, this is a secret plot to advertise py.test, see
http://codespeak.net/py/current/doc/test.html

[2] However, this problem disappears if you start with writing your tests
first: with TDD, you don't have untested methods, because you start by
writing the tests first, and end up with a module that passes the tests
--
# Edvard Majakari Software Engineer
# PGP PUBLIC KEY available Soli Deo Gloria!
One day, when he was naughty, Mr Bunnsy looked over the hedge into Farmer
Fred's field and it was full of fresh green lettuces. Mr Bunnsy, however,
was
not full of lettuces. This did not seem fair. --Mr Bunnsy has an
adventure


Jul 18 '05 #3
aurora <au******@gmail.com> writes:
What I really want to bring up is your might want to look at refactoring
your module in the first place. 348 test cases for one module sounds like a
large number. That reflects you have a fairly complex module to be tested
to start with. Often the biggest benefit of doing automated unit testing is
it forces the developers to modularize and decouple their code in order to
make it testable. This action alone improve that code quality a lot. If
breaking up the module make sense in your case, the test structure will
follows.


Here I have to emphasize a little: of those 348 test cases, only ~30 or so
are real, hand-coded methods. Some of the tests are generated on the fly by
py.test. It is not as fancy as it sounds, though. All it does is

test_some_feature(self):

for foo, bar, expected in known_values:
yield self.foo_bar_equals, foo, bar, expected

def foo_bar_equals(self, foo, bar, expected):

assert some_feature(foo, bar) == expected

There are two methods. However, if known_values contains 100 tuples,
py.test generates 100 "test methods" on the fly. Of course you could just do

test_some_feature(self):

for foo, bar, expected in known_values:
assert some_feature(foo, bar) == expected

but then you wouldn't see so easily which values are tested when you use
verbose mode, that is. That's one of the (many) nice things in py.test I
like :)

However, being practical in testing is probably more worth than being
completely orthodox, on that I agree. That's why I seldom stick to strict
rules in doing tests, though being systematic helps alot, especially
regarding orthogonality. It doesn't help to test same features over and
over again. Eg. if I wrote a test for a dot in 2D space, I'd write tests for
dot on origo, on positive x-axis with y < 0 and y > 0, ditto for x and y
reversed, then same tests for negative x and y, and last for positive and
negative x and y with other being exactly zero. There's no point testing
other values; all other combinations fall to some of the categories
mentioned.

--
# Edvard Majakari Software Engineer
# PGP PUBLIC KEY available Soli Deo Gloria!

$_ = '456476617264204d616a616b6172692c20612043687269737 469616e20'; print
join('',map{chr hex}(split/(\w{2})/)),uc substr(crypt(60281449,'es'),2,4),"\n";
Jul 18 '05 #4
"John Roth" <ne********@jhrothjr.com> writes:
I tend to write one test class per class, but that's
just the way I got started. My feeling is that the
methods in a test class should tell a story if you
read the names in the order they were written,
so I'd split the tests for a class into several
classes if they had different stories to tell.
Well, that's one of the things I forgot to mention. Often I use

TestSomeClassA:
# test for normal, legal inputs

TestSomeClassB:
# test for extreme/border cases, still legal inputs

TestSomeClassC:
# test cases with illegal input, eg. negative integer when only positive
# inputs make sense etc.

Just like you said, they tell a bit different story each, so it probably
makes sense to separate those.

John Roth

"Edvard Majakari" <ed*********@majakari.net> wrote in message
news:87************@titan.staselog.com...

Hi,

I just found py.test[1] and converted a large unit test module to py.test
format (which is actually almost-no-format-at-all, but I won't get there
now). Having 348 test cases in the module and huge test classes, I started
to think about splitting classes. Basically you have at least three
obvious
choises, if you are going for consistency in your test modules:

Choise a:

Create a single test class for the whole module to be tested, whether it
contains multiple classes or not.

...I dont think this method deserves closer inspection. It's probably
rather
poor method to begin with. With py.test where no subclassing is required
(like in Python unittest, where you have to subclass unittest.TestCase)
you'd probably be better off with just writing a test method for each
class
and each class method in the module.

Choise b:

Create a test class for each class in the module, plus one class for any
non-class methods defined in the module.

+ Feels clean, because each test class is mapped to one class in the
module
+ It is rather easy to find all tests for given class
+ Relatively easy to create class skeleton automatically from test module
and the other way round

- Test classes get huge easily
- Missing test methods are not very easy to find[2]
- A test method may depend on other tests in the same class

Choise c:

Create a test class for each non-class method and class method in the
tested
module.

+ Test classes are small, easy to find all tests for given method
+ Helps in test isolation - having separate test class for single method
makes tested class less dependent of any other methods/classes
+ Relatively easy to create test module from existing class (but then you
are not doing TDD!) but not vice versa

- Large number of classes results in more overhead; more typing, probably
requires subclassing because of common test class setup methods etc.

What do you think, any important points I'm missing?

Footnotes:
[1] In reality, this is a secret plot to advertise py.test, see
http://codespeak.net/py/current/doc/test.html

[2] However, this problem disappears if you start with writing your tests
first: with TDD, you don't have untested methods, because you start by
writing the tests first, and end up with a module that passes the tests
--
# Edvard Majakari Software Engineer
# PGP PUBLIC KEY available Soli Deo Gloria!
One day, when he was naughty, Mr Bunnsy looked over the hedge into Farmer
Fred's field and it was full of fresh green lettuces. Mr Bunnsy, however,
was
not full of lettuces. This did not seem fair. --Mr Bunnsy has an
adventure


--
# Edvard Majakari Software Engineer
# PGP PUBLIC KEY available Soli Deo Gloria!

$_ = '456476617264204d616a616b6172692c20612043687269737 469616e20'; print
join('',map{chr hex}(split/(\w{2})/)),uc substr(crypt(60281449,'es'),2,4),"\n";
Jul 18 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Edvard Majakari | last post by:
Hi all ya unit-testing experts there :) Code I'm working on has to parse large and complex files and detect equally complex and large amount of errors before the contents of the file is fed to...
3
by: SnaiL | last post by:
Hi, guys. I am interested in C++ unit testing. I know only two methods how to test private class methods. 1) Declare friend class in the code. But I don't like this style because tests depends...
3
by: Matt Kruse | last post by:
Does anyone actively use JSUnit < http://www.edwardh.com/jsunit/ > for unit testing their javascript code? For logical functions, I imagine it could be very useful. However, I'm wondering how...
38
by: Christoph Zwerschke | last post by:
In August 2001, there was a thread about the "Art of Unit Testing": http://groups.google.com/group/comp.lang.python/browse_frm/thread/aa2bd17e7f995d05/71a29faf0a0485d5 Paul Moore asked the...
11
by: D. Yates | last post by:
Hi, In an effort to improve my own code and try to teach others that I work with that unit testing IS MANDATORY. I'm interested in examples of unit testing that other people are using. How...
5
by: David K Allen | last post by:
Here's my problem. Have a database interface with several methods. I created a database class to implement the interface, and a set of unit tests to test each method. Now I want to support...
72
by: Jacob | last post by:
I have compiled a set og unit testing recommendations based on my own experience on the concept. Feedback and suggestions for improvements are appreciated: ...
5
by: shuisheng | last post by:
Dear All, I was told that unit test is a powerful tool for progamming. If I am writing a GUI code, is it possible to still using unit test? I have a little experience in using unittest++. But...
6
by: Vyacheslav Maslov | last post by:
Hi all! I have many many many python unit test, which are used for testing some remote web service. The most important issue here is logging of test execution process and result. I strongly...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.