Programing/TDD

파이썬 TDD 예제: 숫자야구게임 만들기 #2 (feat. unittest)

뇌님 2023. 1. 28. 02:21
반응형

지난 글에 이어, TDD방식으로 숫자야구 프로그램과 그 테스트코드를 만든 과정을 공유합니다.

 

파이썬 TDD 예제: 숫자야구 프로그램 만들기 #1 (feat. unittest)

TDD 연습으로 숫자야구게임 만들기를 많이 하길래, 저희 사내스터디에서도 책갈이를 한 이후에 숫자야구게임을 각자 만들어보기로 했습니다. 만들면서 느꼈던 점, 서로 피드백을 하면서 추가로

brain-nim.tistory.com

 

테스트X : 플레이 가능하게 변경

NumberBaseball_test.py

# 다섯번째 테스트 코드와 동일

NumberBaseball.py

import random

class Game:
    def __init__(self, correct_answer=None):
        if correct_answer:
            self.correct_anser = correct_answer
        else:
            self.correct_anser = random.sample(['0','1','2','3','4','5','6','7','8','9'],3)
            self.correct_anser = ''.join(self.correct_anser)

    def guess_checker(self, guess):
        if guess == self.correct_anser:
            return "3S"

        # out/ball check
        out_checker = 0
        ball_checker = 0
        for n in guess:
            if n in self.correct_anser:
                ball_checker += 1
            else:
                out_checker += 1

        if out_checker == 3:
            return "OUT"


        # strike check
        strike_checker = 0
        for i in range(3):  # 3자리 수 숫자
            if guess[i] == self.correct_anser[i]:
                strike_checker += 1

        # revise ball check
        ball_checker -= strike_checker

        return f"{strike_checker}S {ball_checker}B"


if __name__ == '__main__':
    game = Game()

    result = ""
    count = 0
    while result != "3S":
        count += 1
        guess = input("3자리 숫자입력 : ")
        result = game.guess_checker(guess)
        print(result)

    print(f"축하합니다. 정답은 {game.correct_anser} 였습니다")
    print(f"{count}번 만에 정답을 맞췄습니다!")

 

만들면서 생각난 것

- 사실 다섯번째 테스트까지만 하고 다 만들었다고 생각했었습니다.

- 그래서 if __name__ == '__main__'을 통해 게임플레이가 가능하도록 작업했습니다.

- 그런데 만들고 나서 테스트를 하다보니 제가 몇가지 예외를 잊고 있었다는 것을 깨달았습니다.

- 지난 글에서 밝힌 것 처럼, 여섯번째, 일곱번째 테스트를 추가로 진행하였습니다.

 

 

여섯번째 테스트 : 예측 숫자가 3자리 숫자가 아닌 경우 length_error

NumberBaseball_test.py

import unittest
from NumberBaseball import Game

class NumberBaseballTest(unittest.TestCase):
    def assertGuessResult(self, correct_answer, guess_answer, right_chk_result):
        game = Game(correct_answer)
        game_chk_result = game.guess_checker(guess_answer)
        self.assertEqual(right_chk_result, game_chk_result)

    # 앞선 테스트 생략

    def test_guess_more_or_less_than_3_length_then_length_error(self):
        self.assertGuessResult("369", "1", "LENGTH_ERROR")
        self.assertGuessResult("369", "12345678", "LENGTH_ERROR")

NumberBaseball.py

import random

class Game:
    def __init__(self, correct_answer=None):
        if correct_answer:
            self.correct_anser = correct_answer
        else:
            self.correct_anser = random.sample(['0','1','2','3','4','5','6','7','8','9'],3)
            self.correct_anser = ''.join(self.correct_anser)

    def guess_checker(self, guess):
        if len(guess) != 3:
            return "LENGTH_ERROR"

        # 중간 코드 생략
        
        return f"{strike_checker}S {ball_checker}B"


if __name__ == '__main__':
    game = Game()

    result = ""
    count = 0
    while result != "3S":
        guess = input("3자리 숫자입력 : ")
        result = game.guess_checker(guess)
        if result == "LENGTH_ERROR":
            print("입력숫자 에러!! 세자리 숫자만 입력해 주세요")
            continue
        print(result)
        count += 1


    print(f"축하합니다. 정답은 {game.correct_anser} 였습니다")
    print(f"{count}번 만에 정답을 맞췄습니다!")

 

 

 

일곱번째 테스트 : 똑같은 숫자를 중복입력하는 경우 duplicate_error

NumberBaseball_test.py

import unittest
from NumberBaseball import Game

class NumberBaseballTest(unittest.TestCase):
    def assertGuessResult(self, correct_answer, guess_answer, right_chk_result):
        game = Game(correct_answer)
        game_chk_result = game.guess_checker(guess_answer)
        self.assertEqual(right_chk_result, game_chk_result)

    # 앞선 테스트 생략
    
    def test_guess_more_or_less_than_3_length_then_length_error(self):
        self.assertGuessResult("369", "1", "LENGTH_ERROR")
        self.assertGuessResult("369", "12345678", "LENGTH_ERROR")

    def test_guess_duplicate_number_then_duplicate_error(self):
        self.assertGuessResult("369", "333", "DUPLICATE_ERROR")
        self.assertGuessResult("369", "110", "DUPLICATE_ERROR")

NumberBaseball.py

import random

class Game:
    def __init__(self, correct_answer=None):
        if correct_answer:
            self.correct_anser = correct_answer
        else:
            self.correct_anser = random.sample(['0','1','2','3','4','5','6','7','8','9'],3)
            self.correct_anser = ''.join(self.correct_anser)

    def guess_checker(self, guess):
        if len(guess) != 3:
            return "LENGTH_ERROR"

        if len(set(guess)) !=3:
            return "DUPLICATE_ERROR"

        # 중간 코드 생략

        return f"{strike_checker}S {ball_checker}B"


if __name__ == '__main__':
    game = Game()

    result = ""
    count = 0
    while result != "3S":
        guess = input("3자리 숫자입력 : ")
        result = game.guess_checker(guess)
        if result == "LENGTH_ERROR":
            print("입력숫자 에러!! 세자리 숫자만 입력해 주세요")
            continue
        elif result == "DUPLICATE_ERROR":
            print("입력숫자 에러!! 동일한 숫자를 중복으로 입력할 수 없습니다")
            continue

        print(result)
        count += 1


    print(f"축하합니다. 정답은 {game.correct_anser} 였습니다")
    print(f"{count}번 만에 정답을 맞췄습니다!")

 

플레이 화면

 

이번 스터디에서 숫자야구 프로그램 개발을 해보면서, 그리고 함께 피드백 하면서 다양한 것을 확인하고 느낄 수 있었습니다.

 

대역이라던가, 숫자가 아닌 문자에 대한 처리 등, 저는 빠뜨린 부분들이 많이 있지만,

여러분들은 더욱 완벽하게 만드실 수 있을 겁니다👍

반응형