2013-04-13 16 views
8

Próbuję zaimplementować scenariusz wiele do wielu za pomocą pythona peewee i chciałbym niektórych testów jednostkowych. Samouczek Peewee jest świetny, ale zakłada, że ​​baza danych jest zdefiniowana na poziomie modułu, a następnie wszystkie modele go używają. Moja sytuacja jest inna: nie mam pliku kodu źródłowego (moduł z punktu widzenia Pythona) z testami, które uruchamiam jawnie, używam nosa, który zbiera testy z tego pliku i uruchamia je.Niestandardowa baza danych sqlite dla testów jednostkowych dla kodu przy użyciu peewee ORM

Jak używać niestandardowej bazy danych tylko dla modeli tworzonych w testach (które są uruchamiane przez nos)? Moim celem jest wykorzystanie bazy danych w pamięci tylko do testów, aby przyspieszyć proces testowania.

+0

Jestem także ciekawy tego. [PyORMish] (http://pyormish.nullism.com) poradzi sobie z tym przez ustawienie wartości 'db_config' na Modelu przed uruchomieniem testu, a następnie ustawienie go z powrotem w metodzie odrywania. Spodziewam się, że będzie to również działać z Peewee. –

Odpowiedz

11

Po prostu przeforsowałem dzisiaj zatwierdzenie, które ułatwia to zadanie.

Rozwiązaniem jest w postaci menedżera kontekstowego, który pozwala zastąpić bazę modelu:

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 

Patrz documentation i spojrzeć na przykład testami:

+0

Trywialny test działa dobrze z peewee-2.1.1, dziękuję. – AnonymousLurker

+1

Czy to nadal jest droga do testowania? –

6

Aby nie uwzględniać menedżera kontekstu w każdym przypadku testowym, należy nadpisać metodę 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

wziąłem wielkie odpowiedzi od @coleifer i @avalanchy i wziął je jeden krok dalej.

W celu uniknięcia przesłanianie metody działać na każdym TestCase podklasy, można użyć klasy bazowej ... i lubię też pomysł nie mając spisać każda klasa model I pracować, więc przyszedłem z tego

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) 

Więc teraz mogę tylko dziedziczą TestCaseWithPeewee i nie trzeba się martwić o cokolwiek innego innych niż próba

0

Podczas korzystania test_database i napotkał problemy z test_db nie jest inicjowany:

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 << ---------------------

I ostatecznie ustalony przez to przechodząc create_tables=True tak:

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()

Według the docscreate_tables powinien domyślnie True ale wydaje się, że nie jest to przypadek w najnowszym wydaniu peewee.

+0

Utworzono problem z github https: // github.com/coleifer/peewee/issues/741 – coleifer

+0

Trackback wskazuje, że testowa baza danych jest w stanie "odroczonym". Testowa baza danych musi być zainicjalizowana nazwą bazy danych. – coleifer

Powiązane problemy