이 페이지의 목차
시스템 테스트와 고쳐 내기
코드 예제: Python · C · 예상 50분
학습 목표
- 완성된 프로그램을 대상으로 시스템 테스트를 수행한다.
- 테스트 결과를 반영해 프로그램을 고치고 결과를 공유한다.
관련 성취기준
- 프그03-04
구현된 프로그램을 대상으로 단위 테스트, 통합 테스트, 시스템 테스트를 할 수 있다.
생각 열기 — 만든 사람은 잘못 쓰지 않는다
7차시의 단위 테스트와 통합 테스트를 모두 통과했다. 모둠에서는 다 끝났다고 생각했다. 옆 모둠에게 써 보라고 넘겼더니 5분 만에 이런 것들이 나왔다.
- 점수를 넣는 칸에 그냥 엔터를 눌렀더니 프로그램이 멈췄다.
- 점수를 300개 넘게 넣었더니 뒤쪽이 잘렸다.
- 결과가 나온 뒤 한 명을 더 넣고 싶었는데 방법이 없어 처음부터 다시 해야 했다.
시스템 테스트 — 전체를, 실제 조건에서
시스템 테스트(system test) — 완성한 프로그램 전체를 실제 사용 조건에서 요구 사항과 대조하는 시험는 앞의 두 테스트와 보는 것이 다르다.
| 단위 테스트 | 통합 테스트 | 시스템 테스트 | |
|---|---|---|---|
| 보는 범위 | 부품 하나 | 이어 붙인 부분 | 완성한 프로그램 전체 |
| 무엇과 대조하는가 | 그 부품의 기대 결과 | 주고받는 값 | 요구 사항 명세서 |
| 누가 하는가 | 만든 사람 | 만든 사람 | 만들지 않은 사람 |
| 환경 | 아무 데서나 | 아무 데서나 | 실제로 쓸 컴퓨터에서 |
| 빠뜨리기 쉬운 것 | 경계값 | 자료형·순서 | 비기능 요구 · 잘못 쓰는 경우 |
시스템 테스트에서 대조 대상이 요구 사항 명세서라는 점이 중요하다. 2차시에 적은 F1F4와 N1N4를 하나씩 짚어 가며 지켜졌는지 확인한다. 명세서를 대충 적었다면 여기서 확인할 것이 없어진다.
비기능 요구를 확인한다
기능 요구는 통합 테스트에서 대부분 걸러진다. 시스템 테스트에서 새로 드러나는 것은 비기능 요구다. 만드는 동안에는 아무 문제도 일으키지 않던 것들이다.
| 요구 | 어떻게 확인하는가 |
|---|---|
| N1 설치 없이 전산실에서 실행된다 | 전산실 컴퓨터에서 직접 실행해 본다. 내 노트북에서 되는 것은 확인이 아니다 |
| N2 300개를 3초 안에 처리한다 | 300개를 실제로 만들어 넣고 시간을 잰다. 5개로 시험한 것은 근거가 되지 않는다 |
| N3 실제 이름·학번을 저장하지 않는다 | 코드와 자료 파일을 훑어 실제 개인정보가 남아 있는지 본다 |
| N4 글자가 들어와도 멈추지 않는다 | 점수 자리에 “칠십오”를 넣어 본다 |
결함을 기록하는 법
찾은 문제를 말로 전하면 사라진다. 결함 보고서로 적는다. 좋은 보고서에는 네 가지가 있다.
- ① 재현
어떻게 하면 다시 생기는가
"그냥 이상하다"가 아니라 "점수 칸에서 아무것도 안 넣고 엔터를 눌렀다"처럼 순서대로 적는다.
- ② 기대
무엇이 나와야 했는가
명세서의 몇 번 요구를 어겼는지 함께 적으면 고치는 사람이 판단하기 쉽다.
- ③ 실제
무엇이 나왔는가
오류 메시지가 있으면 그대로 옮겨 적는다. 요약하지 않는다.
- ④ 환경
어디서 생겼는가
어느 컴퓨터, 어느 실행 방법인지. 특정 환경에서만 나는 문제가 있다.
결함 보고서 — 예시
| 항목 | 내용 |
|---|---|
| 번호 | D-01 |
| 재현 방법 | ① 프로그램을 실행한다 ② 점수 입력 칸에서 아무것도 입력하지 않고 엔터를 누른다 |
| 기대 결과 | 잘못된 입력임을 알리고 다시 입력받는다 (N4) |
| 실제 결과 | 프로그램이 멈추고 오류 메시지가 나온다 |
| 환경 | 전산실 12번 컴퓨터, 웹 실행기 |
| 심각도 | 높음 — 프로그램을 쓸 수 없게 된다 |
고치고, 되던 것을 다시 본다
결함을 고칠 때는 순서가 있다.
- 재현한다. 보고서대로 따라 해 문제를 눈으로 확인한다. 재현되지 않으면 조건이 덜 적힌 것이다.
- 테스트 사례를 먼저 만든다. 그 결함을 잡아내는 사례를 7차시의 테스트 목록에 추가한다. 지금은 실패한다.
- 고친다. 새 사례가 통과할 때까지.
- 전부 다시 돌린다. 되던 사례가 깨지지 않았는지 확인한다 — 회귀 테스트.
2번을 건너뛰면 같은 결함이 나중에 되살아나도 아무도 모른다. 고칠 때마다 테스트 사례가 하나씩 늘어나는 것이 정상이다.
고치기 전과 고친 뒤
생각 열기에서 나온 잘못, 0 < 점수 로 적어 0점이 걸러지던 문제를 고쳐 보자.
def is_valid_before(score):
return 0 < score <= 100
def is_valid_after(score):
return 0 <= score <= 100
for label, f in [("고치기 전", is_valid_before), ("고친 뒤", is_valid_after)]:
print(f"{label}: 0점 -> {f(0)}, 1점 -> {f(1)}, 100점 -> {f(100)}")고치기 전: 0점 -> False, 1점 -> True, 100점 -> True 고친 뒤: 0점 -> True, 1점 -> True, 100점 -> True
#include <stdio.h>
int is_valid_before(int score) { return score > 0 && score <= 100; }
int is_valid_after(int score) { return score >= 0 && score <= 100; }
int main(void)
{
printf("고치기 전: 0점 -> %d, 1점 -> %d, 100점 -> %d\n",
is_valid_before(0), is_valid_before(1), is_valid_before(100));
printf("고친 뒤: 0점 -> %d, 1점 -> %d, 100점 -> %d\n",
is_valid_after(0), is_valid_after(1), is_valid_after(100));
return 0;
}고치기 전: 0점 -> 0, 1점 -> 1, 100점 -> 1 고친 뒤: 0점 -> 1, 1점 -> 1, 100점 -> 1
바뀐 것은 부등호 하나(> → >=)뿐이다. 1점과 100점은 고치기 전과 후가 같아서, 그 값들만 넣어 봤다면 잘못을 끝내 발견하지 못했을 것이다. 경계값을 넣어야 하는 이유가 이 한 줄에 다 들어 있다.
결과를 공유한다
프로젝트의 마지막은 만든 것을 남에게 보여 주는 일이다. 발표에서 다룰 것은 완성한 기능만이 아니다.
| 항목 | 무엇을 말하는가 |
|---|---|
| 무엇을 왜 만들었나 | 1차시의 사용자와 불편. 화면 시연보다 먼저 말한다 |
| 어떻게 나눴나 | 3차시 설계서의 부품 구조를 한 장으로 |
| 무엇을 못 했나 | "있으면 좋음"에서 빼기로 한 것과 그 이유 |
| 어떤 결함을 찾고 고쳤나 | 결함 보고서 한두 개. 고친 과정이 가장 배울 것이 많다 |
| 다시 만든다면 | 설계에서 무엇을 다르게 하겠는가 |
활동
다른 모둠 프로그램을 테스트해 주고 결함 보고서 쓰기
약 45분1단계 — 프로그램과 명세서를 맞바꾼다 (5분)
옆 모둠과 프로그램과 2차시 명세서를 함께 바꾼다. 명세서 없이는 무엇이 결함인지 판정할 수 없다.
2단계 — 명세서를 짚어 가며 확인한다 (15분)
받은 명세서의 요구를 하나씩 확인한다. 만든 사람에게 사용법을 묻지 않는다. 물어야만 쓸 수 있다면 그것 자체가 결함이다.
| 요구 번호 | 지켜졌는가 | 어긋났다면 무엇이 |
|---|---|---|
| F1 | ||
| F2 | ||
| N1 | ||
| N2 |
3단계 — 일부러 잘못 써 본다 (10분)
만든 사람이 하지 않을 행동을 한다.
- 아무것도 입력하지 않고 엔터를 누른다
- 숫자 자리에 글자를 넣는다
- 아주 큰 수, 음수, 0을 넣는다
- 명세서에 적힌 최대 개수보다 많이 넣는다
- 결과가 나온 뒤 하나 더 넣어 본다
4단계 — 결함 보고서를 쓴다 (10분)
찾은 것을 보고서로 적어 넘긴다. 네 가지가 모두 있어야 한다.
| 번호 | 재현 방법 | 기대 결과 (몇 번 요구) | 실제 결과 | 환경 | 심각도 |
|---|---|---|---|---|---|
| D-01 |
5단계 — 받은 보고서로 고친다 (5분 + 이후)
받은 보고서 중 하나를 골라 순서대로 처리한다.
- 재현해 본다
- 그 결함을 잡는 테스트 사례를 7차시 목록에 추가한다 (지금은 실패한다)
- 고친다
- 테스트를 전부 다시 돌려 되던 것이 깨지지 않았는지 확인한다
시간이 모자라면 1·2단계까지만 해도 된다. 테스트 사례를 추가하는 2단계는 건너뛰지 않는다.
개념 확인 문제
보기를 누르면 바로 채점된다. 틀려도 해설을 읽으면 된다.
시스템 테스트가 단위·통합 테스트와 가장 크게 다른 점은?프그03-04
시스템 테스트를 만든 사람이 아닌 다른 사람이 하는 것이 좋은 이유는?프그03-04
'300개를 3초 안에 처리한다'는 비기능 요구를 확인하는 방법으로 알맞은 것은?프그03-04
결함 보고서에서 가장 자주 빠지고, 빠지면 고칠 수 없게 되는 항목은?프그03-04
결함을 고치기 전에 '그 결함을 잡아내는 테스트 사례를 먼저 추가한다'는 순서를 지키는 이유는?프그03-04
0점이 걸러지던 잘못을 1점과 100점만 넣어서는 발견할 수 없었던 이유는?프그03-04
더 알아보기
심화심각도와 우선순위는 다르다
결함 보고서에는 대개 두 가지 등급이 함께 붙는다. 심각도는 그 결함이 얼마나 큰 피해를 주는가이고, 우선순위는 언제 고칠 것인가다. 둘은 다를 수 있다. 아주 드물게만 일어나지만 일어나면 자료가 사라지는 결함은 심각도가 높고, 자주 보이지만 글자 색이 어긋나는 정도라면 심각도는 낮아도 우선순위가 높을 수 있다. 심각도는 사실이고 우선순위는 판단이라고 보면 구분이 쉽다.
실무고친 뒤가 더 위험한 순간이다
결함을 고치는 과정에서 새 결함이 생기는 일이 흔하다. 급하게 고칠수록, 그리고 코드를 잘 모르는 사람이 고칠수록 그렇다. 그래서 고친 뒤에 반드시 전체 테스트를 다시 돌린다. “한 줄만 고쳤으니 괜찮겠지”가 가장 위험한 생각이다. 이 차시의 예제에서 바뀐 것도 부등호 한 글자였지만, 그 한 글자가 프로그램의 판정을 바꿨다.
진로테스트만 하는 직무가 따로 있다
소프트웨어를 만드는 회사에는 테스트를 전문으로 하는 사람이 따로 있다. 요구 사항을 읽고 테스트 사례를 설계하고, 자동으로 돌아가는 테스트를 만들고, 결함을 기록해 넘긴다. 코드를 직접 쓰지 않는 자리도 있고, 테스트를 자동화하는 코드를 쓰는 자리도 있다. **“부수는 일”이 아니라 “무엇을 확인해야 하는지 설계하는 일”**이라는 점에서 만드는 일만큼 판단이 많이 든다. 이번 활동에서 다른 모둠의 프로그램을 깨뜨려 본 경험이 그 일의 맛보기다.
이어지는 학습
이 차시를 이해하려면 다음을 먼저 알아야 한다.
- 7차시의 단위·통합 테스트 결과 — 프로그래밍 프그03-04
교과서에서 찾기
| 교과서 | 해당 위치 | 쪽수 |
|---|---|---|
| 성림출판(Python) | 프로그램 설계와 구현 › 01 프로그램 개발 과정 > 4 프로그램 테스트 | 219쪽 |
| 씨마스커뮤니케이션(Python) | 프로그램 설계와 구현 › 2 프로그래밍 실제 | 222쪽 |
| 삼양미디어(Python) | 프로그램의 설계와 구현 › 02 프로그램 개발 프로젝트 | 190쪽 |
| 삼양미디어(C) | 프로그램의 설계와 구현 › 02 프로그램 개발 프로젝트 | 197쪽 |
| 씨마스(C) | 프로그래밍 설계와 구현 › 3 프로그래밍의 실제 Ⅱ | 236쪽 |
| 웅보출판사(C) | 프로그램 설계와 구현 › Chapter 04 프로그램 테스트 | 227쪽 |