[TIP] (no subject)

holger krekel holger at merlinux.eu
Sun Mar 29 11:09:11 PDT 2015


On Sun, Mar 29, 2015 at 12:38 -0400, dpb dpb wrote:
> Thanks to both of you.
> 
> I understand that it's normally the case to want complete isolation between
> tests.
> 
> But on occasion it's useful to run tests on a series of cumulative changes
> to state. That means forfeiting test independence, or anyway building it
> into the sequence in which tests are run. The alternatives seem to be
> placing many asserts into each test function, or running tests based on
> simulated data.
> 
> I see that I can keep track cumulative changes in state pretty simply,
> using a non-test class (rather than the test class) to define the
> state-bearing object.

Yes, more precisely you can do something like this:

    import pytest

    class IncState:
        """ you can store state on attributes and pass them from test to test. """

    @pytest.fixture(scope="module")
    def incstate():
        return IncState()

    def test_one(incstate):
        incstate.x = 1

    def test_two(incstate):
        assert incstate.x == 1
        incstate.x += 1

    def test_three(incstate):
        assert incstate.x == 2

With pytest it's safe to do it because it guarantees execution in source order.
Other test runners depend on dictionary order (of the module globals() or a class dict) 
and thus are typically less predictable.  Of course this pattern does violate test
isolation and i have very rarely used the above incremental pattern when i wanted
to avoid having one large test containing all the increments.  Rarely
means twice or so in my 15 years of writing thousands of tests.

best,
holger


> - dpb
> 
> On Sun, Mar 29, 2015 at 12:01 PM, Ned Batchelder <ned at nedbatchelder.com>
> wrote:
> 
> >  On 3/29/15 4:57 AM, dpb dpb wrote:
> >
> >  Something I do not see addressed explicitly in the Pytest docs is this
> > behavior: Unlike normal class writing in Python 3, changing the value of a
> > class attribute in one function does not leave it changed in test functions
> > that are called subsequently:
> >
> >   As Holger mentioned, a new TestExample instance is created for each
> > test.  This is how all the test runners work, because you want isolation
> > between your tests.  One of the principles of the xUnit style of testing is
> > that each test is independent of all other tests.  You want to be able to
> > run a single test and not have it depend on the results of previous tests.
> >
> > --Ned.
> >
> >  # test_pytest_class_attributes.py
> >> """Test the setting of class attributes."""
> >> class TestExample():
> >>     def setup(self):
> >>         self.attribute = 1
> >
> >
> >>     def test_changing_attr(self):
> >>         """Change attribute on object."""
> >>         self.attribute = 2
> >>         assert self.attribute == 2
> >
> >
> >>     def test_attr_is_changed(self):
> >>         """Assume attribute is changed."""
> >>         assert self.attribute == 2
> >
> >
> >>     def test_attr_is_unchanged(self):
> >>         """Assume attribute is unchanged."""
> >>         assert self.attribute == 1
> >
> >
> >  Output:
> >
> >  $ py.test test_pytest_class_attributes.py -v
> >> ============================= test session starts
> >> ==============================
> >> platform darwin -- Python 3.4.1 -- py-1.4.25 -- pytest-2.6.3 --
> >> /Users/dpb/py34/bin/python3.4
> >> collected 3 items
> >> test_pytest_class_attributes.py::TestExample::test_changing_attr PASSED
> >> test_pytest_class_attributes.py::TestExample::test_attr_is_changed FAILED
> >> test_pytest_class_attributes.py::TestExample::test_attr_is_unchanged
> >> PASSED
> >> =================================== FAILURES
> >> ===================================
> >> _______________________ TestExample.test_attr_is_changed
> >> _______________________
> >> self = <test_pytest_class_attributes.TestExample object at 0x10dd98ef0>
> >>     def test_attr_is_changed(self):
> >>         """Test whether attribute is changed."""
> >> >       assert self.attribute == 2
> >> E       assert 1 == 2
> >> E        +  where 1 = <test_pytest_class_attributes.TestExample object at
> >> 0x10dd98ef0>.attribute
> >
> >
> >
> > test_pytest_class_attributes.py:14: AssertionError
> >> ====================== 1 failed, 2 passed in 0.02 seconds
> >> ======================
> >> $
> >
> >
> >  Is there special syntax or some special structure to make class
> > attributes behave In Pytest as they do in an ordinary Python class? Example:
> >
> >  # display_class_attributes.py
> >> """Test the setting of class attributes."""
> >
> >
> >> class TestExample():
> >>     def __init__(self):
> >>         self.attribute = 1
> >
> >
> >>     def test_changing_attr(self):
> >>         """Change attribute on object."""
> >>         self.attribute = 2
> >>         assert self.attribute == 2
> >>         print('Finished test_changing_attr.\n')
> >
> >
> >>     def test_attr_is_changed(self):
> >>         """Test whether attribute is changed."""
> >>         assert self.attribute == 2
> >>         print('Finished test_attr_is_changed.\n')
> >
> >
> >>     def test_attr_is_unchanged(self):
> >>         """Test whether attribute is unchanged."""
> >>         assert self.attribute == 1
> >>         print('Finiahed test_attr_is_unchanged.\n')
> >
> >
> >> t = TestExample()
> >> t.test_changing_attr()
> >> t.test_attr_is_changed()
> >> t.test_attr_is_unchanged()
> >
> >
> >  Output:
> >
> >  > $ python display_class_attributes.py
> > >
> > > self.attribute == 2: True
> > >
> > > self.attribute == 2: True
> > >
> > > self.attribute == 1: False
> > >
> > > $
> >
> >  Thanks.
> >
> >  - dpb
> >
> >
> > _______________________________________________
> > testing-in-python mailing listtesting-in-python at lists.idyll.orghttp://lists.idyll.org/listinfo/testing-in-python
> >
> >
> >
> > _______________________________________________
> > testing-in-python mailing list
> > testing-in-python at lists.idyll.org
> > http://lists.idyll.org/listinfo/testing-in-python
> >
> >

> _______________________________________________
> testing-in-python mailing list
> testing-in-python at lists.idyll.org
> http://lists.idyll.org/listinfo/testing-in-python


-- 
about me:    http://holgerkrekel.net/about-me/
contracting: http://merlinux.eu



More information about the testing-in-python mailing list