# [Python] 테스팅과 디버깅

## 테스팅과 디버깅

---

### 단위 테스트와 테스트 주도 개발

[unittest — Unit testing framework](https://docs.python.org/3/library/unittest.html)

**단위 테스트 Unit test**

- 개별 함수나 메서드와 같은 코드의 가장 작은 단위가 예상대로 동작하는지 검증

- `unittest` 모듈을 이용해 단위 테스트르르 작성 및 실행 가능

- 표준 라이브러리는 아니지만 nose2, pytest와 같은 패키지를 사용하기도 한다

**테스트 주도 개발**

1. 명세 기준으로 테스트 케이스 정의

2. 테스트 케이스를 통과할 수 있는 코드 작성

3. 통과하면 새로운 기능 추가

```javascript
# test.py
import unittest

def add(x, y):
    return x + y
    
class TestAdd(unittest, TestCase):
    def test_add(self):
        self.assertEqual(add(1, 2), 3)

if __name_ == '__main__':
    unittest.main()
```

- 테스트를 먼저 작성하고 그 테스트를 통과하도록 코드를 구현

- 코드의 품질 향상, 버그를 줄일 수 있다

### 디버깅 기법과 도구 활용

[pdb — 파이썬 디버거](https://docs.python.org/ko/3.13/library/pdb.html)

- 프로그램에서 오류를 찾아내고 그 원인을 알아내어 수정하는 작업

- 대부분의 통합개발환경(IDE)들은 디버깅 도구를 제공

```javascript
import pdb

def add_to_ten(num):
    result = num + 10
    pdb.set_trace() # 디버거를 실행. break 포인트
    return result

add_to_ten(5)
```

- `h`: 도움말

- `n`: 현재 라인 실행 후 다음 라인으로 넘어간다

- `s`: 현재 라인 실행 후 다음 스텝을 진행

- `c`: break point가 있을 때까지 계속 실행

- `q`: 중단

```javascript
import pdb

def add(a, b):
    return a + b

def test():
    for i in range(10):
        x = add(i, 10)
        pdb.set_trace() # breakpoint()
    for i in range(10):
        y = add(i, 100)
        pdb.set_trace() # breakpoint()

test()
```

- python 3.7버전에서는 `breakpoint()`로 간단하게 디버깅 가능

### 코드 품질 개선을 위한 정적 분석

**소프트웨어 테스팅**

- 기능 테스팅

    - 화이트 박스 테스팅: 개별 기능, 메서드, 클래스, 모듈 테스트 (정적 분석)

    - 블랙 박스 테스팅: 소프트웨어 코드에 가시성이 없는 코드 (셀레니옴 등을 사용하기도 한다)

- 성능 테스팅 (부하 테스팅, 스트레스 테스팅 등)

- 보안 테스팅

- 사용성 테스팅

- 설치 테스팅

- 접근성 테스팅

**정적 분석 static analysis**

- 프로그램을 실행하지 않고 코드를 분석하여 버그, 코드 스멜, 안티 패턴 등을 찾아내는 방법

- Python에서는 `pylint`, `flake8`, `Pyflakes` 등의 도구를 사용하여 정적 분석

- PEP8과 같은 표준

- 코드의 구문 오류, 들여쓰기 등

- 로직이나 나쁜 냄새

    - God Object: 너무 많은 기능이 있는 객체

    - Parameter creep: 너무 많은 파라미터가 있을 경우 함수 호출과 테스트에 부하를 준다

    - Cyclomatic complexity: 과도한 분기와 루프

    - 이외에 코드의 나쁜 냄새는검색

    - 복잡도가 높아질수록 테스트 용이성(오류를 노출하기 쉬운 정도)이 낮아짐

```javascript
pip install pylint
pylint test.py
```

```javascript
def 구구단():
    for i in range(2, 10):
        for j in range(1, 10):
            print('{} * {} = {}'.format(i, j, i*j))

구구단()
```

- pylint를 이용하여 my_module.py 파일을 정적 분석할 수 있다

- R: 모범 사례 Refactor

- C: 표준 위반 Convention

- W: 사소한 문제 경고 Warning

- E: 에러 Error

- F: 치명적 Fatal

For the site tree, see the [root Markdown](https://slashpage.com/yerim-devnote.md).
