[Twisted-Python] Stopping Reactor in UnitTest Callback

Hey there, I'm trying to start and stop a twisted server in a unittest: http://dpaste.org/qwaUt/ . Calling reactor.stop() in the callback causes a KeyboardInterrupt exception, and tearDown gets never executed, as it's probably waiting for the test to finish. After calling `trial d.py` you need to run a `telnet localhost 8007` manually to stimulate the connectionMade() method. I'm totally stuck and would appreciate any help. Thanks Fabian

On 07:58 pm, fabian.rothfuchs@googlemail.com wrote:
Why? This isn't the typical way to write unit tests for Twisted-based code. The reactor is started and stopped by trial as necessary. Your code should just expect that it is running and let trial stop it when it is time to stop. If you have asynchronous code to test, you return a Deferred from a test method and the test completes when the Deferred fires. Not when the reactor stops. Also, a lot of people have come to dislike this style of test, instead preferring to use test doubles that don't involve real I/O or time so that they can completely test the logic of their code deterministically - thus also without ever running a real reactor or needing to use the "return a Deferred from a test method" feature of trial. Jean-Paul

I'm in the dilemma of using both - Django and Twisted. My goal is to have Django initialising the test (python manage.py test <appname>), instead of trial, as it will setup the whole test environment (I.e. Creates a db copy, allows per-model testing, follows certain conventions, etc). As to that I'm trying to find a way how to start/stop the reactor from the test, as trial is not executed. Do you have an idea or an approach how this could be realised? Thanks Fabian On 1/10/13 9:51 PM, "exarkun@twistedmatrix.com" <exarkun@twistedmatrix.com> wrote:

On Sat, Jan 12, 2013 at 2:00 PM, Fabian Rothfuchs <fabian.rothfuchs@googlemail.com> wrote:
One thing that works for us is to have our Twisted-using tests subclass testtools.TestCase[1], and declare that they are asynchronous Twisted tests. e.g. class TestTwistedAPI(testtools.TestCase): run_tests_with = AsynchronousDeferredRunTest def test_foo(self): d = foo.some_api() d.addCallback(self.assertEqual, "bar") return d Of course, not inheriting from Django's TestCase means you lose a lot of its implicit set-up, but most of that can be called from public APIs. We have a very rough project that does some of the necessaries.[2] You could probably use twisted.trial.unittest.TestCase instead of testtools.TestCase. cheers, jml [1] http://pypi.python.org/pypi/testtools [2] http://pypi.python.org/pypi/djangofixture

On Sat, Jan 12, 2013 at 9:00 AM, Fabian Rothfuchs < fabian.rothfuchs@googlemail.com> wrote:
The functionality to start/stop the reactor when a test returns a Deferred is part of twisted.trial.unittest.TestCase, which subclasses Python's unittest.TestCase. As a result you don't need to use the trial command-line tool, you can use any Python test runner that knows about Python's TestCase; just make sure to subclass twisted.trial.unittest.TestCase, and your test will support running the reactor for you when you return a Deferred. Or, if possible, you can avoid using the reactor at all; some approaches (as mentioned by Jean-Paul) are described in the trial documentation: http://twistedmatrix.com/documents/current/core/howto/trial.html -- Itamar Turner-Trauring, Future Foundries LLC http://futurefoundries.com/ — Twisted consulting, training and support.

Yes, I thought so, too. Indeed it happens that the reactor is started automatically, but after the test succeeds, it's not being stopped (only chance is to kill 9 it). I'm afraid I need to use the reactor, as I'd like to make automatic end-to-end tests within my application, going from the workflow until a dummy server, returning the data that was sent by the protocol back to the test-callback. From: Itamar Turner-Trauring <itamar@futurefoundries.com> Reply-To: Twisted general discussion <twisted-python@twistedmatrix.com> Date: Sunday, January 13, 2013 12:31 AM To: Twisted general discussion <twisted-python@twistedmatrix.com> Subject: Re: [Twisted-Python] Stopping Reactor in UnitTest Callback On Sat, Jan 12, 2013 at 9:00 AM, Fabian Rothfuchs <fabian.rothfuchs@googlemail.com> wrote:
The functionality to start/stop the reactor when a test returns a Deferred is part of twisted.trial.unittest.TestCase, which subclasses Python's unittest.TestCase. As a result you don't need to use the trial command-line tool, you can use any Python test runner that knows about Python's TestCase; just make sure to subclass twisted.trial.unittest.TestCase, and your test will support running the reactor for you when you return a Deferred. Or, if possible, you can avoid using the reactor at all; some approaches (as mentioned by Jean-Paul) are described in the trial documentation: http://twistedmatrix.com/documents/current/core/howto/trial.html -- Itamar Turner-Trauring, Future Foundries LLC http://futurefoundries.com/ Twisted consulting, training and support. _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

On 07:58 pm, fabian.rothfuchs@googlemail.com wrote:
Why? This isn't the typical way to write unit tests for Twisted-based code. The reactor is started and stopped by trial as necessary. Your code should just expect that it is running and let trial stop it when it is time to stop. If you have asynchronous code to test, you return a Deferred from a test method and the test completes when the Deferred fires. Not when the reactor stops. Also, a lot of people have come to dislike this style of test, instead preferring to use test doubles that don't involve real I/O or time so that they can completely test the logic of their code deterministically - thus also without ever running a real reactor or needing to use the "return a Deferred from a test method" feature of trial. Jean-Paul

I'm in the dilemma of using both - Django and Twisted. My goal is to have Django initialising the test (python manage.py test <appname>), instead of trial, as it will setup the whole test environment (I.e. Creates a db copy, allows per-model testing, follows certain conventions, etc). As to that I'm trying to find a way how to start/stop the reactor from the test, as trial is not executed. Do you have an idea or an approach how this could be realised? Thanks Fabian On 1/10/13 9:51 PM, "exarkun@twistedmatrix.com" <exarkun@twistedmatrix.com> wrote:

On Sat, Jan 12, 2013 at 2:00 PM, Fabian Rothfuchs <fabian.rothfuchs@googlemail.com> wrote:
One thing that works for us is to have our Twisted-using tests subclass testtools.TestCase[1], and declare that they are asynchronous Twisted tests. e.g. class TestTwistedAPI(testtools.TestCase): run_tests_with = AsynchronousDeferredRunTest def test_foo(self): d = foo.some_api() d.addCallback(self.assertEqual, "bar") return d Of course, not inheriting from Django's TestCase means you lose a lot of its implicit set-up, but most of that can be called from public APIs. We have a very rough project that does some of the necessaries.[2] You could probably use twisted.trial.unittest.TestCase instead of testtools.TestCase. cheers, jml [1] http://pypi.python.org/pypi/testtools [2] http://pypi.python.org/pypi/djangofixture

On Sat, Jan 12, 2013 at 9:00 AM, Fabian Rothfuchs < fabian.rothfuchs@googlemail.com> wrote:
The functionality to start/stop the reactor when a test returns a Deferred is part of twisted.trial.unittest.TestCase, which subclasses Python's unittest.TestCase. As a result you don't need to use the trial command-line tool, you can use any Python test runner that knows about Python's TestCase; just make sure to subclass twisted.trial.unittest.TestCase, and your test will support running the reactor for you when you return a Deferred. Or, if possible, you can avoid using the reactor at all; some approaches (as mentioned by Jean-Paul) are described in the trial documentation: http://twistedmatrix.com/documents/current/core/howto/trial.html -- Itamar Turner-Trauring, Future Foundries LLC http://futurefoundries.com/ — Twisted consulting, training and support.

Yes, I thought so, too. Indeed it happens that the reactor is started automatically, but after the test succeeds, it's not being stopped (only chance is to kill 9 it). I'm afraid I need to use the reactor, as I'd like to make automatic end-to-end tests within my application, going from the workflow until a dummy server, returning the data that was sent by the protocol back to the test-callback. From: Itamar Turner-Trauring <itamar@futurefoundries.com> Reply-To: Twisted general discussion <twisted-python@twistedmatrix.com> Date: Sunday, January 13, 2013 12:31 AM To: Twisted general discussion <twisted-python@twistedmatrix.com> Subject: Re: [Twisted-Python] Stopping Reactor in UnitTest Callback On Sat, Jan 12, 2013 at 9:00 AM, Fabian Rothfuchs <fabian.rothfuchs@googlemail.com> wrote:
The functionality to start/stop the reactor when a test returns a Deferred is part of twisted.trial.unittest.TestCase, which subclasses Python's unittest.TestCase. As a result you don't need to use the trial command-line tool, you can use any Python test runner that knows about Python's TestCase; just make sure to subclass twisted.trial.unittest.TestCase, and your test will support running the reactor for you when you return a Deferred. Or, if possible, you can avoid using the reactor at all; some approaches (as mentioned by Jean-Paul) are described in the trial documentation: http://twistedmatrix.com/documents/current/core/howto/trial.html -- Itamar Turner-Trauring, Future Foundries LLC http://futurefoundries.com/ Twisted consulting, training and support. _______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
participants (5)
-
exarkun@twistedmatrix.com
-
F Rothfuchs
-
Fabian Rothfuchs
-
Itamar Turner-Trauring
-
Jonathan Lange