2009-01-22 11 views
5

मैं एक बड़े डेल्फी कोड बेस के लिए यूनिट परीक्षण आधारभूत संरचना लिख ​​रहा हूं। मैं SysUtils.FileExists में शुद्ध कार्यों के लिए कॉल को लिंक करना चाहता हूं उदाहरण के लिए "MockSysUtils.FileExists" के लिए।फ़ंक्शन इकाइयों को बदलें

एक ही इंटरफेस के साथ एक SysUtils इकाई बनाना संकलक द्वारा सराहना नहीं की जाती है।

मैं जो सोच रहा हूं वह रनटाइम पर मेरे मॉक फ़ंक्शन में हुक करना है। क्या आजकल यह संभव है?

कोई अन्य सुझाव?

सादर,

पीटर

उत्तर

9

क्रम में आयोजित एक समारोह की जगह मुश्किल है लेकिन आमतौर पर तकनीकी रूप से संभव है। "सभी" आप क्या करने की जरूरत है:

  • सवाल
  • में समारोह का पता लेने के पहले 5 बाइट्स एकत्रित न करने या तो (क आरईटी शिक्षा के लिए जाँच करने के लिए - बहुत छोटे दिनचर्या एक और दिनचर्या साथ लगे होना हो सकता है, को रोकने आप इसे)
  • परिवर्तन से उसकी पेज संरक्षण (VirtualProtect के साथ) की जगह से लिखने योग्य
  • एक जेएमपी rel32 अनुदेश के साथ पहले 5 बाइट्स पुनर्लेखन होना करने के लिए (यानी E9 < ऑफसेट करने के लिए अपने-समारोह>)
  • लागू अपने सामान्य रूप से वर्जन फ़ंक्शन, यह सुनिश्चित कर लें कि इसमें sa है मुझे तर्क और कॉलिंग सम्मेलन के रूप में आप जिस मजाक कर रहे हैं

SysUtils.pas के एक अलग संस्करण के खिलाफ एक आसान तरीका लिंक करना होगा। इसके लिए आपको आरटीएल और वीसीएल में सभी इकाइयों को फिर से कंपाइल करने की आवश्यकता होगी जो SysUtils.pas पर निर्भर करते हैं, लेकिन ऊपर वर्णित फ़ंक्शन इंट्रुमेंटेशन दृष्टिकोण की तुलना में यह काफी आसान है।

सबसे आसान तरीका भाषा-स्तर एक है, जहां आप सीधे SysUtils पर भरोसा नहीं करते हैं (और इसलिए उच्च स्तर पर स्विच कर सकते हैं), या आप सशर्त रूप से एक अलग इकाई को संदर्भित करने के लिए uses घोषणा को संशोधित करते हैं ।

+0

"या आप सशर्त रूप से एक अलग इकाई को संदर्भित करने के लिए उपयोग घोषणाओं को संशोधित करते हैं।" - मुझे मारता है कि यह इसके लिए सबसे आसान होना चाहिए। सुनिश्चित करें कि आपकी विशेष इकाई आखिरी है, और फिर आप किसी भी फ़ंक्शन को फिर से परिभाषित कर सकते हैं। – mj2008

+0

यह मानता है कि यूनिट स्रोत उपलब्ध है। यदि यह है, तो यह एक ब्रेनर है; हालांकि, प्रश्नकर्ता ने विशेष रूप से रनटाइम के बारे में पूछा था! –

+0

मुझे विडंबना पसंद है :) लेकिन आप पूरी तरह से सही हैं। +1 – guerda

0

धन्यवाद,

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

पहला दृष्टिकोण शायद एक समारोह के लिए ठीक है, लेकिन इस मामले में मुझे लगता है।

मैं दूसरे दृष्टिकोण के लिए जाऊंगा।

6

आप इसे MadCodeHook के साथ कर सकते हैं। HookCode फ़ंक्शन का उपयोग करें, इसे उस फ़ंक्शन का पता दें जिसे आप प्रतिस्थापित करना चाहते हैं और उस फ़ंक्शन का पता जिसे आप इसके बजाय बुलाया जाना चाहते हैं। यह आपको एक फ़ंक्शन पॉइंटर वापस देगा जो आप मूल को कॉल करने और बाद में अनहेक करने के लिए उपयोग कर सकते हैं। संक्षेप में, यह बैरी के विवरण के मध्य तीन चरणों को लागू करता है।

मुझे लगता है कि मैडकोडहूक व्यक्तिगत उपयोग के लिए स्वतंत्र है। यदि आप उससे कुछ बेहतर खोज रहे हैं, तो आप an old version of the Tnt Unicode controls ढूंढने का प्रयास कर सकते हैं।यह वीसीएल के कुछ कोडों में यूनिकोड समर्थन को इंजेक्ट करने के लिए एक ही हुकिंग तकनीक का उपयोग करता था। आपको पुराने संस्करण की आवश्यकता होगी क्योंकि अधिक हालिया रिलीज अब मुक्त नहीं हैं। TntSystem.pas में फ़ंक्शन पाएं, यह भी है जहां आपको इसका उपयोग करने के उदाहरण मिलेंगे।

कोड-हुकिंग अच्छा है क्योंकि आपको आरटीएल और वीसीएल को फिर से कंपाइल करने की आवश्यकता नहीं है, और इसमें यह नियंत्रित करने के लिए सशर्त संकलन शामिल नहीं है कि कौन से कार्य दायरे में हैं। आप कोड को अपनी यूनिट-टेस्ट सेटअप प्रक्रिया से हुक कर सकते हैं, और मूल कोड कभी अंतर नहीं जान पाएगा। ऐसा लगता है कि यह मूल FileExists फ़ंक्शन (क्योंकि यह है) को कॉल कर रहा है, लेकिन जब यह वहां जाता है, तो यह तुरंत आपके मॉक किए गए संस्करण पर कूद जाएगा।

0

यह थोड़ा रास्ता है लेकिन यहां एक और विकल्प है।

जब आपके इकाई परीक्षण और अपने मुख्य codebase निर्माण इसके साथ जाने के लिए, आप का उपयोग करने के

बजाय

fileexists(MyFilename); 

आप grep सकता है सभी कार्यों आप बदल सकते हैं और इकाई निर्दिष्ट करना चाहते grep सकता है fileexists और आप का निर्माण समय पर यह काम किया है (स्वचालित निर्माण उपकरण का उपयोग कर)

MockTests.fileexists(MyFileName); 

के साथ बदलें यह आसानी से किया जा सकता है और जीआरई के साथ आप प्रदान करेगा सबसे लचीलापन। आपके पास बस एक कॉन्फ़िगरेशन फ़ाइल हो सकती है जो सभी कार्यों को प्रतिस्थापित करने के लिए सूचीबद्ध किया गया हो।

1

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

आपका MockSysutils इकाई:

unit MockSysutils; 

interface 

function FileExists(...) ... 
... 
end. 

आपका इकाई, आप परीक्षण करना चाहते हैं:

unit UnitTotest; 

interface 

uses 
    Sysutils, 
    MockSysUtils; 

... 

    if FileExists(...) then 

fileexists अब MockSysutils से बजाय Sysutils से संस्करण कॉल करेंगे।

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