2011-05-28 11 views
20

मैं नकली वस्तुओं के साथ परीक्षण मामलों को लिखने के लिए Google App Engine testbed ढांचे का उपयोग कर रहा हूं। यह here दस्तावेज है। मुझे अपने डेटास्टोर परीक्षणों को नकली डेटाबेस (Testbed.init_datastore_v3_stub) का उपयोग करके अच्छी तरह से काम कर रहा है, और इससे मेरे टेस्ट केस एक तेज़, ताजा डेटाबेस पर चलने देते हैं जो प्रत्येक टेस्ट केस के लिए पुनः आरंभ किया जाता है। अब मैं कार्यक्षमता का परीक्षण करना चाहता हूं जो वर्तमान उपयोगकर्ता पर निर्भर करता है।आप ऐप इंजन में उपयोगकर्ता सेवा का नकल कैसे करते हैं?

Testbed.init_user_stub नामक एक और टेस्टबैक सेवा है, जिसे मैं "नकली" उपयोगकर्ता सेवा प्राप्त करने के लिए सक्रिय कर सकता हूं। दुर्भाग्यवश, इस के लिए कोई प्रलेखन प्रतीत नहीं होता है। मैं सक्रिय करने और इस तरह यह उपयोग कर रहा हूँ:

import unittest 
from google.appengine.ext import testbed 
from google.appengine.api import users 

class MyTest(unittest.TestCase): 
    def setUp(self): 
     self.testbed = testbed.Testbed() 
     self.testbed.activate() 
     self.testbed.init_user_stub() 

    def testUser(self): 
     u = users.get_current_user() 
     self.assertNotEqual(u, None) 

समस्या यह है कि मैं किसी भी तरह एक "नकली" उपयोगकर्ता को प्रमाणित करने के लिए "नकली" उपयोगकर्ता सेवा बताने के लिए नहीं मिला है है। ताकि परीक्षण चल रहा है, मैं (जाहिर) अर्थ नकली उपयोगकर्ता सेवा मेरे ऐप कि वर्तमान उपयोगकर्ता प्रवेश न होने पर कह रहा है मिल

AssertionError: None == None 

। मैं कैसे नाटक करने के लिए है कि एक उपयोगकर्ता लॉग ऑन है नकली उपयोगकर्ता सेवा बता सकते हैं में? आदर्श रूप से, मैं नकली उपयोगकर्ता का उपनाम, ईमेल, user_id निर्दिष्ट करने में सक्षम होना चाहता हूं और चाहे वे एक व्यवस्थापक हों या नहीं। ऐसा लगता है कि यह एक सामान्य बात है (क्योंकि आपको यह जांचने की ज़रूरत है कि ऐप कैसे व्यवहार करता है जब कोई) कोई भी लॉग इन नहीं होता है, बी) कोई उपयोगकर्ता लॉग इन होता है, और सी) एक व्यवस्थापक लॉग इन होता है), लेकिन गुगलिंग "init_user_stub" लगभग कुछ भी नहीं देता है।

नोट:

if __name__ == '__main__': 
    unittest.main() 

उत्तर

17

खैर मुझे नहीं लगता कि: नीचे करने के लिए इस

import sys 
sys.path.append('/PATH/TO/APPENGINE/SDK') 
import dev_appserver 
dev_appserver.fix_sys_path() 

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

देव सर्वर वर्तमान में लॉग इन उपयोगकर्ता को तीन पर्यावरण चर के आधार पर दर्शाता है :

  • USER_EMAIL: उपयोगकर्ता के ईमेल पते, और उपयोगकर्ता के उपनाम।
  • यूएसER_आईडी: उपयोगकर्ता की अद्वितीय Google आईडी (स्ट्रिंग)।
  • यूएसER_आईएस_एडीएमआईएन: "0" यदि उपयोगकर्ता गैर-व्यवस्थापक है, तो "1" यदि उपयोगकर्ता एक व्यवस्थापक है।

आप os.environ का उपयोग के रूप में आप किसी भी अन्य वातावरण चर इन स्थापित करने के लिए कर सकते हैं, और वे तत्काल प्रभाव (स्पष्ट रूप से यह उत्पादन सर्वर पर काम नहीं करेगा) ले लो। लेकिन आप टेस्टबेड के user_stub के साथ उनका उपयोग कर सकते हैं और जब आप टेस्टबेड को निष्क्रिय करते हैं तो उन्हें रीसेट कर दिया जाएगा (जो आपको tearDown पर करना चाहिए, इसलिए आपको प्रत्येक टेस्ट केस के लिए एक नया वातावरण मिलता है)।

के बाद से वातावरण चर की स्थापना एक सा बोझल है, मैं उनका पैकेज के लिए कुछ आवरण कार्यों लिखा है:

import os 

def setCurrentUser(email, user_id, is_admin=False): 
    os.environ['USER_EMAIL'] = email or '' 
    os.environ['USER_ID'] = user_id or '' 
    os.environ['USER_IS_ADMIN'] = '1' if is_admin else '0' 

def logoutCurrentUser(): 
    setCurrentUser(None, None) 
+11

इस मूल रूप से सही विचार है। सिवाय इसके कि आप 'os.environ'' के बजाय ['testbed.setup_env()'] (http://code.google.com/appengine/docs/python/tools/localunittesting.html#Changing_the_Default_Environment_Variables) का उपयोग करना चाहते हैं। – ryan

+1

मैं इसे कम कर रहा हूं क्योंकि ** यह पर्यावरण को प्रदूषित कर रहा है **। यह ध्यान दिया जाना चाहिए कि एक सफाई की आवश्यकता है। यह टेरीबेड का उपयोग करके किया जा सकता है @ एरियन ने कहा। – siebz0r

11

यहाँ है कि क्या सफल मुझे एक उपयोगकर्ता द्वारा प्रवेश अनुकरण के लिए:

self.testbed.setup_env(USER_EMAIL='[email protected]',USER_ID='1', USER_IS_ADMIN='0') 
self.testbed.init_user_stub() 
+0

जो काम करता है, लेकिन ऐसा लगता है कि testbed.setup_env() testbed.activate() से पहले जाना है, अन्यथा इसका कोई प्रभाव नहीं पड़ता है। – gargc

+0

@gargc मुझे यह कहने में खेद है कि आपने जो कहा है वह गलत और संभावित रूप से 'खतरनाक' है। एक प्रदर्शन के लिए कृपया मेरा जवाब देखें। – siebz0r

+1

@ siebz0r अच्छा कॉल! वैसे, मुझे पता चला है कि मुझे इसे काम करने के लिए कॉल का क्रम क्यों बदलना पड़ा। USER_EMAIL और USER_ID को डिफ़ॉल्ट वातावरण के हिस्से के रूप में सक्रियण पर खाली स्ट्रिंग पर सेट किया गया है (जो user_is_admin के साथ नहीं होता है)। समाधान 'overwrite = True' को setup_env पर पास करना है, अन्यथा पर्यावरण में पहले से मौजूद किसी भी चर [ignored] हैं (https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine /ext/testbed/__init__.py?r=381#328) जिसके परिणामस्वरूप get_current_user() हमेशा कोई नहीं होता है। – gargc

9

Bijan के उत्तर के अलावा:

google.appengine.api.users में वास्तविक चेक इस तरह:

def is_current_user_admin(): 
    return (os.environ.get('USER_IS_ADMIN', '0')) == '1' 

कुंजी वातावरण चर USER_IS_ADMIN'1' करने के लिए सेट करने के लिए इस प्रकार है। यह कई तरीकों से किया जा सकता है, लेकिन ध्यान दें कि आप एक वैश्विक चर को संशोधित कर रहे हैं और इस प्रकार यह अन्य कोड को प्रभावित कर सकता है। कुंजी एक उचित सफाई करने के लिए है।

कोई Mock librarypatch os.environ का उपयोग कर सकता है, Testbed का उपयोग करें या अपने स्वयं के रचनात्मक तरीके से रोल करें। मैं Testbed का उपयोग करना पसंद करता हूं क्योंकि यह संकेत देता है कि हैक एपेंगेन से संबंधित है। 3.3 से पहले पाइथन संस्करणों में नकली शामिल नहीं है, इसलिए यह एक अतिरिक्त परीक्षण निर्भरता जोड़ता है।

अतिरिक्त सूचना: जब unittest module का उपयोग कर रहा addCleanup बजाय tearDown के बाद से सफाई भी कहा जाता है जब setUp विफल रहता है उपयोग करने के लिए पसंद करते हैं।

उदाहरण परीक्षण:

import unittest 

from google.appengine.api import users 
from google.appengine.ext import testbed 


class AdminTest(unittest.TestCase): 
    def setUp(self): 
     tb = testbed.Testbed() 
     tb.activate() 
     # ``setup_env`` takes care of the casing ;-) 
     tb.setup_env(user_is_admin='1') 
     self.addCleanup(tb.deactivate) 

    def test_is_current_user_admin(self): 
     self.assertTrue(users.is_current_user_admin()) 

नोट:Testbed.setup_envTestbed.activate के बाद बुलाया जाना चाहिए। Testbed सक्रियण पर os.environ का स्नैपशॉट लेता है, स्नैपशॉट निष्क्रिय करने पर पुनर्स्थापित किया जाता है। यदि Testbed.setup_env सक्रियण से पहले कहा जाता है तो वास्तविक os.environ अस्थायी उदाहरण के बजाय संशोधित किया जाता है, इस प्रकार पर्यावरण को प्रभावी रूप से प्रदूषित कर देता है।

>>> import os 
>>> from google.appengine.ext import testbed 
>>> 
>>> tb = testbed.Testbed() 
>>> tb.setup_env(user_is_admin='1') 
>>> tb.activate() 
>>> assert 'USER_IS_ADMIN' in os.environ 
>>> tb.deactivate() 
>>> assert 'USER_IS_ADMIN' not in os.environ 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AssertionError 
0

यहाँ मैं अपने जवाब को यहां आधारित परीक्षण के लिए बनाई गई एक जोड़े सहायक कार्यों है:

>>> import os 
>>> from google.appengine.ext import testbed 
>>> 
>>> tb = testbed.Testbed() 
>>> tb.activate() 
>>> tb.setup_env(user_is_admin='1') 
>>> assert 'USER_IS_ADMIN' in os.environ 
>>> tb.deactivate() 
>>> assert 'USER_IS_ADMIN' not in os.environ 
>>> 

यह वातावरण को प्रदूषित करता है:

यह एकदम सही ढंग से व्यवहार करता है। (NoseGAE साथ)

# tests/test_helper.py 
import hashlib 

def mock_user(testbed, user_email='[email protected]', is_admin=False): 
    user_id = hashlib.md5(user_email).hexdigest() 
    is_admin = str(int(is_admin)) 

    testbed.setup_env(USER_EMAIL=user_email, 
         USER_ID=user_id, 
         USER_IS_ADMIN=is_admin, 
         overwrite=True) 
    testbed.init_user_stub() 

def mock_admin_user(testbed, user_email='[email protected]'): 
    mock_user(testbed, user_email, True) 

नमूना उपयोग:: मैं एक test_helper मॉड्यूल में उन्हें अटक

import unittest 

from google.appengine.ext import ndb, testbed 
from google.appengine.api import users 

from tests.test_helper import mock_user, mock_admin_user 

class MockUserTest(unittest.TestCase): 
    def setUp(self): 
     self.testbed = testbed.Testbed() 
     self.testbed.activate() 
     self.testbed.init_datastore_v3_stub() 
     self.testbed.init_memcache_stub() 
     ndb.get_context().clear_cache() 

    def tearDown(self): 
     self.testbed.deactivate() 

    def test_should_mock_user_login(self): 
     self.assertIsNone(users.get_current_user()) 
     self.assertFalse(users.is_current_user_admin()) 

     mock_user(self.testbed) 
     user = users.get_current_user() 
     self.assertEqual(user.email(), '[email protected]') 
     self.assertFalse(users.is_current_user_admin()) 

     mock_admin_user(self.testbed) 
     admin = users.get_current_user() 
     self.assertEqual(admin.email(), '[email protected]') 
     self.assertTrue(users.is_current_user_admin()) 
संबंधित मुद्दे