2011-02-25 2 views
7

अपने आवेदन में, वहाँ एक मॉडल (मुझे लगता है कि यह एक "भंडार" DDD भाषा में कुछ हद तक है) कि आमतौर पर इस्तेमाल किया प्रश्नों धारण के लिए एक वर्ग है। इन वर्गों में से प्रत्येक को निर्माण के साथ प्रश्न बनाने के लिए SQLAlchemy सत्र ऑब्जेक्ट पारित किया गया है। मुझे अपने यूनिट परीक्षणों में कुछ प्रश्नों को चलाने के लिए सबसे अच्छा तरीका लगाने में थोड़ा कठिनाई हो रही है। सर्वव्यापी ब्लॉग उदाहरण का उपयोग करके, मान लीजिए कि मेरे पास कॉलम और गुण "दिनांक" और "सामग्री" के साथ "पोस्ट" मॉडल है। मैं भी विधि "find_latest" कि "तिथि" अवरोही क्रम में सभी पदों के लिए क्वेरी करने के लिए माना जाता है के साथ एक "PostRepository" है। ऐसा कुछ दिखता है:अजगर SQLAlchemy - मजाक एक मॉडल विशेषता के "desc" विधि

from myapp.models import Post 

class PostRepository(object): 
    def __init__(self, session): 
     self._s = session 

    def find_latest(self): 
     return self._s.query(Post).order_by(Post.date.desc()) 

मुझे Post.date.desc() कॉल का मज़ाक उड़ाते हुए समस्या हो रही है। अभी मैं अपने यूनिट परीक्षण में Post.date.desc के लिए एक नकली पैचिंग बंदर हूं, लेकिन मुझे लगता है कि एक बेहतर दृष्टिकोण होने की संभावना है।

संपादित करें: मैं नकली वस्तुओं के लिए mox उपयोग कर रहा हूँ, मेरे वर्तमान इकाई परीक्षण तरह दिखता है:

import unittest 
import mox 

class TestPostRepository(unittest.TestCase): 

    def setUp(self): 
     self._mox = mox.Mox() 

    def _create_session_mock(self): 
     from sqlalchemy.orm.session import Session 
     return self._mox.CreateMock(Session) 

    def _create_query_mock(self): 
     from sqlalchemy.orm.query import Query 
     return self._mox.CreateMock(Query) 

    def _create_desc_mock(self): 
     from myapp.models import Post 
     return self._mox.CreateMock(Post.date.desc) 

    def test_find_latest(self): 
     from myapp.models.repositories import PostRepository 
     from myapp.models import Post 

     expected_result = 'test' 

     session_mock = self._create_session_mock() 
     query_mock = self._create_query_mock() 
     desc_mock = self._create_desc_mock() 

     # Monkey patch 
     tmp = Post.date.desc 
     Post.date.desc = desc_mock 

     session_mock.query(Post).AndReturn(query_mock) 
     query_mock.order_by(Post.date.desc().AndReturn('test')).AndReturn(query_mock) 
     query_mock.offset(0).AndReturn(query_mock) 
     query_mock.limit(10).AndReturn(expected_result) 

     self._mox.ReplayAll() 
     r = PostRepository(session_mock) 

     result = r.find_latest() 
     self._mox.VerifyAll() 

     self.assertEquals(expected_result, result) 

     Post.date.desc = tmp 

इस काम है, हालांकि बदसूरत लगता है करता है और मुझे यकीन है कि नहीं कर रहा हूँ "AndReturn बिना कारण है कि यह विफल रहता है ('test') "post.date.desc() का टुकड़ा। &Return ('test')"

उत्तर

13

मुझे नहीं लगता कि आप वास्तव में अपने प्रश्नों का परीक्षण करने के लिए मैक्स का उपयोग करके अधिक लाभ प्राप्त कर रहे हैं। परीक्षण कोड, नहीं कार्यान्वयन की तर्क परीक्षण किया जाना चाहिए। एक बेहतर समाधान एक नया डेटाबेस बनाना होगा, इसमें कुछ ऑब्जेक्ट्स जोड़ें, उस डेटाबेस पर क्वेरी चलाएं, और यह निर्धारित करें कि आपको सही परिणाम मिल रहे हैं या नहीं। उदाहरण के लिए:


# Create the engine. This starts a fresh database 
engine = create_engine('sqlite://') 
# Fills the database with the tables needed. 
# If you use declarative, then the metadata for your tables can be found using Base.metadata 
metadata.create_all(engine) 
# Create a session to this database 
session = sessionmaker(bind=engine)() 

# Create some posts using the session and commit them 
... 

# Test your repository object... 
repo = PostRepository(session) 
results = repo.find_latest() 

# Run your assertions of results 
... 

अब, तुम वास्तव में तर्क कोड के परीक्षण कर रहे हैं। इसका मतलब है कि आप अपनी विधि के कार्यान्वयन को बदल सकते हैं, लेकिन जब तक क्वेरी सही तरीके से काम करती है, परीक्षण अभी भी पास होना चाहिए। यदि आप चाहते हैं, तो आप इस विधि को एक क्वेरी के रूप में लिख सकते हैं जो सभी ऑब्जेक्ट्स प्राप्त करता है, फिर परिणामस्वरूप सूची को स्लाइस करता है। परीक्षा उत्तीर्ण होगी, जैसा कि इसे करना चाहिए। बाद में, आप एसए अभिव्यक्ति एपीआई का उपयोग कर क्वेरी चलाने के लिए कार्यान्वयन को बदल सकते हैं, और परीक्षण पास होगा।

ध्यान में रखना एक बात यह है कि आपको SQL डेटाबेस के साथ अन्य डेटाबेस प्रकार से अलग व्यवहार करने में समस्या हो सकती है। में-स्मृति SQLite का उपयोग करके आप तेजी से परीक्षण देता है, लेकिन अगर आप इन परीक्षणों के बारे में गंभीर होना चाहते हैं, तो आप शायद उन्हें डेटाबेस के एक ही प्रकार आप उत्पादन में उपयोग किया जाएगा और साथ ही के खिलाफ चलाने के लिए चाहता हूँ।

+0

भावना का एक बहुत बनाता है यही कारण है कि, मैं भी हो रही थी कोड के विवरण पर लटका दिया। अंतर्दृष्टि के लिए धन्यवाद। –

+5

क्या आप कह रहे हैं कि बजाय एक इकाई परीक्षण (तर्क की एक इकाई) करने का, (डेटाबेस) के साथ एकीकरण परीक्षण करना है। यह एक वैध दृष्टिकोण है, और संभवतः एक ओआरएम के लिए सबसे समझदार होने के लिए, फिर भी इन परीक्षणों के प्रदर्शन में एक या दो आयामों का धुन होता है। सही? –

+1

आप सही हैं कि एक परीक्षा लिखना (चाहे आप इसे "इकाई" परीक्षण या "एकीकरण" परीक्षण कहते हैं) जो किसी भी तरह धीमे संसाधन तक पहुंच जाएगा (चाहे वह डिस्क ड्राइव, बाहरी सेवा या डेटाबेस हो) का अर्थ होगा ऐसे संसाधन की तुलना में धीमी परीक्षा जो इस तरह के संसाधन तक नहीं पहुंचती है। –

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^