שלום לכולם!

אחד האלמנטים המרכזיים בתאוריה של בדיקות קוד היא זו של חיקוי (Mocking). הכוונה 
היא ליצור אלמנט תכנותי שעבור הקוד הנבדק מתנהג כמו האלמנט הרגיל, אך למעשה אנו 
שולטים בו, ומכתיבים מה הוא יחזיר, ועוקבים אחריו.

כעת נניח שיש לנו קוד קיים שטוען מודול וקורא לאובייקטים ופונקציות ממנו: איך 
נוכל לעשות חיקוי של המודול מבלי לשנות את הקוד של המודול הנבדק?

אני מימשתי קוד כזה בפרל כאן:

http://search.cpan.org/src/SHLOMIF/SVN-RaWeb-Light-0.6.0/SVN/RaWeb/Light/Mock/CGI.pm

השורה המשמעותית היא:

BEGIN
{
    $INC{'CGI.pm'} = "/usr/lib/perl5/site_perl/5.8.6/CGI.pm",
}

שגורמת למפרש לחשוב שהמודול כבר נטען.

תהיתי איך אפשר לעשות זאת בפייתון. קראתי על כך שהפקודה import רושמת את המודול 
במשתנה sys.modules ולכן חיפשתי דרך לרשום שם מודול משלי. אחרי מספר נסיונות 
ודיבורים עם אנשים ב-IRC, הצלחתי לכתוב קוד הוכחת-היתכנות שמחקה את מודול cgi:

<<<<<<<<<<<<
import sys
import new
from StringIO import StringIO

class cgi_param:
    def __init__(self, value):
        self.value = value
    def value(self):
        return self.value
    
def get_params():
    return {"hello":cgi_param("ShlomifTest")}

cgi_mod = new.module("cgi");
cgi_mod.FieldStorage = get_params
sys.modules['cgi'] = cgi_mod

save_stdout = sys.stdout
sys.stdout = StringIO()
import mytestcgi

buffer = sys.stdout.getvalue()

sys.stdout = save_stdout

if (buffer == "Content-Type: text/html\n\n\nShlomifTest\n"):
    print "ok"
else:
    print "not ok: buffer == " + buffer

>>>>>>>>>>>>

מה שקורה הוא שכאשר טוענים את המודול "mytestcgi" אשר מכיל את הקוד, אז הוא קולט 
את המשתנים שאנו נותנים לו, ולא את מה שהמודול cgi האמיתי (שכלל לא נטען) נותן 
לו.

בכבוד רב,

        שלומי פיש

---------------------------------------------------------------------
Shlomi Fish      [EMAIL PROTECTED]
Homepage:        http://www.shlomifish.org/

Tcl is LISP on drugs. Using strings instead of S-expressions for closures
is Evil with one of those gigantic E's you can find at the beginning of 
paragraphs.

לענות