# 프로젝트 테스터

여러분이 작성한 코드가 제대로 동작하는지 확인하기 위한 테스트들이 있습니다. 궁극적으로 모든 프로젝트에는 일련의 테스트가 제공될 것입니다. 현재 사용 가능한 테스팅 프레임워크는 [여기](https://github.com/chu-aie/os-2024/tree/main/src/ostep-projects/tester)에서 찾을 수 있습니다. 각 프로젝트 디렉토리에 있는 특정 테스팅 스크립트를 사용하여 여러분의 코드를 대상으로 테스트를 실행할 수 있습니다.

예를 들어, 초기 유틸리티 프로젝트에서 여러분이 작성한 비교적 간단한 `hcat` 프로그램은 `test-hcat.sh` 스크립트를 실행하여 테스트할 수 있습니다. 이는 다음과 같은 명령으로 수행할 수 있습니다:

```bash
git clone https://github.com/chu-aie/os-2024
cd src/ostep-projects/initial-utilities/hcat
emacs -nw hcat.c
gcc -o hcat hcat.c -Wall
./test-hcat.sh
```

```
test 1: passed
test 2: passed
test 3: passed
test 4: passed
test 5: passed
test 6: passed
test 7: passed
```

물론 이 시퀀스는 (a) 여러분이 `emacs`를 사용하고 (그래야 합니다!), (b) 코드가 한 번에 작성되며 (인상적입니다!), (c) 완벽하게 동작한다는 것을 전제로 합니다 (잘 하셨습니다!). 간단한 과제의 경우에도 컴파일/실행/디버그 사이클이 몇 번의 반복이 필요할 수 있습니다.

## 사용법

`run-tests.sh` 스크립트는 다양한 테스터에 의해 호출되어 테스팅 작업을 수행합니다. 각 테스트는 실제로 매우 간단합니다: 프로그램 명세에 따라 표준 출력과 표준 오류를 비교하는 것입니다.

- 표준 출력(standard output): 프로그램이 정상적으로 출력하는 텍스트 데이터로, 일반적으로 콘솔 화면에 표시됩니다.
- 표준 오류(standard error): 프로그램이 오류 메시지를 출력하기 위해 사용하는 별도의 출력 채널로, 일반적으로 콘솔 화면에 표시됩니다.

주어진 프로그램 명세 디렉토리에는 `tests/` 디렉토리가 있는데, 여기에는 각 테스트 `n`에 대해 예상되는 반환 코드, 표준 출력, 표준 오류가 `n.rc`, `n.out`, `n.err` 파일에 각각 저장되어 있습니다. 테스팅 프레임워크는 `1`부터 시작하여 더 이상 테스트를 찾을 수 없거나 실패가 발생할 때까지 테스트 번호를 계속 증가시킵니다. 따라서 새로운 테스트를 추가하는 것은 쉽습니다. 관련 파일을 사용 가능한 가장 낮은 번호의 테스트 디렉토리에 추가하기만 하면 됩니다.

테스트 번호 `n`을 설명하는 데 필요한 파일은 다음과 같습니다:

- `n.rc`: 프로그램이 반환해야 하는 반환 코드 (보통 0 또는 1)
- `n.out`: 테스트에서 기대되는 표준 출력
- `n.err`: 테스트에서 기대되는 표준 오류
- `n.run`: 테스트를 실행하는 방법 (필요한 인수 등)
- `n.desc`: 테스트에 대한 짧은 텍스트 설명
- `n.pre` (선택 사항): 테스트 전에 실행할 코드, 무언가를 설정하기 위함
- `n.post` (선택 사항): 테스트 후에 실행할 코드, 무언가를 정리하기 위함

또한 테스팅이 시작될 때 한 번 실행되는 `pre`라는 단일 파일이 있습니다. 이는 종종 코드 베이스를 보다 복잡하게 빌드하는 데 사용됩니다. 반복적인 시간 낭비 활동을 방지하려면 아래에 설명된 대로 `-s` 플래그를 사용하여 이를 억제하세요.

대부분의 경우 래퍼 스크립트가 `run-tests.sh`를 호출하여 필요한 작업을 수행하는 데 사용됩니다.

`run-tests.sh`의 옵션은 다음과 같습니다:

- `-h` (도움말 메시지)
- `-v` (verbose: 각 테스트가 수행하는 작업을 출력)
- `-t n` (테스트 `n`만 실행)
- `-c` (테스트가 실패한 후에도 계속 진행)
- `-d` (`tests/` 디렉토리가 아닌 이 디렉토리에서 테스트 실행)
- `-s` (`pre` 파일에 있는 일회성 명령 세트 실행 억제)

- 래퍼 스크립트(wrapper script): 다른 프로그램이나 스크립트를 호출하는 스크립트로, 호출되는 프로그램의 입력과 출력을 조작하거나 추가적인 처리를 수행합니다.

여기서 설명한 테스팅 프레임워크는 여러분의 코드를 체계적으로 테스트하고 검증하는 데 도움이 될 것입니다. 각 테스트는 입력, 예상 출력, 예상 반환 코드 등을 명확하게 정의하므로 프로그램이 명세대로 동작하는지 쉽게 확인할 수 있습니다.

테스트를 추가하거나 수정하는 것도 간단합니다. `tests/` 디렉토리에 적절한 파일을 추가하거나 변경하기만 하면 됩니다. 이를 통해 프로그램의 다양한 동작을 검증하고 edge case를 처리할 수 있습니다.

`run-tests.sh` 스크립트는 테스팅 프로세스를 자동화하고 사용자 정의할 수 있는 다양한 옵션을 제공합니다. verbose 모드로 실행하여 각 테스트의 진행 상황을 확인하거나, 특정 테스트만 실행하거나, 테스트 실패 후에도 계속 진행하도록 설정할 수 있습니다.

또한 `pre`와 `post` 파일을 사용하여 테스트 전후에 필요한 설정 및 정리 작업을 수행할 수 있습니다. 이는 테스트 환경을 일관되게 유지하고 테스트 간 간섭을 최소화하는 데 도움이 됩니다.

프로젝트를 진행하면서 제공된 테스트를 활용하고 필요에 따라 새로운 테스트를 추가하세요. 체계적인 테스트는 코드의 정확성과 안정성을 보장하고 디버깅 시간을 단축하는 데 큰 도움이 될 것입니다.

테스트 주도 개발(Test-Driven Development, TDD)은 테스트를 먼저 작성하고 그에 맞춰 코드를 개발하는 방법론입니다. 이 접근법을 따르면 명세에 집중하게 되고, 모듈화와 유지보수성이 향상됩니다. 제공된 테스팅 프레임워크를 활용하여 TDD를 연습해 보는 것도 좋은 경험이 될 것입니다.

코드를 작성할 때는 가독성과 효율성을 함께 고려해야 합니다. 적절한 변수명과 함수명을 사용하고, 주석을 충실히 달며, 코드를 논리적인 블록으로 구성하세요. 또한 불필요한 복잡성을 피하고 간결하고 이해하기 쉬운 코드를 작성하도록 노력하세요.

디버깅은 프로그래밍의 필수 불가결한 부분입니다. 테스트가 실패할 경우 gdb와 같은 디버거를 사용하여 문제의 원인을 찾아내세요. 코드를 단계별로 실행하고 변수의 값을 확인하며 로직의 흐름을 추적하세요. 디버깅 기술을 연마하면 문제 해결 능력이 크게 향상될 것입니다.

마지막으로 동료들과 협업하고 코드 리뷰를 활용하세요. 다른 사람의 시각에서 코드를 바라보면 개선점과 버그를 발견하기 쉽습니다. 서로의 코드를 리뷰하고 건설적인 피드백을 제공하세요. 협업을 통해 더 나은 코드와 문제 해결 방법을 배울 수 있습니다.

이 프로젝트 테스터를 활용하여 체계적이고 효과적으로 코드를 테스트하고 개선해 나가시기 바랍니다. 좋은 테스트와 꾸준한 연습을 통해 여러분의 프로그래밍 실력은 한층 더 성장할 것입니다. 행운을 빕니다!
