2013-04-13 7 views
8

Sto cercando di implementare uno scenario molti-a-molti utilizzando l'ORM peewee python e mi piacerebbe alcuni test unitari. Il tutorial di Peewee è ottimo ma presuppone che il database sia definito a livello di modulo, quindi tutti i modelli lo stanno utilizzando. La mia situazione è diversa: non ho un file di codice sorgente (un modulo dal punto di vista di Python) con test che eseguo esplicitamente, sto usando nose che raccoglie i test da quel file e li esegue.Database sqlite personalizzato per unit test per il codice che utilizza peewee ORM

Come si utilizza un database personalizzato solo per i modelli istanziati nei test (che vengono eseguiti dal naso)? Il mio obiettivo è utilizzare un database in memoria solo per i test, per accelerare il processo di test.

+0

Sono curioso anche di questo. [PyORMish] (http://pyormish.nullism.com) può gestire questo impostando il valore 'db_config' sul Modello prima di eseguire il test, e quindi reimpostandolo nel metodo teardown. Mi aspetto che questo funzioni anche con Peewee. –

risposta

11

Ho appena inviato un commit oggi che rende tutto più semplice.

la correzione è nella forma di un contesto Manager, che consente di sovrascrivere il database di un modello:

from unittest import TestCase 
from playhouse.test_utils import test_database 
from peewee import * 

from my_app.models import User, Tweet 

test_db = SqliteDatabase(':memory:') 

class TestUsersTweets(TestCase): 
    def create_test_data(self): 
     # ... create a bunch of users and tweets 
     for i in range(10): 
      User.create(username='user-%d' % i) 

    def test_timeline(self): 
     with test_database(test_db, (User, Tweet)): 
      # This data will be created in `test_db` 
      self.create_test_data() 

      # Perform assertions on test data inside ctx manager. 
      self.assertEqual(Tweet.timeline('user-0') [...]) 

     # once we exit the context manager, we're back to using the normal database 

Vedere il documentation e dare un'occhiata al l'esempio casi di test:

+0

Un test banale funziona bene con peewee-2.1.1, grazie. – AnonymousLurker

+1

Questa è ancora la strada da percorrere quando si tratta di test? –

6

Per non includere il gestore del contesto in ogni caso di test, sovrascrivere il metodo run.

# imports and db declaration 

class TestUsersTweets(TestCase): 
    def run(self, result=None): 
     with test_database(test_db, (User, Tweet)): 
      super(TestUsersTweets, self).run(result) 

    def test_timeline(self): 
     self.create_test_data() 
     self.assertEqual(Tweet.timeline('user-0') [...]) 
5

ho preso le grandi risposte da @coleifer e @avalanchy e li portò un ulteriore passo avanti.

Al fine di evitare l'override del metodo di esecuzione su ogni TestCase sottoclasse, è possibile utilizzare una classe di base ... e mi piace anche l'idea di non dover scrivere le ogni classe modello con cui lavoro, così sono venuto con questo

import unittest 
import inspect 
import sys 
import peewee 
from abc import ABCMeta 
from playhouse.test_utils import test_database 
from business_logic.models import * 

test_db = peewee.SqliteDatabase(':memory:') 


class TestCaseWithPeewee(unittest.TestCase): 
    """ 
    This abstract class is used to "inject" the test database so that the tests don't use the real sqlite db 
    """ 

    __metaclass__ = ABCMeta 

    def run(self, result=None): 
     model_classes = [m[1] for m in inspect.getmembers(sys.modules['business_logic.models'], inspect.isclass) if 
         issubclass(m[1], peewee.Model) and m[1] != peewee.Model] 
     with test_database(test_db, model_classes): 
      super(TestCaseWithPeewee, self).run(result) 

così, ora posso solo ereditare da TestCaseWithPeewee e non devono preoccuparsi di altro che il test

0

Quando si utilizza test_database ho incontrato problemi con test_db non essere inizializzato:

nose.proxy.Exception: Error, database not properly initialized before opening connection -------------------- >> begin captured logging << -------------------- peewee: DEBUG: ('SELECT "t1"."id", "t1"."name", "t1"."count" FROM "counter" AS t1', []) --------------------- >> end captured logging << ---------------------

Alla fine ho risolto questo passando create_tables=True in questo modo:

def test_timeline(self): with test_database(test_db, (User, Tweet), create_tables=True): # This data will be created in `test_db` self.create_test_data()

Secondo the docscreate_tables dovrebbe default True ma sembra che non è il caso nella versione più recente di peewee.

+0

Problema github creato https: // github.com/coleifer/peewee/issues/741 – coleifer

+0

Il traceback indica che il database di test si trova in uno stato "differito". Il database di test deve essere inizializzato con un nome di database. – coleifer