2009-12-31 1 views
14

Sto scrivendo un modulo Python che include una determinata API di servizi Web. È tutto REST, quindi relativamente semplice da implementare.Utilizzo di SimpleHTTPServer per il test dell'unità

Tuttavia, ho riscontrato un problema quando si tratta di test delle unità: poiché non eseguo i servizi per cui ho creato questo modulo, non voglio batterli, ma allo stesso tempo, ho bisogno di recuperare dati per eseguire i miei test. Ho guardato SimpleHTTPServer, che sarebbe OK.

Ho risolto parte del problema che avevo, ma ora, poiché non riesco a terminare il thread, ottengo problemi con "indirizzo già in uso" quando si avvia l'applicazione di test più di una volta.

Ecco alcuni esempi di codice

PORT = 8001 

handler = SimpleHTTPServer.SimpleHTTPRequestHandler 

httpd = SocketServer.TCPServer(("", PORT), handler) 

httpd_thread = threading.Thread(target=httpd.serve_forever) 
httpd_thread.setDaemon(True) 
httpd_thread.start() 

api_data = urllib.urlopen("http://localhost:8001/post/index.json") 
print "Data start:" 
print json.load(api_data) 

Dove "index.json" è un file JSON finta che ho fatto, che sostituisce la cosa reale. Come posso pulire le cose con garbo dopo la fine del programma?

+0

SimpleHTTPServer dovrebbe essere davvero il modo più semplice. Che tipo di problemi stai avendo? – balpha

+0

Ho riformulato le cose, spero che ora sia più chiaro. – Einar

risposta

11

Provare a usare un subclass of TCPServer with allow_reuse_address set True:

class TestServer(SocketServer.TCPServer): 
    allow_reuse_address = True 

... 
httpd = TestServer(("", PORT), handler) 
+0

geniale! bello e semplice – Claudiu

+0

Questo non ha funzionato per me, ma sono stato in grado di risolvere questo problema impostando SocketServer in un metodo setUpClass invece del metodo setUp. L'errore di indirizzo in uso sembra avvenire la seconda volta che viene chiamato il metodo setUp (che si verifica quando viene eseguito il secondo test). – mlissner

4

Utilizziamo un server costruito su wsgiref. http://docs.python.org/library/wsgiref.html

È molto semplice aggiungere funzionalità a questo server quando vengono aggiunti i test di unità.

Avvia il server con subprocess. http://docs.python.org/library/subprocess.html?highlight=subprocess#module-subprocess

Non utilizziamo thread per questo tipo di test. Perché? (1) Il nostro server di test unitario è piuttosto complesso e vorremmo tenerlo completamente isolato dalle applicazioni client. (2) Le nostre applicazioni client saranno processi separati su hardware separato, dobbiamo essere sicuri di avere aspettative realistiche in termini di prestazioni per quella configurazione. (3) È più semplice. (4) È portatile su tutte le piattaforme. (5) È banale passare da test di unità stand-alone a test di integrazione con un server simile alla produzione già in esecuzione.

In realtà abbiamo una piccola applicazione WSGI che rende l'arresto del server in un modo ragionevolmente controllato in modo che i registri vengano arrestati correttamente.

+0

In effetti, sembra che il sottoprocesso possa essere una buona alternativa. Investigherà ulteriormente. – Einar

4

thread vecchio ma le risposte qui non mi ha aiutato, sto usando HTTPServer, e chiudendo dopo ogni test di unità (per impostazione predefinita HTTPServer ha allow_reuse_address = 1 set). Tuttavia ho ancora trovato il problema già in uso dopo aver chiamato shutdown. Ho risolto il problema utilizzando:

from BaseHTTPServer import HTTPServer 

class MyHTTPServer(HTTPServer): 
    def shutdown(self): 
     self.socket.close() 
     HTTPServer.shutdown(self) 

Non sai perché questo non si verifica di default? Può essere che questo non sia ottimale?