steveYeah
steveYeah

Reputation: 351

Writing Python test classes using Nose and Sqlalchemy with fixtures

I've been fighting with nose and fixtures today and can't help but feel I'm doing something wrong.

I had all my tests written as functions and everything was working OK, but I want to move them to test classes as I think it's tidier and the tests can then be inherited from.

I create a connection to the testdb, the transaction to use, and a number of fixtures at a package level for all tests. This connection is used by repository classes in the application to load test data from the DB.

I tried to create my test classes with the class they are to test as an attribute. This was set in the __init__ function of the test class.

The problem I had is the class I was testing needs to be instantiated with data from my test DB, but Nose creates an instance of the test class before the package setup function is run. This mean that there are no fixtures when the test classes are created and the tests fail.

The only way I can get it to work is by adding a module setup function that defines the class I want to test as a global, then use that global in the test methods, but that seems quite hacky. Can anyone suggest a better way?

That isn't very clear, so here is an example of my test module...

from nose.tools import *
from myproject import repositories
from myproject import MyClass

def setup():
    global class_to_test

    db_data_repo = repositories.DBDataRepository()
    db_data = db_data_repo.find(1)

    class_to_test = MyClass(db_data)


class TestMyClass(object):

    def test_result_should_be_an_float(self):
        result = class_to_test.do_something()

        assert isinstance(result, float)

If you know a better way to achieve this then please share :) thanks!

Upvotes: 1

Views: 720

Answers (1)

Oleksiy
Oleksiy

Reputation: 6567

If you are moving toward unittest.TestCase class based testing, you might as well use setUp()/tearDown() method that will run before each test method, and setUpClass() to setup up class specific things, and nose will handle it just as unittest will, something like this:

class TestMyClass(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        db_data_repo = repositories.DBDataRepository()
        db_data = db_data_repo.find(1)
        cls.class_to_test = MyClass(db_data)    

    def test_result_should_be_an_float(self):
        result = self.class_to_test.do_something()
        assert isinstance(result, float)

Upvotes: 1

Related Questions