<div dir="ltr">...there are bunches of text books which talk about testing strategies for state vs. data driven finite state machines...<div>many approaches...</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Mar 29, 2015 at 2:14 PM, dpb dpb <span dir="ltr"><<a href="mailto:dpb.mediamath@gmail.com" target="_blank">dpb.mediamath@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">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. <div><br></div><div>I prefer to try to arrange things so that each test function has a single, reportable assertion for any given collection of parameters.<div><br></div><div>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.</div></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Mar 29, 2015 at 2:09 PM, holger krekel <span dir="ltr"><<a href="mailto:holger@merlinux.eu" target="_blank">holger@merlinux.eu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>On Sun, Mar 29, 2015 at 12:38 -0400, dpb dpb wrote:<br>
> Thanks to both of you.<br>
><br>
> I understand that it's normally the case to want complete isolation between<br>
> tests.<br>
><br>
> But on occasion it's useful to run tests on a series of cumulative changes<br>
> to state. That means forfeiting test independence, or anyway building it<br>
> into the sequence in which tests are run. The alternatives seem to be<br>
> placing many asserts into each test function, or running tests based on<br>
> simulated data.<br>
><br>
> I see that I can keep track cumulative changes in state pretty simply,<br>
> using a non-test class (rather than the test class) to define the<br>
> state-bearing object.<br>
<br>
</span>Yes, more precisely you can do something like this:<br>
<br>
import pytest<br>
<br>
class IncState:<br>
""" you can store state on attributes and pass them from test to test. """<br>
<br>
@pytest.fixture(scope="module")<br>
def incstate():<br>
return IncState()<br>
<br>
def test_one(incstate):<br>
incstate.x = 1<br>
<br>
def test_two(incstate):<br>
assert incstate.x == 1<br>
incstate.x += 1<br>
<br>
def test_three(incstate):<br>
assert incstate.x == 2<br>
<br>
With pytest it's safe to do it because it guarantees execution in source order.<br>
Other test runners depend on dictionary order (of the module globals() or a class dict)<br>
and thus are typically less predictable. Of course this pattern does violate test<br>
isolation and i have very rarely used the above incremental pattern when i wanted<br>
to avoid having one large test containing all the increments. Rarely<br>
means twice or so in my 15 years of writing thousands of tests.<br>
<br>
best,<br>
holger<br>
<div><div><br>
<br>
> - dpb<br>
><br>
> On Sun, Mar 29, 2015 at 12:01 PM, Ned Batchelder <<a href="mailto:ned@nedbatchelder.com" target="_blank">ned@nedbatchelder.com</a>><br>
> wrote:<br>
><br>
> > On 3/29/15 4:57 AM, dpb dpb wrote:<br>
> ><br>
> > Something I do not see addressed explicitly in the Pytest docs is this<br>
> > behavior: Unlike normal class writing in Python 3, changing the value of a<br>
> > class attribute in one function does not leave it changed in test functions<br>
> > that are called subsequently:<br>
> ><br>
> > As Holger mentioned, a new TestExample instance is created for each<br>
> > test. This is how all the test runners work, because you want isolation<br>
> > between your tests. One of the principles of the xUnit style of testing is<br>
> > that each test is independent of all other tests. You want to be able to<br>
> > run a single test and not have it depend on the results of previous tests.<br>
> ><br>
> > --Ned.<br>
> ><br>
> > # test_pytest_class_attributes.py<br>
> >> """Test the setting of class attributes."""<br>
> >> class TestExample():<br>
> >> def setup(self):<br>
> >> self.attribute = 1<br>
> ><br>
> ><br>
> >> def test_changing_attr(self):<br>
> >> """Change attribute on object."""<br>
> >> self.attribute = 2<br>
> >> assert self.attribute == 2<br>
> ><br>
> ><br>
> >> def test_attr_is_changed(self):<br>
> >> """Assume attribute is changed."""<br>
> >> assert self.attribute == 2<br>
> ><br>
> ><br>
> >> def test_attr_is_unchanged(self):<br>
> >> """Assume attribute is unchanged."""<br>
> >> assert self.attribute == 1<br>
> ><br>
> ><br>
> > Output:<br>
> ><br>
> > $ py.test test_pytest_class_attributes.py -v<br>
> >> ============================= test session starts<br>
> >> ==============================<br>
> >> platform darwin -- Python 3.4.1 -- py-1.4.25 -- pytest-2.6.3 --<br>
> >> /Users/dpb/py34/bin/python3.4<br>
> >> collected 3 items<br>
> >> test_pytest_class_attributes.py::TestExample::test_changing_attr PASSED<br>
> >> test_pytest_class_attributes.py::TestExample::test_attr_is_changed FAILED<br>
> >> test_pytest_class_attributes.py::TestExample::test_attr_is_unchanged<br>
> >> PASSED<br>
> >> =================================== FAILURES<br>
> >> ===================================<br>
> >> _______________________ TestExample.test_attr_is_changed<br>
> >> _______________________<br>
> >> self = <test_pytest_class_attributes.TestExample object at 0x10dd98ef0><br>
> >> def test_attr_is_changed(self):<br>
> >> """Test whether attribute is changed."""<br>
> >> > assert self.attribute == 2<br>
> >> E assert 1 == 2<br>
> >> E + where 1 = <test_pytest_class_attributes.TestExample object at<br>
> >> 0x10dd98ef0>.attribute<br>
> ><br>
> ><br>
> ><br>
> > test_pytest_class_attributes.py:14: AssertionError<br>
> >> ====================== 1 failed, 2 passed in 0.02 seconds<br>
> >> ======================<br>
> >> $<br>
> ><br>
> ><br>
> > Is there special syntax or some special structure to make class<br>
> > attributes behave In Pytest as they do in an ordinary Python class? Example:<br>
> ><br>
> > # display_class_attributes.py<br>
> >> """Test the setting of class attributes."""<br>
> ><br>
> ><br>
> >> class TestExample():<br>
> >> def __init__(self):<br>
> >> self.attribute = 1<br>
> ><br>
> ><br>
> >> def test_changing_attr(self):<br>
> >> """Change attribute on object."""<br>
> >> self.attribute = 2<br>
> >> assert self.attribute == 2<br>
> >> print('Finished test_changing_attr.\n')<br>
> ><br>
> ><br>
> >> def test_attr_is_changed(self):<br>
> >> """Test whether attribute is changed."""<br>
> >> assert self.attribute == 2<br>
> >> print('Finished test_attr_is_changed.\n')<br>
> ><br>
> ><br>
> >> def test_attr_is_unchanged(self):<br>
> >> """Test whether attribute is unchanged."""<br>
> >> assert self.attribute == 1<br>
> >> print('Finiahed test_attr_is_unchanged.\n')<br>
> ><br>
> ><br>
> >> t = TestExample()<br>
> >> t.test_changing_attr()<br>
> >> t.test_attr_is_changed()<br>
> >> t.test_attr_is_unchanged()<br>
> ><br>
> ><br>
> > Output:<br>
> ><br>
> > > $ python display_class_attributes.py<br>
> > ><br>
> > > self.attribute == 2: True<br>
> > ><br>
> > > self.attribute == 2: True<br>
> > ><br>
> > > self.attribute == 1: False<br>
> > ><br>
> > > $<br>
> ><br>
> > Thanks.<br>
> ><br>
> > - dpb<br>
> ><br>
> ><br>
> > _______________________________________________<br>
</div></div>> > testing-in-python mailing listtesting-in-python@lists.idyll.orghttp://<a href="http://lists.idyll.org/listinfo/testing-in-python" target="_blank">lists.idyll.org/listinfo/testing-in-python</a><br>
<span>> ><br>
> ><br>
> ><br>
> > _______________________________________________<br>
> > testing-in-python mailing list<br>
> > <a href="mailto:testing-in-python@lists.idyll.org" target="_blank">testing-in-python@lists.idyll.org</a><br>
> > <a href="http://lists.idyll.org/listinfo/testing-in-python" target="_blank">http://lists.idyll.org/listinfo/testing-in-python</a><br>
> ><br>
> ><br>
<br>
> _______________________________________________<br>
> testing-in-python mailing list<br>
> <a href="mailto:testing-in-python@lists.idyll.org" target="_blank">testing-in-python@lists.idyll.org</a><br>
> <a href="http://lists.idyll.org/listinfo/testing-in-python" target="_blank">http://lists.idyll.org/listinfo/testing-in-python</a><br>
<br>
<br>
</span><div><div>--<br>
about me: <a href="http://holgerkrekel.net/about-me/" target="_blank">http://holgerkrekel.net/about-me/</a><br>
contracting: <a href="http://merlinux.eu" target="_blank">http://merlinux.eu</a><br>
</div></div></blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
testing-in-python mailing list<br>
<a href="mailto:testing-in-python@lists.idyll.org">testing-in-python@lists.idyll.org</a><br>
<a href="http://lists.idyll.org/listinfo/testing-in-python" target="_blank">http://lists.idyll.org/listinfo/testing-in-python</a><br>
<br></blockquote></div><br></div>