Testing class methods with pytest

大兔子大兔子 提交于 2021-02-17 08:30:32

问题


In the documentation of pytest various examples for test cases are listed. Most of them show the test of functions. But I’m missing an example of how to test classes and class methods. Let’s say we have the following class in the module cool.py we like to test:

class SuperCool(object):

    def action(self, x):
        return x * x

How does the according test class in tests/test_cool.py have to look?

class TestSuperCool():

    def test_action(self, x):
        pass

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


回答1:


All you need to do to test a class method is instantiate that class, and call the method on that instance:

def test_action(self):
    sc = SuperCool()
    assert sc.action(1) == 1



回答2:


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

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

You can apparently use something like the classic setup and teardown style unittest using the methods here: http://doc.pytest.org/en/latest/xunit_setup.html

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

Edit: yeah so apparently if you do something like

class TestSuperCool():
    def setup(self):
        self.sc = SuperCool()

    ... 

    # test using self.sc down here



回答3:


I would use any fixtures only to create test environment (like database connection) or data parametrization.

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

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

Example with parametrization:

@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:


If the class initialization is expensive but you need to run lots of paramaterized tests on a class method, you can change the method definition to allow external inputs. Then you can initialize once outside the test loop and run as many tests as you like on 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

Now your test script can look like:

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 isn't some kind of anti-pattern XD



来源:https://stackoverflow.com/questions/39395731/testing-class-methods-with-pytest

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!