2010-11-01 14 views
11

क्या आम लिस्प के लिए एक मॉकिंग/स्टबिंग फ्रेमवर्क है?क्या आम लिस्प के लिए एक मॉकिंग/स्टबिंग फ्रेमवर्क है?

EmacsLispMock बहुत अच्छा लग रहा है, लेकिन यह एक Emacs lisp ढांचा है, और मैं सामान्य लिस्प से उपयोग करने के लिए कुछ ढूंढ रहा हूं।

कोई सुझाव?

+2

एक मॉकिंग/स्टबिंग फ्रेमवर्क क्या करता है? – Xach

+0

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

+0

मैं शायद "स्टब फ़ंक्शन बी" को परिभाषित करता हूं (डिफन बी (और बाकी तर्क) 5) अगर मैं चाहता था, विशेष रूप से, एक फ़ंक्शन लौटा रहा हो। 5. यह उस जगह पर है और मेरे "बी" का उपयोग करके कार्य किया गया है, उचित परिभाषा पुनः लोड करें। – Vatine

उत्तर

4

निम्नलिखित आप के लिए

(defmacro with-replaced-function (fdef &rest body) 
    (let ((oldf (gensym)) 
     (result (gensym)) 
     (name (car fdef)) 
     (args (cadr fdef)) 
     (rbody (cddr fdef))) 
    `(let ((,oldf (symbol-function ',name))) 
     (setf (symbol-function ',name) (lambda ,args ,@rbody)) 
     (let ((,result (progn ,@body))) 
     (setf (symbol-function ',name) ,oldf) 
     ,result)))) 

(defmacro show (x) 
    `(format t "~a --> ~a~%" 
      ',x ,x)) 

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

(defun foo (x y) (+ x y)) 

(defun bar (x) (foo x (* x 2))) 

(show (bar 42)) 

(show (with-replaced-function (foo (x y) (* x y)) 
           (bar 42))) 

(show (bar 42)) 

मैक्रो बस समारोह वर्तमान प्रतीक से बताया जा रहा बचाता है और प्रदान की ठूंठ कार्यान्वयन के साथ यह बदल देता है जो खोज रहे हैं क्या करना चाहिए। ब्लॉक के अंत में फ़ंक्शन को मूल मान पर पुनर्स्थापित किया जाता है।

यह शायद शरीर से गैर स्थानीय रास्ते के खिलाफ एक सुरक्षा जोड़ने का मतलब होगा।

भी ध्यान रखें कि स्पष्ट रूप से बदल रहा है एक समारोह परिभाषा फ़ंक्शन कॉल एक संकलक द्वारा inlined कर दिया है, तो काम करने के लिए नहीं जा रहा है। सीएल में एक विशेष NOTINLINE घोषणा है जिसका उपयोग इस समस्या को रोकने के लिए किया जा सकता है।

+6

यह ध्यान दिया जाना चाहिए कि यह आवश्यक रूप से संकलित कोड में काम नहीं कर सकता है, कार्यों के रूप में फ़ाइल कंपाइलर द्वारा रेखांकित किया जा सकता है (संकलक उदाहरण के लिए मान सकते हैं कि एक ही फ़ाइल में कार्य समान रहते हैं)। इसलिए इन कार्यों को रेखांकित नहीं करना आवश्यक हो सकता है। –

+0

@Rainer यह इंगित करने के लिए धन्यवाद कि –

+0

गैर-स्थानीय निकास के खिलाफ सुरक्षा 'अवांछित-रक्षा' का उपयोग करके किया जाता है। यह एक काफी बुनियादी पैटर्न है, जो अक्सर मैक्रोज़ में पाया जाता है। – Svante

1

आपको सीएल में एक मॉकिंग/स्टबिंग फ्रेमवर्क की आवश्यकता नहीं है।

बस अपनी कक्षा कक्षा से व्युत्पन्न नया CLOS बनाएं जो आप स्टब/मॉक करना चाहते हैं और आप कर रहे हैं के लिए विधियों ovverides के साथ।

स्टबिंग के लिए, क्यों न केवल कार्य को फिर से परिभाषित करें?

+2

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

+4

मेरा मानना ​​है कि FLET केवल एक निर्दिष्ट व्याख्यात्मक संदर्भ के भीतर एक प्रतीक को एक समारोह में बांधता है। – Vatine

+0

फ़ंक्शन को फिर से परिभाषित करना काम करेगा यदि बाद में परिभाषा को "पुनर्स्थापित" करने का एक अच्छा तरीका है, क्योंकि मैं वास्तविक फ़ंक्शन परिभाषाओं को गड़बड़ किए बिना परीक्षण चलाने में सक्षम होना चाहता हूं। उस पर कोई विचार? –

1

ऐसा करने का यह सबसे आसान तरीका नहीं है?

> (defun b() 'original) 
B 
> (setf f #'b) 
#<Compiled-function B #xC2C1546> 
> (defun a() (funcall f)) 
A 
> (a) 
ORIGINAL 
> (setf f #'(lambda() 'stub)) 
#<Anonymous Function #xC2D990E> 
> (a) 
STUB 
> (setf f #'b) 
#<Compiled-function B #xC2C1546> 
> (a) 
ORIGINAL 
+0

दिलचस्प सुझाव। तो, इसका मतलब यह होगा कि आपको सामान्य कोड की बजाय funcall का उपयोग करके, कुछ फ़ंक्शन कॉल के साथ अपना कोड लिखना होगा। शायद यह सामान्य लापरवाही तरीका है? अर्थात। उपयोग करने के लिए कार्यान्वयन रनटाइम के दौरान भिन्न हो सकता है, इसलिए funcall का उपयोग करें। –

0

आप किसी मैक्रो

(defmacro with-fun (origfn mockfn &body body) 
    `(let ((it ,origfn)) 
     (setf ,origfn ,mockfn) 
    ,@body 
     (setf ,origfn ,it))) 

यह सिर्फ एक विचार है अंदर समारोह फिर से परिभाषा रैप करने के लिए कोशिश कर सकते हैं, और आप इस तरह के मैक्रो को लागू करना होगा। आप profile कार्यान्वयन के लिए Google पर जा सकते हैं जो वास्तव में एक फ़ंक्शन को दूसरे के साथ प्रतिस्थापित करता है और प्रोफाइलिंग जानकारी जोड़ता है। आप वहां से कुछ विचार उधार ले सकते हैं।

+0

मीठा लग रहा है! मैं निश्चित रूप से इसे –

+0

उत्तर देने के लिए नए लोगों के लिए प्रयास करूंगा: यह एक अनौपचारिक मैक्रो है और यदि आप उस शरीर को पास करते हैं जिसमें प्रतीक 'यह' है तो आपका कोड काम नहीं करेगा। अधिक जानकारी के लिए जांचें: https://en.wikipedia.org/wiki/Anaphoric_macro और https://en.wikipedia.org/wiki/Hygienic_macro – tsikov

2

रेनर बताते हैं के रूप में, फ़ाइल संकलक कभी कभी inlines काम करता है, जो बदलते मतलब है समारोह परिभाषा स्थानों पर जहां समारोह inlined गया था में कोई असर नहीं होगा।

समारोह नाम की परिभाषा बदलने से समारोह का उपयोग करते हैं, उदाहरण के लिए, एक शाब्दिक वस्तु के रूप में जगह नहीं होगी अगर आप कहीं एक चर में मेरे-टोंटदार-समारोह # सहेजी गई '।

हालांकि, कुछ लिस्पी कार्यान्वयन में आप फ़ंक्शन रैपर को परिभाषित कर सकते हैं या इसे प्राप्त करने के लिए सलाह का उपयोग कर सकते हैं: उदाहरण के लिए, एलेग्रो सीएल में fwrappers है। एसबीसीएल में, आप गैर-मानक: ब्रेक फ़ंक्शन और कस्टम * इनवॉक-डीबगर-हुक * के साथ TRACE का उपयोग कर सकते हैं, और मुझे यकीन है कि अन्य लिस्प कार्यान्वयन के समान कुछ होगा।

मुझे नहीं लगता कि किसी को भी एक पुस्तकालय में इन छोटा करते तरीकों से पैक किया गया है है। आप पहले हो सकते हैं! (और यह बहुत अच्छा होगा। मुझे इस तरह कुछ उपयोग करना अच्छा लगेगा।)

1

मैंने एक मैक्रो के साथ एक लाइब्रेरी लिखी जो @ 6502 के उत्तर (with-mocked-functions) के समान ही है, लेकिन थोड़ा और सामान्य है। यह with-added-methods भी प्रदान करता है जो आपको सीमित गतिशील दायरे के लिए नकली विधियों को लिखने की अनुमति देता है।आप इसे यहां पा सकते हैं: https://github.com/bytecurry/bytecurry.mocks

0

कुछ साल बाद, वहां है। हमारे पास cl-mock और mockingbird दोनों Quicklisp में हैं।

(ql:quickload :mockingbird) 

यह एक भी अगर एक समारोह बुलाया गया था जांच करने के लिए है, तो कितनी बार करता है, तो और जो तर्क के साथ की अनुमति देता है और यह अलग-अलग तरीकों ठूंठ संभव है।

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