How to write a nose2 plugin that shares different types of tests?

I am writing a plugin that will separately process my unit tests, functional tests and integration tests.
My test folder will have the following structure:

/ tests
-/unit
-/functional
-/integration

Each unit test will be in the device directory, and each functional test will be in the functional directory, and so on.

I am familiar with the Layers plugin, but I would prefer my tests to comply with the convention.
Which hook should be used to enter the appropriate layer before running the tests? Should it be loadTestsFromModule hook? Can you show me an example?

I would also like to split the final report for each type of test.
Which hook should I use?

+4
source share
3 answers

You do not need to write a plugin, the built-in attr module is designed for this purpose. However, this does not depend on your file hierarchy. Instead, you mark individual tests as a unit, functionality, or integration. It will look like this:

from nose.plugins import attrib @attrib.attr("functional") class FunctionalTestCase(unittest.TestCase): pass 

To perform functional tests only, follow these steps:

 nosetests -a functional 

If I were to create this test layout, I probably would have 3 subclasses of unittest.TestCase already marked with "unit", "functional" and "integration". New tests can easily inherit the correct test type.

+1
source

I got this working with nose2 using the nose2 attrib plugin for detection and some code copied from the nose1 attrib plugin that allowed me to decorate my tests.

Using the nose2 attrib plugin

You will see the nose2 attrib plugin , which allows you to define custom attributes for test functions and classes.

For this to work, you must specify the attributes of the tests after defining the test function.

 class MyTestCase(unittest.TestCase): def test_function(self): self.assertEqual(1+1, 2) test_function.custom_attr1 = True test_function.custom_attr2 = ['foo', 'bar'] 

You can then run the filtered test suite by specifying -A or --attribute as the --attribute command line nose2 to display the attributes you need to map to your test suite. You can even use the -E or --eval-attribute command-line argument , which allows more complex Python expressions to match test attributes.

eg. nose2 -v -A custom_attr1
will run all tests that have custom_attr1 specified with the truth .

Using decorators to specify test attributes

This was not enough for me because I did not like the idea of ​​defining these attributes on tests after they were defined. I wanted to use a decorator instead, but nose2 did not have a built-in decorator for this.

I went to the source code of nose1 for my attrib plugin and copied the source for the attr function.

 def attr(*args, **kwargs): """Decorator that adds attributes to classes or functions for use with the Attribute (-a) plugin. """ def wrap_ob(ob): for name in args: setattr(ob, name, True) for name, value in kwargs.iteritems(): setattr(ob, name, value) return ob return wrap_ob 

I put this in the test/attrib_util.py . Now I can specify the attributes using the decorator. My source code for the test class above can be converted to (IMO) easier:

 from test.attrib_util import attr class MyTestCase(unittest.TestCase): @attr('custom_attr1', custom_attr2=['foo', 'bar']) def test_function(self): self.assertEqual(1+1, 2) 

You will notice that attributes can be specified as args or kwargs; all args will get the default value True .

You can also use this attr decorator in a test class or base class, and the attributes will apply to all test functions defined internally. This makes it very easy to separate the unit and functional tests.

 from test.attrib_util import attr @attr('functional') class FunctionalTestCase(unittest.TestCase): pass class MyFunctionalCase(FunctionalTestCase): def test_function(self): print 'this will be considered a "functional" test function' 
+1
source

If you already have tests sorted by directories (as you mentioned), you can write a plugin that uses the wantDirectory method.

 import os.path from nose.plugins import Plugin class TestCategory(Plugin): """ Run tests in a defined category (unittest, functional, integration. Always runs uncategorized tests. """ def wantDirectory(self, dirname): dirname = os.path.basename(dirname) if (dirname in ('unit', 'functional', 'integration') and dirname != self.category): return False return None 

You want to write the options() and configure() methods for this plug-in to deal with turning it on and off and displaying the user's choice of category. When launching the networks, you choose from three categories:

 nosetests --category functional 

Since only one test category is launched at a time, you will receive a separate report for each test category. Of course, you can always run all the tests without including this plugin.

(adding as another answer, because this is a completely different approach).

0
source

Source: https://habr.com/ru/post/1483486/


All Articles