前面講到要做一體化自動化測試框架,那么,最重要的是要解決什么呢?
相信了解windows編程的人員,都能發現這個問題所在。在窗體中,寫下代碼,控制每一個控件的輸入是非常簡單的事。但是,一旦顯示了一個模態窗體,原有的流程代碼會不再往下執行,而是停留在新窗體中,等待消息相應。這就是我們代碼控制界面的關鍵問題。
這是什么道理呢?
我使用的是delphi系統,所以我可能使用vcl框架來解釋這個問題。但是其他語言同樣適用。
在windows程序中,winmain是入口。而winmain的處理,就是一個典型的死循環,先從消息隊列中取出消息,然后再給各窗體派發消息。
為了方便理解,我們將這個模型簡化,就是一個死循環a。中間在處理任意的代碼。
現在,由于調用了某一段處理,進入了另外一個死循環b。當代碼從a函數進入了b,那么當然,a循環下面的代碼當然只能停留下來,直到b循環結束。
而在windows界面中,模態窗體就是一個消息死循環。當windows彈出一個模態窗體的時候,其消息隊列獨立處理,不再走整個應用程序的消息循環。
現在比較明白了,不能方便控制界面的原因在于windows應用程序并不是流程化的,而是消息驅動的。
明白了這個道理,就有可能找到突破口。我想到了鉤子。在delphi中使用鉤子,推薦使用fastcode。
既然程序從a循環進入到b循環,我不能繼續執行a循環的代碼,那么,可不可以在進入b循環后,繼續執行a的代碼呢?
這應該是可行的。關鍵在于我必須做到b循環中,能夠調用到我的代碼。
在delphi的一般窗體,你可以通過使鉤子hook住tform的doshow方法。那樣,窗體不管是否是showmodal的,都會觸發,然后通過給此窗體發送一個特殊消息,并在此窗體中,使用鉤子,處理此消息。那么就可以在窗體完全顯示之后,真正處理你的任務了。這里有一個技巧,窗體真正顯示,并不是調用doshow的時候,而是經過windows的消息循環,完全處理好所有顯示相關消息之后。這里,通過消息循環機制,給它發送一個額外消息,那么可以保障,觸發你的任務的時機,是在窗體處理完原有消息之后。
當然了,在vcl中,并不是這么簡單就能處理所有問題。最主要的是那些標準windows窗體,比如messagebox,opendialog。這些窗體不是由tform組合而成的。所以對象和消息機制都不一樣。需要單獨處理。
這里有一種方式,是通過定時器,定時查詢活動窗體狀態。如果檢測到非標準windows窗體,手動觸發你的任務。也是一種權衡解決方式。
由于代碼版權問題,我這里不能貼出這些代碼,不過主要意思應該都講清楚了吧。
總結以下這個關鍵點:
消息機制和流程代碼的沖突,是根本原因
簡單的模型,就是循環嵌套循環問題
使用鉤子,在循環開始處,觸發任務
這樣,基本就可以控制界面了。
文章來源于領測軟件測試網 http://www.kjueaiud.com/