views:

56

answers:

4

Hi there,

I'm programming an HTTP proxy in Python (transparent proxy for request/response monitoring). But as a TDD adopter, I'm starting the project with HTTP inputs that should be caught by a TCP server. But, as any server, it must run within an event loop, so that it can listen in a specific port.

Well, since starting the event loop will keep the interpreter inside the loop, after starting the server from a unit test, I cannot come back to the test to send an HTTP request to this server.

What do you guys recommend me to design so that I can run the server and come back to the unit test to test it? Use threads? Zero-timeouts?

Thanks!

Diogo

A: 

unit testing is more about testing things at the function level, an integration test is more of an "end to end" type thing. If your function has dependencies that you can't really get around, it is a good time to find a mocking framework for your platform.

Matt Briggs
Thanks, Matt, but my actual question was which is the best way to start a server from a unit test - non-blocking event loop or multithreading.
diogobaeder
A: 

You need to refactor whatever your loop listens to so that you can replace that with a fake or mock. If that object is not derived from an interface, you might have to write a wrapper object that you can fake or mock.

Regarding the looping problem: Multithreading would indeed be a possible solution.

Adrian Grigore
I'm thinking about going multithreading, it seems to be the best solution, indeed... and maybe mocking the socket module, also, as you said, as it's a neighbour to the object that I want to test.
diogobaeder
A: 

The most natural way: write your test clients using the same event handling framework as your server (no different than writing any other client/server code).

Then, each unit test would look roughly like:

  1. Register the test server's socket listener
  2. Register the test client's socket connector
  3. Start the event loop, waiting for the interaction to complete (or time out)
  4. Process/report the test results

In most cases, it would be the responsibility the test client to determine when the test is complete and signal the event loop to exit, but this can depend on the test. Your would also probably want to write standardized timeout handlers to fail the test (same as you would with blocking I/O).

Piet Delport
Thanks, but, as I told Matt, my question is regarding the best choice to avoid the server to block the entire interpreter, so that I can get back to the unit test to test the server.
diogobaeder
The server doesn't block the interpreter, the event loop does: and if you move your test client into the event loop, that's no longer a problem. You can look at e.g. Twisted Python's tests for widespread application of this kind of thing.
Piet Delport
+1  A: 

The loop itself shouldn't be covered by the TDD. You can test mostly everything else, and, given that the code within the loop is properly isolated, you can be confident on your code.

That is, if your loop is reduced to simply

while keep_serving:
    keep_serving = handle_events(...)

you can test handle_events and its components, and the loop itself is trivial.

Also, you'll be faced with having to test connections, sockets, etc. I recommend the excellent Mocker module, by Gustavo Niemeyer. It's very handy (if non-trivial to fully understand at first sight).

rbp
Well, this is a very interesting aproach; I haven't thought of just not start the loop, but instead mock the request/response being passed to the handlers. It seems like a much easier solution than actually starting the server and having the interpreter stuck there. I'll also consider trying Mocker, as I've only used mockito till now. Thanks!
diogobaeder