2014-09-02 24 views
1

我目前正在創建一些單元測試。我對他們相當陌生,只是試圖弄溼我的腳。所以我試圖運行的當前測試是根據用戶輸入檢查預期輸出。所以我會用某種類型的值修補輸入,然後檢查最後是否收到stdout消息。聽起來有點混亂,但我希望有人能提供幫助。這是我的運行代碼。Python單元測試If語句的預期輸出

def main(): 


    Attack = input("Are we being attacked?!") 

    if(Attack == "yes"): 
    print("We are being attacked! Attack Back!") 

所以在上面的例子中,我會測試打印語句,因爲我會修補用戶輸入的值爲yes。這裏是我的測試套件

import unittest 
from unittest.mock import patch 
import io 
import sys 

from RunFile import main 

class GetInputTest(unittest.TestCase): 

    @patch('builtins.input', return_value='yes') 
    def test_output(self): 
     saved_stdout = sys.stdout 
     try: 
      out = io.StringIO() 
      sys.stdout = out 
      main() 
      output = out.getvalue().strip() 
      self.assertEqual(output, "We are being attacked! Attack Back!") 
     finally: 
      sys.stdout = saved_stdout 


if __name__ == "__main__": 
    unittest.main() 

所以這顯然不起作用。那麼我錯過了什麼?謝謝大家!

EDITED:這是我運行測試時得到的錯誤消息。我明白這個錯誤,只是不知道如何去解決它。

Error 
Traceback (most recent call last): 
    File "C:\Python33\lib\unittest\mock.py", line 1087, in patched 
    return func(*args, **keywargs) 
TypeError: test_output() takes 1 positional argument but 2 were given 
+0

是明擺着的嗎?會發生什麼呢? 「'我們被攻擊了!'反擊!'與'」Hello Pirate!「有關?」'? – jonrsharpe 2014-09-02 22:06:49

+0

糟糕。我的錯。完全忘記改變這一點。但不管它仍然不適合我。我編輯了我的代碼。 @jonrsharpe – SalceCodec 2014-09-02 22:15:14

+0

您確定在您的測試中調用了正確的「main()」嗎?會發生什麼?它只是在斷言失敗? – shieldstroy 2014-09-02 22:25:06

回答

2

通過patch裝飾的函數將採取Mock作爲附加參數。您需要

@patch('builtins.input', return_value='yes') 
def test_output(self, m): 

其第二個參數m將在Mock對象替換inputtest_output被稱爲參考。

pydoc unittest.mockpatch

如果patch用作裝飾和new是 省略,所創建的模擬傳遞中作爲一個額外的參數到 裝飾功能。

+0

好吧,我試過這個,它有點工作......它給了我「好」,但它通過了測試,無論我的標準輸出,所以基本上預期的標準輸出= – SalceCodec 2014-09-02 22:51:24

+0

它似乎在爲我工作,如果我改變模擬的返回值來改變'main'的作用,或者改變字符串'main'打印,測試就會失敗。 – chepner 2014-09-03 12:32:39

1

除了@ chepner的答案,你需要使用unittest.TestCase的,而assert方法不是聲稱自己(雙關語意)

class TestStuff(unittest.TestCase): 
    @patch('builtins.input', return_value='yes') 
    def test_output(self, new_input): 
     try: 
      out = io.StringIO() 
      sys.stdout = out 
      main() 
      output = out.getvalue().strip() 
      self.assertEqual(output, "We are being attacked! Attack Back!") 
     finally: 
      sys.stdout = saved_stdout 

但是這可能不是做什麼是最好的方式,你正在努力去做。你可以修補多個內建程序,你知道!

class TestStuff(unittest.TestCase): 
    @patch('builtins.input', return_value='yes') 
    @patch('builtins.print') 
    def test_output(self, new_print, new_input): 
     # the mocked functions are passed in opposite order 
     # to where they're decorated 
     main() 
     new_print.assert_called_with("We are being attacked! Attack Back!") 

如果裝飾是可怕的,你甚至可以這樣做:

class TestStuff(unittest.TestCase): 
    def test_output(self): 
     with patch('builtins.input', return_value='yes'), \ 
      patch('builtins.print') as new_print: 
      main() 
      new_print.assert_called_with("We are being attacked! Attack Back!")