2017-01-26 10 views
9

आइए कहें कि मेरे पास एक बहुत ही सरल वेब ऐप है जो नीले रंग के रूप में प्रस्तुत किया जाता है यदि वर्तमान राष्ट्रपति लोकतंत्र और लाल हो तो वे रिपब्लिकन हैं।मॉक किए गए आरईएसटी एपीआई के साथ टेस्ट एनवायरनमेंट

/presidents/current 

जो वर्तमान में json ऑब्जेक्ट:

{name: "Donald Trump", party: "Republican"} 

तो जब मेरे पृष्ठ लोड मैं endpoint संपर्क करें, मैं लाल दिखाने या एक REST API का अंत बिंदु के माध्यम से, वर्तमान अध्यक्ष प्राप्त करने के लिए प्रयोग किया जाता है कौन लौटा है इस पर निर्भर करता है नीला।

मैं इस HTML/जावास्क्रिप्ट पेज का परीक्षण करना चाहता हूं और मैं बैक-एंड का मज़ाक उड़ाना चाहता हूं ताकि मैं परीक्षण वातावरण में एपीआई प्रतिक्रियाओं से नियंत्रण कर सकूं। उदाहरण के लिए:

def test_republican(): 
    # configure the response for this test that the web app will receive when it connects to this endpoint 
    configure_endpoint(
     "/presidents/current", 
     jsonify(
      name="Donald Trump", 
      party="Republican" 
     ) 
    ) 

    # start the web app in the browser using selenium 
    load_web_app(driver, "http://localhost:8080") 

    e = driver.find_element_by_name("background") 
    assert(e.getCssValue("background-color") == "red") 


def test_democrat(): 
    # configure the response for this test that the web app will receive when it connects to this endpoint 
    configure_endpoint(
     "/presidents/current", 
     jsonify(
      name="Barack Obama", 
      party="Democrat" 
     ) 
    )  

    # start the web app in the browser using selenium 
    load_web_app(driver, "http://localhost:8080") 

    e = driver.find_element_by_name("background") 
    assert(e.getCssValue("background-color") == "blue") 

तो सवाल यह है कि मैं समारोह configure_endpoint कैसे लागू करना चाहिए() और क्या पुस्तकालयों तुम मुझे सिफारिश कर सकते हैं?

उत्तर

1

यदि फ़ंक्शन requests library का उपयोग रीस्ट एपीआई तक पहुंचने के लिए करता है, तो requests-mock का उपयोग करके नकली का सुविधाजनक तरीका है कि परीक्षण उद्देश्यों के लिए लाइब्रेरी की कार्यक्षमता।

+0

कोई load_web_app() आसानी से सेलेनियम का उपयोग कर ब्राउज़र में html/js फ़ाइल लोड करता है। मुझे एक एपीआई सर्वर बनाकर बैकएंड को नकल करने की ज़रूरत है जिस पर वेब ऐप कनेक्ट होता है। यह नकली सर्वर परीक्षण पर्यावरण के भीतर से विन्यास योग्य होना चाहिए। – Baz

+0

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

+0

एपीआई है पहले से ही परीक्षण के साथ कवर किया गया है। इन परीक्षणों में एपीआई को कॉल करना और परीक्षण करना शामिल है कि सही प्रतिक्रिया प्राप्त होती है। अब मैं वेब ऐप के भीतर प्रवाह का परीक्षण करना चाहता हूं और यह जांचने के लिए कि ऐप उन ब्राउज़रों के लिए अपेक्षित व्यवहार करता है जिन्हें मैं समर्थन देना चाहता हूं। दूसरे शब्दों में, मैं फ्रंट-एंड को उपप्रणाली के रूप में देखना चाहता हूं और इसके लिए उप सिस्टम परीक्षण लिखना चाहता हूं। – Baz

2

मैं टॉरनाडो वेब ढांचे का उपयोग करूंगा।

import json 
import functools 
import operator 
from tornado import ioloop, web, gen 
from tornado.options import define, options 

define("data_file", default='default/mock.json', type=str) 

class Handler(web.RequestHandler): 

    def data_received(self, chunk): 
     pass 

    def initialize(self, data): 
     self.data = data 

    @gen.coroutine 
    def get(self, *args, **kwargs): 
     path = self.request.path.split("/")[1:] 
     path = functools.reduce(
      operator.add, 
      [[k, v[0].decode("utf-8")] for k, v in   self.request.query_arguments.items()], 
      path 
     ) 

     try: 
      self.write(functools.reduce(operator.getitem, path, self.data)) 
     except KeyError: 
      self.set_status(404) 


class Application(web.Application): 
    def __init__(self): 
     data = {} 
     with open(options.data_file) as data_file: 
      data = json.load(data_file) 

     handlers = [ 
      ('(.*)', Handler, {"data": data}) 
     ] 
     settings = dict(
      gzip=True, 
      static_hash_cache=True, 
     ) 
     web.Application.__init__(self, handlers, **settings) 


    def main(): 
     io_loop = ioloop.IOLoop.instance() 
     backend_application = Application() 
     backend_application.listen(8001) 
     io_loop.start() 

    if __name__ == "__main__": 
     main() 

यह एक कोड मैं किसी REST- एपीआई जो एक स्टैंडअलोन स्क्रिप्ट है मजाक के लिए इस्तेमाल किया है, लेकिन यह अपने परीक्षण वातावरण में भी जोड़ा जा सकता है।

मैंने एक JSON फ़ाइल परिभाषित की है जो विभिन्न पथ घटकों को परिभाषित करता है और क्या वापस किया जाना चाहिए। इस तरह:

{ 
    "presidents": { 
     "current": { 
      "name": "Donald Trump", 
      "party": "Republican" 
     } 
    } 
} 

मैं एक mock.json को यह बचाया और एक पैरामीटर mock_rest.py --data-file="./mock.json" साथ स्क्रिप्ट कहा जाता है।

मुझे उम्मीद है कि आपको एक प्रारंभिक बिंदु और एक अच्छा उदाहरण मिल जाएगा।

4

जैसा कि @Kie उल्लेख किया गया है, configure_endpoint कार्यान्वयन पर्याप्त नहीं होगा, अगर आप सेलेनियम पायथन कोड के भीतर पूरे सर्वर-पक्ष को दबाएंगे। परीक्षण नेटवर्क के भीतर से अनुरोध करने के लिए आपको एक वेब सर्वर या HTTP के माध्यम से प्रतिक्रिया देने की आवश्यकता होगी।

ऐसा लगता है कि प्रश्न आंशिक रूप से क्लाइंट-साइड कोड के परीक्षण के बारे में है। मैं जो देखता हूं वह यह है कि आप क्लाइंट-साइड लॉजिक के लिए यूनिट-टेस्ट बनाने की कोशिश कर रहे हैं, लेकिन इस तर्क को जांचने के लिए एकीकरण परीक्षण सूट का उपयोग करें (यह अजीब है)।

मुख्य विचार निम्नानुसार है।

आप क्लाइंट-साइड कोड का परीक्षण करने का प्रयास कर रहे हैं। तो, चलो क्लाइंट-साइड मैक्स भी बनाते हैं! चूंकि कोड का यह हिस्सा पूरी तरह क्लाइंट-साइड से संबंधित सामान है।

यदि आप वास्तव में मोजे चाहते हैं, तो स्टब्स न करें (यहां अंतर देखें: https://stackoverflow.com/a/3459491/882187) यह आपके जावास्क्रिप्ट कोड के अंदर HTTP अनुरोधों का नकल करने का एक बेहतर तरीका है। सिर्फ इसलिए कि आप क्लाइंट-साइड कोड कोड का परीक्षण कर रहे हैं, सर्वर-साइड लॉजिक के कुछ हिस्सों में नहीं।

जो कुछ भी सर्वर-साइड से अलग है - यह एक अच्छा विचार है कि जब आपकी परियोजना बढ़ती है तो आप प्यार करेंगे, जबकि अधिक से अधिक अंतराल दिखाई देंगे।

उदाहरण के लिए, आप निम्नलिखित दृष्टिकोण का उपयोग कर सकते हैं:

var restResponder = function() { // the original responder your client-side app will use 
    this.getCurrentPresident = function(successCallback) { 
    $.get('/presidents/current', callback); 
    } 
}; 

var createMockResponder = function(president, party){ // factory that creates mocks 
    var myPresident = president; 
    var myParty = party; 

    return function() { 
    this.getCurrentPresident = function (successCallback) { 
     successCallback({"name": myPresident, "party": myParty}); 
    } 
    }; 
} 

// somewhere swap the original restResponder with new mockResponder created by 'createMockResponder' 

// then use it in your app: 

function drawColor(restResponder, backgroundEl) { 
    restResponder.getCurrentPresident(function(data){ 
    if (data.party == "Democrat") $(backgroundEl).style('background-color', 'blue') 
    else if (data.party == "Republican") $(backgroundEl).style('background-color', 'red') 
    else console.info('Some strange response from server... Nevermind...'); 
    }); 
} 

व्यावहारिक रूप से, इस कार्यान्वयन क्या आप एक ढांचे के रूप में क्लाइंट साइड पर की क्या ज़रूरत है पर निर्भर करता है। यदि jQuery, तो मेरा उदाहरण पर्याप्त है, लेकिन यह बहुत शब्दशः दिखता है।

// Set up the mock http service responses 
$httpBackend = $injector.get('$httpBackend'); 
// backend definition common for all tests 
authRequestHandler = $httpBackend.when('GET', '/auth.py') 
           .respond({userId: 'userX'}, {'A-Token': 'xxx'}); 

चेक बाहर डॉक्स: मामले में आप और अधिक उन्नत कुछ, AngularJS की तरह है, तो आप कोड के 2-3 लाइनों में भी ऐसा ही कर सकते हैं https://docs.angularjs.org/api/ngMock/service/ $ httpBackend

आप अभी भी करने के लिए छड़ी कर रहे हैं विचार, कि आपको सेलेनियम परीक्षणों के अंदर मोक्स चाहिए, कृपया इस प्रोजेक्ट को आजमाएं: https://turq.readthedocs.io/en/latest/

यह रीस्ट उत्तरदाताओं का वर्णन करने के लिए पायथन डीएसएल के साथ कार्य करता है। का उपयोग turq अपने mocks इस प्रकार दिखेगा:

path('/presidents/current').json({'name':'Barack Obama', 'party': 'Democrat'}, jsonp=False) 

इसके अलावा, मैं mocks के बजाय स्टब्स कोशिश करते हैं और इस पायथन मॉड्यूल का उपयोग करने की सिफारिश करेंगे: mock-serverhttps://pypi.python.org/pypi/mock-server/0.3.7 आप निर्देशिका इसी पूर्व आबादी वाले युक्त लेआउट बनाने के लिए आवश्यक हैं JSON प्रतिक्रियाएं और mock-server 'localhost: 8080' पर प्रतिक्रिया देने के लिए कुछ बॉयलरप्लेट कोड जोड़ने के लिए। आपके उदाहरण के लिए निर्देशिका लेआउट इस तरह दिखेगा:

stub_obama/ 
    presidents/ 
    current/ 
     GET_200.json  # will contain {"name": "Barack Obama", "party": "Democrat"} 
stub_trump/ 
    presidents/ 
    current/ 
     GET_200.json  # will contain {"name": "Donald Trump", "party": "Republican"} 

लेकिन mock_server तूफान पर आधारित है, यह परीक्षण मुझे लगता है कि में प्रयोग करने के लिए बहुत भारी समाधान है।

मुझे आशा है कि मेरा उत्तर सहायक और जानकारीपूर्ण होगा। चर्चा करने के लिए आपका स्वागत है! मैंने सेलेनियम, बड़े और छोटे परीक्षणों, परीक्षण क्लाइंट-साइड और सर्वर-साइड के साथ कई परियोजनाएं की हैं।

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