파이썬 디버깅 - 04 실전 디버깅!

핏자·2023년 4월 9일
0

인공지능사관학교

목록 보기
12/31
post-thumbnail
  • 빠른 복습

- 디버깅이란?

사용/테스트 중 찾아낸 버그를 없애 나가는 과정


* 버그의 원인을 찾고

* 발생한 버그를 해결하고

* 비슷한 버그의 재발을 방지하는 것


- 사용자 경험과 직결

버그로 인한 불쾌한 경험 > 새로운 기능


- 처음부터 완벽한 코드는 없다

코드가 잘 작동하지 않을 때 -> 어... 왜 안되지?

코드가 한 번에 작동할 때 -> 어... 왜 벌써 되지?


빠르게 문제를 파악/해결하는 것이 능력!


- 실패는 성공의 어머니

많은 버그를 경험할 수록,

안전한 코드를 설계하는 능력이 생긴다!


- 에러 메시지 읽기

Traceback ( most recent call last) :
 File "main.py", line 4, in <module>
  greeting("Donald Trump")
 File "main.py", line 2, in greeting
  print("Hello", yourname + "!")
NameError: name'yourname' is not defined # 오류

- Syntax error

컴퓨터가 이해할 수 없는 코드

def add_all(numbers):
	result = 0 
	for number in numbers #for문 끝에 :가 빠졌다
    	result += number
	reutrn result

- Name error

정의한 적 없는 변수

def add_all(numbers):
	result = 0 
	for number in numbers:
    	result += numbre #number 오타
	reutrn result
add_all([1,2,3])

- Type error

숫자와 'won'을 더할 수 없음

def usd_to_krw(price):
	price_in_krw = price * 1100 
	reutrn price_in_krw + " won" # str(price_in_krw) 변경
    
usd_to_krw(4.99)

- Index error

문자열의 0번째 글자가 존재하지 않음

def first_character(string):
	reutrn string[0] # if len(string) > 0: 추가

first_character("") 

- Zero division error

0으로 나눌 수 없음

def average(numbers):
	return sum(numbers) / len(numbers) # if len(numbers)>0: 추가

average([])

- try / except

def average(numbers):
	try:
		return sum(numbers) / len(numbers)
	except ZeroDivisionError:
		print("No numbers!")

- 유닛테스트

Unit(가장 작은 단위 = 함수 1개) Test


테스트 작성을 어떻게 작성하느냐에 따라

어떤 출력을 의도하는지가 결정됨


즉, 테스트 == 설계


- 유닛테스트의 조건

1. 읽기 쉽다, 2. 독립적이다, 3. 충분히 작다, 4. 충분히 넓다


- unittst

import unittest

class IsPalindromeTests(unittest.TestCase):
	def test_level(self):
    	self.assertTrue(is_palindrome("level"))
	def test_level(self):
    	self.assertFals(is_palindrome("lever"))
unittest.main()



  • 이번 주 미션 소개

- 계산기

class calculator():
	def clear():
    	...
	def press_digit(digit):
    	...
	def press_plus():
    	...
class calculatorTest(unittest.TestCase):
	def test_press_one_digit(self):
    	...
	def test_press_multiple_plus(self):
    	...
	def test_press_clear_after_writing(self):
    	...

- 계산기 테스트 / 디버깅

스켈레톤 코드 이해 -> 테스트 코드 작성 -> 테스트에 실패한 부분 수정








  • 실습문제1. 계산기 테스트 / 디버깅

    계산기 자체를 구현하는 calculator.py와 구현한 계산기를 테스트하는 코드인 calculator_test.py 를 수정하여라

    calculator.py

    Calculator 클래스는 계산기 버튼의 종류에 따라 4가지의 메소드를 가집니다.
    press_digit(): 숫자 버튼을 눌렀을 때의 동작을 구현합니다. 0부터 9까지의 숫자를 인자로 받을 수 있으며
    assert() 문에 의해 이 외의 인자가 들어온 경우 에러가 발생합니다.
    press_operator(): 연산자 버튼을 눌렀을 때의 동작을 구현합니다. +, -, * , / 중 하나의 기호를 인자로 받을 수 있습니다. 이외의 인자가 들어온 경우 에러가 발생합니다.
    press_equal(): = 버튼을 눌렀을 때의 동작을 구현합니다.
    press_clear(): 클리어, 즉 계산기의 C 혹은 AC 버튼을 눌렀을 때의 동작을 구현합니다.

    calculator_test.py

    Calculator의 동작을 테스트하는 코드입니다. 파이썬의 unittest 모듈을 사용하며, 각 테스트 함수 별로 설명이 적혀 있습니다. 설명을 읽고, 그대로 구현하면 됩니다.

# calculator.py
def operate(n1, n2, operator):
    if operator == '+':
        return n1 + n2
    if operator == '-':
        return n1 - n2
    if operator == '*':
        return n1 * n2
    if operator == '/':
        return n1 / n2

class Calculator:
    operators = ['+', '-', '*', '/']

    def __init__(self):
        self.current_number = 0
        self.current_operator = None
        self.memory = None


        self.last_input = None
    
    def press_digit(self, digit):
        assert(type(digit) is int)
        assert(0 <= digit <= 9)
        if self.last_input is None or type(self.last_input) is int:
            self.current_number = self.current_number * 10 + digit
        elif type(self.last_input) is str:
            self.memory = self.current_number
            self.current_number = digit
        self.last_input = digit
    
    def press_operator(self, operator):
        assert(operator in self.operators)
        if self.memory is not None:
            self.current_number = operate(self.memory, self.current_number, self.current_operator)
        self.current_operator = operator
        self.last_input = operator
    
    def press_equal(self):
        if self.memory is not None:
            self.current_number = operate(self.memory, self.current_number, self.current_operator)
        self.last_input = None
    
    def press_clear(self):
        self.current_number = 0
        self.current_operator = None
        self.memory = None
        self.last_input = None
# calculator_test.py
import unittest
from calculator import Calculator

class AdditionTests(unittest.TestCase):
    # "3 + 8 =" 을 입력하고 결과를 확인합니다.
    def test_add_two_numbers(self):
        calculator = Calculator()
        calculator.press_digit(3)
        calculator.press_operator('+')
        calculator.press_digit(8)
        calculator.press_equal()
        self.assertEqual(calculator.current_number, 3 + 8)
    
    # "13 + 24 + 37 =" 을 입력하고 결과를 확인합니다.
    # 위의 코드를 참고해 테스트 코드를 완성하세요.
    def test_add_two_2_digit_numbers(self):
        calculator = Calculator()
        calculator.press_digit(1)
        calculator.press_digit(3)
        calculator.press_operator('+')
        calculator.press_digit(2)
        calculator.press_digit(4)
        calculator.press_operator('+')
        calculator.press_digit(3)
        calculator.press_digit(7)
        calculator.press_equal()
        self.assertEqual(calculator.current_number, 13 + 24 + 37)


class SubtractionTests(unittest.TestCase):
    # "99 - 37 =" 을 입력하고 결과를 확인합니다.
    # 위의 코드를 참고해 테스트 코드를 완성하세요.
    def test_subtract_two_numbers(self):
        calculator = Calculator()
        calculator.press_digit(9)
        calculator.press_digit(9)
        calculator.press_operator('-')
        calculator.press_digit(3)
        calculator.press_digit(7)
        calculator.press_equal()
        self.assertEqual(calculator.current_number, 99 - 37)
    
    # "37 - 24 + 17 =" 을 입력하고 결과를 확인합니다.
    # 위의 코드를 참고해 테스트 코드를 완성하세요.
    def test_subtract_three_numbers(self):
        calculator = Calculator()
        calculator.press_digit(3)
        calculator.press_digit(7)
        calculator.press_operator('-')
        calculator.press_digit(2)
        calculator.press_digit(4)
        calculator.press_operator('+')
        calculator.press_digit(1)
        calculator.press_digit(7)
        calculator.press_equal()
        self.assertEqual(calculator.current_number, 37 - 24 + 17)


class ClearTests(unittest.TestCase):
    # "9 C 8 + 7 =" 을 입력하고 결과를 확인합니다. (C는 clear)
    def test_clear_between_numbers(self):
        calculator = Calculator()
        calculator.press_digit(9)
        calculator.press_clear()
        calculator.press_digit(8)
        calculator.press_operator('+')
        calculator.press_digit(7)
        calculator.press_equal()
        self.assertEqual(calculator.current_number, 8 + 7)
    
    # "9 + 8 = C 1 + 1 =" 을 입력하고 결과를 확인합니다. (C는 clear)
    # 위의 코드를 참고해 테스트 코드를 완성하세요.
    def test_clear_between_operations(self):
        calculator = Calculator()
        calculator.press_digit(9)
        calculator.press_operator('+')
        calculator.press_digit(8)
        calculator.press_equal()
        calculator.press_clear()
        calculator.press_digit(1)
        calculator.press_operator('+')
        calculator.press_digit(1)
        calculator.press_equal()
        self.assertEqual(calculator.current_number, 1 + 1)

unittest.main()
profile
개발자 핏자의 로그들

0개의 댓글