הי, 1) קודם כל רציתי להעיר שלפעמים יותר פשוט (וגם יותר מדמה את המצב האמיתי שאתה בודק) פשוט לדרוך על המשתנים הרלוונטיים במודול הקיים. במקרה שלך למשל, היה מספיק לעשות:
import cgi cgi.FieldStorage = get_params (כאשר אתה עושה import mytestcgi המודול cgi לא יאותחל מחדש, כי הוא כבר ב- sys.modules). 2) טעינת מודול (import) לא אמורה להריץ קוד ביצועי, אלא לבצע פעולות איתחול בלבד. במודולים שרוצים שיהיה אפשר להשתמש בהם גם בתור סקריפט, נהוג לכתוב משהו כמו: if __name__ == "__main__": run_main() (כאשר הקוד הביצועי נמצע בפונקציה run_main). ולמה אני אומר את זה? כי בדוגמה שלך נראה כאילו פעולת import mytestcgi אמורה להדפיס את פלט ה- cgi. אילו mytestcgi היה כתוב לפי הנוהג שציינתי לעיל אז החישובים וההדפסות נעשים לא בזמן ה- import, אלא כאשר קוראים ל- run_main. במקרה כזה אפשר לבצע את הדריכה על המשתנים שבסע' 1 בצורה קצת יותר ממוקדת, או אפילו להחליף את cgi באוביקט משלך מבלי להתעסק עם sys.modules בכלל: import mytestcgi # I assume mytestcgi does "import cgi" mytestcgi.cgi = my_cgi_object # see comment below mytestcgi.run_main() (הערה: אם mytestcgi עושה "from cgi import ..." ולא import cgi, אז צריך לדרוך נקודתית על שמות הפונקציות שנטענו במקום על השם cgi) 3) סתם rant לגבי דריכות על מודולים : יש חבילות - למשל Pmw, שמחליפות (ב- sys.modules) מודולים באוביקט משלהן, שאמור להתנהג כמו מודול. מכיוון שהחיקוי אינו מלא זה גורם לצרות צרורות, וכל מיני דברים מפסיקים לעבוד. נניח כאשר מנסים לעבור גרסת פיתון או להשתמש ב- import hooks. בקיצור: לקוד פנימי, בדיקות ודיבג הכל טוב ויפה, אבל כאשר רוצים להפיץ חבילת תוכנה למשתמשים כדאי לנסות לעבוד בצורה פשוטה ולהמנע מהתחכמויות מיותרות. Shlomi Fish wrote: > שלום לכולם! > > אחד האלמנטים המרכזיים בתאוריה של בדיקות קוד היא זו של חיקוי (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 האמיתי (שכלל לא נטען) נותן > לו. > בברכה, עמית