2010-12-04 258 views
1

問候,單元測試,黑盒測試時需要多長時間?

我遇到了一個奇怪的問題。

我相信測試代碼時,你在參數X,Y,Z放到一個功能,你需要測試輸出以保證工作正常進行。但是如果你的代碼使用門面模式或者聯繫你可以查詢的「內部」源代碼,但是這很快就會在測試代碼中引起緊耦合問題。

這裏有一個例子:

class Notifier 

    def send_notification action_string 
    # contact messaging server and deliver message 
    end 

end 

class DoSpecialStuff 

    def my_method 
    code.. code.. 
    n = Notifier.new 
    n.send_notification "WOOT" 
    end 

end 

現在,DoSpecialStuff.my_method好好嘗試一下有任何輸出,但其目的是要輸出去的地方抽象的「複雜性」的通知!從而導致無法測試的功能!

我們通過這樣測試這段代碼嗎?現在

def test 
    assert_no_execption_raised do # hurm... a test in name only? 
    o = DoSpecialStuff.new 
    o.my_method 
    end 
end 

,我們可以檢查,其中此消息去,但是從外觀對象的點帶走,我們試圖隱藏的複雜性。

我們可以測試輸出,但應該我們?什麼是正確的?

-daniel

回答

2

它有助於始終牢記的是測試的關鍵在於可以幫助你,你的代碼工作的信心,並將繼續在今後的工作。

這看起來像那種地方互動的測試將是有益的。在DoSpecialStuff的測試中剔除通知程序,以確保它正確使用通告程序。越高,您可能需要嘲笑DoSpecialStuff來測試位於其上的代碼。

+0

但是,當Mock' (urhm)對象,用比較少的「meta」語言(比如ruby),你必須通過通知者或從一些你可以控制的地方傳入。這是因爲通告程序對象是直接在類中創建的。這適用於紅寶石(歡呼!),但什麼是好的和一般的策略。 – Daniel 2010-12-04 01:03:53

0

,可能更符合你的情況的另一種方法是舉實例,並在你的例子可能是方法調用,協作類的另一種方法是這樣的:

class DoSpecialStuff 

    def my_method 
    code.. code.. 
    send_notification   
    end 

    def send_notifier 
    n = Notifier.new 
    n.send_notification "WOOT" 
    end 

end 

原諒我,如果我的語法錯誤,無論這是什麼語言(Ruby?),我都不熟悉。

現在來測試,延長DoSpecialStuff覆蓋send_notification,這樣它要麼什麼也不做,或者你可以驗證它被稱爲與測試(我假設有耀武揚威的全局變量的某種方式或類似)。

1

to allow your tests/code to scale neatly you should decouple your code using an interface,這使得重構簡單得多,otherwise by coupling your code you incur technical debt你可能添加

  1. 接口來解耦代碼
  2. 一個模擬的DoSpecialStuff測試的分離代碼的行爲像您期望
  3. 後更新測試

如果你在C++中編寫代碼,它看起來像

通告程序代碼

Notifier.h 
class Notifier : public I_Notifier 
{ 
    void _sendNotification(NotificationInstance * notification); 
}; 

Notifier.cpp 
void Notifier::_sendNotification(NotificationInstance * notification) 
{ 
    //do some stuff that needs testing 
} 

接口的通知,這是被添加到DoSpecialStuff類解耦代碼 I_Notifier.h

class I_Notifier 
{ 
    void sendNotification(NotificationInstance * notification) { _sendNotification(notification); } 
    virtual void _sendNotification(NotificationInstance * notification)=0; 
} 

模擬用於DoSpecialStuff的測試方面,我們的模擬假設通知程序代碼工作我們的單元測試爲DoSpecialStuff只是爲了確保sendNotification被稱爲,所以我們的測試可以檢查send_notification_called的狀態,看看它是否成功o不是。

Mock_Notifier.h 
struct Test_Notifier : public I_Notifier 
{ 
    Test_Notifier() : send_notification_called(false) 

    virtual void _sendNotification(NotificationInstance * instance) 
    { 
    send_notification_called = true; 
    } 
    bool send_notification_called; 
}; 

DoSpecialStuff代碼注意,此類現在已經到通知類這就是解耦代碼的接口(因此我們的測試不再需要,除非我們使用從中調用包括實際的類

DoSpecialStuff.cpp 
class DoSpecialStuff 
{ 
    DoSpecialStuff(I_Notifier * n) : notifier_(n) {} 
    void DoSpecialStuff::_myMethod(NotificationInstance * notification) 
    I_Notifier * notifier_; 
} 

void DoSpecialStuff::_myMethod(NotificationInstance * notification) 
{ 
    //do some stuff that needs testing 
    n.send_notification (notification) 
} 

接口

I_DoSpecialStuff.h 
class I_DoSpecialStuff 
{ 
    void myMethod(NotificationInstance * notification) { _myMethod(notification); } 
    virtual void _myMethod(NotificationInstance * notification)=0; 
} 

凡功能是

  • 接觸消息服務器和消息遞送消息
上的單元測試頂部

你也有一組功能測試,所以單元測試將測試類的每一個方法(在適當情況下) ,功能測試套件將啓動服務器的一個實例,然後功能測試將調用將與消息傳遞服務器聯繫的功能,然後檢查輸出(無論是數據庫狀態還是返回的信號)