[TIP] (no subject)

dpb dpb dpb.mediamath at gmail.com
Sun Mar 29 12:14:29 PDT 2015


Yes, that's what I had in mind — a separate non-test class that can be
passed in as a fixture or instantiated and assigned to a module-level
variable.

I prefer to try to arrange things so that each test function has a single,
reportable assertion for any given collection of parameters.

As long as I know the test functions will always be run in the prescribed
order, I can pass option -x to py.test when I run it, and it will exclude
all tests after the first failing one.

On Sun, Mar 29, 2015 at 2:09 PM, holger krekel <holger at merlinux.eu> wrote:

> 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/testing-in-python/attachments/20150329/d3ae2eac/attachment.htm>


More information about the testing-in-python mailing list