Testing class methods with pytest

The pytest documentation lists various examples for test cases. Most of them show feature checking. But Im missing an example of how to test classes and class methods. Suppose we have the following class in the cool.py module that we like to test:

 class SuperCool(object): def action(self, x): return x * x 

What should the corresponding test class look like in tests/test_cool.py ?

 class TestSuperCool(): def test_action(self, x): pass 

How can test_action() be used to test action() ?

+24
python pytest
source share
4 answers

All you need to do to test the class method is an instance of this class and calls the method on this instance:

 def test_action(self): sc = SuperCool() assert sc.action(1) == 1 
+22
source share

Well, one way is to simply create your object in the test method and interact with it from there:

 def test_action(self, x): o = SuperCool() assert o.action(2) == 4 

You can obviously use something like the classic setup and teardown test using the following methods: http://doc.pytest.org/en/latest/xunit_setup.html

I am not 100% sure how they are used because the documentation for pytest is terrible.

Edit: yes, obviously, if you are doing something like

 class TestSuperCool(): def setup(self): self.sc = SuperCool() ... # test using self.sc down here 
+9
source share

I would use any devices only for creating a test environment (for example, connecting to a database) or parameterizing data.

If your data is relatively trivial, you can define it inside the test system:

 def test_action_without_fixtures(): sc = SuperCool() sc.element = 'snow' sc.melt() assert sc.element == 'water' 

Parameterization example:

 @pytest.mark.parametrize("element, expected", [('snow', 'water'), ('tin', 'solder')]) def test_action_with_parametrization(element, expected): sc = SuperCool() sc.element = element sc.melt() assert sc.element == expected 
+4
source share

If initializing a class is expensive, but you need to run many paramaterized tests for a class method, you can change the method definition to allow external input. Then you can initialize once outside the test cycle and run as many methods as you need for the method. For example:

Instead of this:

 class SuperCool(): def action(self): return self.attribute ** 2 

Rewrite to allow external input:

 class SuperCool(): def action(self, x=None): if x is None: x = self.attribute return x ** 2 

Your test script may now look like this:

 sc = SuperCool() @pytest.mark.parametrize("x, y", [(1, 1), (2, 4)]) def test_action_with_parametrization(x, y): assert sc.action(x) == y 

But I'm not an experienced programmer, so hopefully this is not an XD anti-pattern

0
source share

All Articles