decorators don't play nice with nose?

H

hyperboreean

Hi, I am trying to test the business part of a web service. For this I
am using unittest & nose.
I wrote a decorator that should handle the xml test file retrieval, but
it seems I can't get it working with nose.
Here's the code:


* MyApp.py -- base test class *

import os
import unittest

from MyApp.Core import XmlParser


__all__ = ['MyAppTest', 'setup']


PATH = os.path.dirname(__file__) or ''


class setup(object):
"""Decorator to ease the use of xml files in MyApp tests.

The way it works it that it decorates a test method which has a first
default parameter called 'parser' and it overwrites this parameter value
with a XmlParser instance.

The xml file should be located under:
data/testedBusinessRequest/testMethodName.xml
"""
def __init__(self, testedBusinessRequest = ''):
self.testedBusinessRequest =\
testedBusinessRequest.lower()


def _getXmlParser(self, xml):
documentElement = XmlParser.parseXmlStream(xml)
parser = XmlParser.getParser(documentElement)
return parser


def __call__(self, method):

# TODO: error handling here
methodName = method.func_code.co_name
methodName = methodName.split('_')[1]

xmlFolder = self.testedBusinessRequest
xmlFile = '%s.xml' % methodName

path = os.path.join(PATH, 'data',
xmlFolder, xmlFile)

f = open(path)
xml = f.read()
f.close()
method.func_defaults = (self._getXmlParser(xml),)
return method


class MyAppTest(unittest.TestCase):

def setUp(self):
self.database = Database()

def tearDown(self):
pass


* test_Login.py - test a business request *
from MyAppTest import MyAppTest, setup

from MyApp import Login


class TestLogin(MyAppTest):
testedBusinessRequest = 'Login'

@setup(testedBusinessRequest)
def test_validParameters(self, parser = None):
response = Login(self.database, parser).run()
return True



Ok, so the decorator setup should fill the parser parameter with a
XmlParser object. This works well if I add a __main__ and use unittest
to run the tests. But if I use nose, I get the following error:

*TypeError: unbound method __call__() must be called with setup instance
as first argument (got module instance instead)*

Any advices?
Thanks!
 
J

J Kenneth King

hyperboreean said:
From: hyperboreean <[email protected]>
Subject: decorators don't play nice with nose?
Newsgroups: comp.lang.python
To: (e-mail address removed)
Date: Mon, 06 Apr 2009 11:01:04 +0300

Hi, I am trying to test the business part of a web service. For this I
am using unittest & nose.
I wrote a decorator that should handle the xml test file retrieval,
but it seems I can't get it working with nose.
Here's the code:


* MyApp.py -- base test class *

import os
import unittest

from MyApp.Core import XmlParser


__all__ = ['MyAppTest', 'setup']


PATH = os.path.dirname(__file__) or ''


class setup(object):
"""Decorator to ease the use of xml files in MyApp tests.

The way it works it that it decorates a test method which has a first
default parameter called 'parser' and it overwrites this parameter value
with a XmlParser instance.

The xml file should be located under:
data/testedBusinessRequest/testMethodName.xml
"""
def __init__(self, testedBusinessRequest = ''):
self.testedBusinessRequest =\
testedBusinessRequest.lower()


def _getXmlParser(self, xml):
documentElement = XmlParser.parseXmlStream(xml)
parser = XmlParser.getParser(documentElement)
return parser


def __call__(self, method):

# TODO: error handling here
methodName = method.func_code.co_name
methodName = methodName.split('_')[1]

xmlFolder = self.testedBusinessRequest
xmlFile = '%s.xml' % methodName

path = os.path.join(PATH, 'data',
xmlFolder, xmlFile)

f = open(path)
xml = f.read()
f.close()
method.func_defaults = (self._getXmlParser(xml),)
return method


class MyAppTest(unittest.TestCase):

def setUp(self):
self.database = Database()

def tearDown(self):
pass


* test_Login.py - test a business request *
from MyAppTest import MyAppTest, setup

from MyApp import Login


class TestLogin(MyAppTest):
testedBusinessRequest = 'Login'

@setup(testedBusinessRequest)
def test_validParameters(self, parser = None):

FWIW, nose and unittest both provide methods for setting up and
tearing down tests. You should probably look at those first before
rolling your own. At the very least it will give you an idea of how
yours should work.

Cheers
 
D

Diez B. Roggisch

hyperboreean said:
Hi, I am trying to test the business part of a web service. For this I
am using unittest & nose.
I wrote a decorator that should handle the xml test file retrieval, but
it seems I can't get it working with nose.
Here's the code:


* MyApp.py -- base test class *

import os
import unittest

from MyApp.Core import XmlParser


__all__ = ['MyAppTest', 'setup']


PATH = os.path.dirname(__file__) or ''


class setup(object):
"""Decorator to ease the use of xml files in MyApp tests.

The way it works it that it decorates a test method which has a first
default parameter called 'parser' and it overwrites this parameter value
with a XmlParser instance.

The xml file should be located under:
data/testedBusinessRequest/testMethodName.xml
"""
def __init__(self, testedBusinessRequest = ''):
self.testedBusinessRequest =\
testedBusinessRequest.lower()


def _getXmlParser(self, xml):
documentElement = XmlParser.parseXmlStream(xml)
parser = XmlParser.getParser(documentElement)
return parser


def __call__(self, method):

# TODO: error handling here
methodName = method.func_code.co_name
methodName = methodName.split('_')[1]

xmlFolder = self.testedBusinessRequest
xmlFile = '%s.xml' % methodName

path = os.path.join(PATH, 'data',
xmlFolder, xmlFile)

f = open(path)
xml = f.read()
f.close()
method.func_defaults = (self._getXmlParser(xml),)
return method


class MyAppTest(unittest.TestCase):

def setUp(self):
self.database = Database()

def tearDown(self):
pass


* test_Login.py - test a business request *
from MyAppTest import MyAppTest, setup

from MyApp import Login


class TestLogin(MyAppTest):
testedBusinessRequest = 'Login'

@setup(testedBusinessRequest)
def test_validParameters(self, parser = None):
response = Login(self.database, parser).run()
return True



Ok, so the decorator setup should fill the parser parameter with a
XmlParser object. This works well if I add a __main__ and use unittest
to run the tests. But if I use nose, I get the following error:

*TypeError: unbound method __call__() must be called with setup instance
as first argument (got module instance instead)*

Any advices?

Nose works via the func_name parameter of a method/function.

So when you decorate it, you need to make sure that is set properly. One
option is to do something like this:


from functools import wraps

def my_decorator(f):
@wraps(f)
def _d(*args, **kwargs):
return f(*args, **kwargs)

return _d


Diez
 
M

Michele Simionato

Nose works via the func_name parameter of a method/function.

So when you decorate it, you need to make sure that is set properly. One
option is to do something like this:

from functools import wraps

def my_decorator(f):
    @wraps(f)
    def _d(*args, **kwargs):
        return f(*args, **kwargs)

    return _d

Or you can use the decorator module: http://pypi.python.org/pypi/decorator
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,477
Members
44,898
Latest member
BlairH7607

Latest Threads

Top