56

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()?

laserbrain
  • 985
  • 3
  • 10
  • 20

3 Answers3

53

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
elethan
  • 16,408
  • 8
  • 64
  • 87
  • So, there is no kind of mapping involved in pytest? – laserbrain Sep 08 '16 at 16:18
  • @laserbrain I am not sure what you mean by mapping in this case, but my example should work for you if you try it. – elethan Sep 08 '16 at 16:19
  • I mean that the method `test_action()` is mapped on `action()`, so that no instantiation is necessary (like auto magic). – laserbrain Sep 08 '16 at 16:21
  • 4
    @laserbrain and how this automagic would figure out what kind of assertions and checks you want to do? _Explicit is better than implicit_. – Łukasz Rogalski Sep 08 '16 at 16:22
  • @laserbrain I still don't really follow, but afaik in most cases pytest will treat a class method the same as a normal top-level function – elethan Sep 08 '16 at 16:23
  • @elethan I have a class similar to `class TestSuperCool`, but this class has multiple functions similar to `def test_action)`. When I directly run `pytest test_module.py::TestSuperCool::test_action`, it works fine and my tests pass. But when I run `pytest test_module.py::TestSuperCool`, it fails. Do you know how you test individual test Classes in `pytest` rather than each test function? – alpha_989 Feb 19 '18 at 01:14
  • actually no worries.. it seems to be some issue with either my ipython or `ipython` on Windows10. Seems like even after I do a `%reset -s`, it doesnt reset or clear the namespace in ipython. This has been happening repeatedly when I run it in ipython. After I restarted `ipython`, the problem went away. – alpha_989 Feb 19 '18 at 01:59
21

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
Mohsin
  • 536
  • 6
  • 18
Tyler Sebastian
  • 9,067
  • 6
  • 39
  • 62
  • 1
    You're not wrong about the documentation; I thought I knew what I was doing until I tried writing a test suite from scratch. – Corinne Bosley Sep 08 '20 at 12:25
  • better link: https://docs.pytest.org/en/stable/xunit_setup.html – Ray Tayek Apr 17 '21 at 20:12
  • how would i run this: `https://github.com/diffeo/py-nilsimsa/blob/master/nilsimsa/test.py`? i tried like above and got fixture self not found even tho i passed it into my test method – jsky Jul 03 '21 at 15:39
17

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
klapshin
  • 761
  • 8
  • 14