2017-07-11 7 views
-2

最近Pythonで初めてプログラミングを始めました。私はこのコードの単体テストの本質にアクセスできないと言われました。私はユニットテストとPythonユニットテストの重要性に耳を傾けて練習しようとしました。単体テストを単純な数値の再生コードに適用したい

コードを以下に示します。

# UpDown.py 

import random 
import unittest 

servicenumber = 0 
exp = 0 

## Game play screen 
def start_screen(): 
    global servicenumber 
    exe = """ 
============================== 
1. Up/Down Game Start 
2. Exp check 
3. exit 
============================== 
Please enter your desired service number.""" 

    print(exe) 
    servicenumber = input() 
    if servicenumber == 1: 
     start_game() 
    elif servicenumber == 2: 
     check_exp() 
    elif servicenumber == 3: 
     game_exit() 
    else: 
     print "Please enter one of 1, 2, or 3." 


## Up/Down This is the part of the game. 
def start_game(): 
     re = 1 
     global servicenumber 
     global exp 
     if servicenumber == 1: 
      while re != 0: 
       notice = """ 
    ============================== 
    Randomly generated values ​​are from 1 to 100. 
    Players should enter a number between 1 and 100. 
    If you win, you gain 2 exp, and if you lose, it decreases by 1. 
    Please enter 0 to finish. 
    ==============================\n""" 
       print(notice) 
       var = input('input : ') 
       if var > 100: 
        print 'Please enter a value between 1 and 100.' 
        continue 
       elif var < 0: 
        print 'Please enter a value between 1 and 100.' 
        continue 
       elif var == 0: 
        re = 0 
       else: 
        print '' 

       randvalue = random.randrange(1,101) 
       if var > randvalue: 
        print 'Up' 
        exp = exp + 2 
        print "exp+2" 
        print "Your experience ",exp 
        print "Randomly generated values ",randvalue 
        continue 
       elif var < randvalue: 
        print 'Down' 
        exp = exp-1 
        print 'Decreasing story ~~' 
        continue 
       elif var == randvalue: 
        print 'The story of being tapped ~~' 
        continue 
       else: 
        print "Randomly generated values ",randvalue 
        continue 
     start_screen() 


def check_exp(): 
    global servicenumber 
    if servicenumber == 2: 
     print "Experience: ",exp 
     start_screen() 


## (exit) 
def game_exit(): 
    global servicenumber 
    if servicenumber == 3: 
     print 'Exit' 
     exit() 


if __name__ == "__main__": 
    start_screen() 
else: 
    print "Imported. Start unit testing.\n" 

そして、私は を実践しようとしたコードは、私はそれは無意味だと思います。

import unittest 
import UpDownGame 

class testing(unittest.TestCase): 
    def test_start(self): 
     self.assertTrue(UpDownGame.start_screen) 

    def test_game(self): 
     self.assertTrue(UpDownGame.start_game) 

    def test_chkexp(self): 
     self.assertTrue(UpDownGame.check_exp) 

    def test_exit(self): 
     self.assertTrue(UpDownGame.game_exit) 


def initialize(): 
    return testing 


if __name__ == "__main__": 
    testsuite = (unittest.makeSuite(testing)) 
    unittest.TextTestRunner(verbosity=2).run(testsuite) 

ですから、単体テストに関するアドバイスが必要です。 このコードにユニットテストを適用する方法を教えていただければ、本当にありがとうございます。 また、必要な基礎知識があると思ったら教えてください。

ありがとうございます。

答えて

0

問題は、すでにコードを書いたときにテストを書くことであり、本質的にコードをテストするのが難しいということです。コードの各部分がテストされる前にテストを書いたのであれば、コードを全く違った形で書くでしょう。

コードを完全に無視すると、プロンプトが表示され、入力が読み込まれ、その入力に基づいて関数が呼び出される 'start_screen'関数が必要になります。呼び出される関数をハードワイヤリングしたくないので(テストするのが難しくなるため)、アクションの辞書を取り、その関数の代わりにテストアクションを渡すことができるように関数を変更する可能性があります実際のコードが実行されます。また、input()からの読み取りを希望しないので、再度カスタマイズすることもできます。 printで出力を書き込むこともテストには悪い考えです。なぜなら、出力をキャッチしたいのであれば出力をキャッチしたいのですが、今は無視します。

だから、へdef start_screen()を変更:

DEFAULT_ACTIONS = { 1: start_game, 2: check_exp, 3: game_exit } 
def start_screen(actions=DEFAULT_ACTIONS, input=input): 
    pass 

とテストを書く:

def test_start_input_1_calls_action_1(self): 
    calls = [] 
    dummy_actions = { 1: lambda: calls.append('action1') } 
    def dummy_input(): 
     calls.append('input') 
     return 1 
    start_screen(actions=dummy_actions, input=dummy_input) 
    assert calls == ['input', 'action1'] 

次のあなたは、テストがコンパイルし、実行し、アサーションエラーで失敗していることを確認します。それ以外の理由で失敗した場合は、テストを修正します。

そのときだけ、start_screenを変更してテストに合格します。

次に、他のテストを追加できます。

def test_start_input_4_prompts_again(self): 
    calls = [] 
    inputs = [1, 4] 
    dummy_actions = { 1: lambda: calls.append('action1') } 
    def dummy_input(): 
     calls.append('input') 
     return inputs.pop(0) 
    start_screen(actions=dummy_actions, input=dummy_input) 
    assert calls == ['input', 'input', 'action1'] 

今、あなたがそのよう、あなたはコードを変更、あなたはアサーションエラーを取得していることを確認します。良い次のテストは、「入力」機能が4にそれが初めて呼び出されたとき、次に1を返すものであろうテストは合格になります。今、最も重要なステップ:次の2つのテストを見て、彼らはこのような何かを見て、あなたが別の関数の重複を削除して、テストを変更するように、彼らはほとんど同じであることを参照してください。

def test_start_input_1_calls_action_1(self): 
    self.start_helper([1], ['input', 'action1']) 

def test_start_input_4_prompts_again(self): 
    self.start_helper([4, 1], ['input', 'input', 'action1']) 

def start_helper(self, inputs, expected_calls): 
    ... add code here ... 

その後、書くために行くを他の機能をテストします。グローバル変数を失いたくなるでしょう:テストされた関数は、外部に設定された変数に依存せず、きれいである必要があります。また再帰的に呼び出すことはおそらく間違っていると思いますが、start_screenにループがあることを考慮する必要があるかもしれません。その場合は、今書き込んだテストを更新する必要があります。

すべてのステップで、すでにテストを書いているという事実が、コードについてのあなたの考え方に影響を与えます。