카테고리 없음

[SW] 소프트웨어 테스트에 대해서

lucy1215 2023. 3. 27. 15:07
728x90
반응형

소프트웨어 개발은 인간 중심의 활동이며 고도의 지적 활동이다. 이 두 가지 요소 모두 오류가 발생하기 쉬운 활동이다.

소프트웨어에서 오류는 분명 좋지 않다. 소프트웨어 개발 비용과 기간이 늘어날 뿐만 아니라 안전에 중요한 시스템의 경우 결과가 더욱 악화될 수 있기 때문이다.

 

 

소프트웨어 개발 과정에 여러 단계, 즉 요구 사항 명세, 아키텍처, 설계, 구현, 심지어 테스트 중에도 실수가 발생할 수 있다.

개발 과정에 결함이 발견되면 두 가지 실수가 있었던 것이다.

먼저 결함이 유입되었고 둘째는 테스트로 오류가 발견되지 않은 것이다.

 

 

결함의 가능성을 낮추는 방법은 두 가지다.

첫째, 결함이 처음부터 발생하지 않도록 방지하는 방법이 있다.

둘째, 유입된 결함을 식별하고 제거하는 방법이다.

 

 

테스트 작업은 소프트웨어 개발에서 매우 중요하다. 평균적으로 테스트는 프로젝트 시간의 50%와 프로젝트 예산의 50% 이상을 소비한다. Jones에 의하면 버그를 찾아서 고치는 것은 큰 시스템에서 가장 비싼 비용 요소이며 다른 어떤 활동보다 시간이 더 걸린다고 한다.

 

 

테스트 작업은 시험할 소프트웨어에 테스트 케이스를 주어 실행시킨 후 시스템의 동작이 예상한 대로 실행되는지 확인하는 것이다. 오류를 잘 찾아내는 테스트의 성패는 테스트 케이스에 달려 있다. 이 글은 테스트 케이스의 선택 방법, 기준, 효과에 초점을 두고 있다.

 

 

테스트는 두 가지 접근 방식을 기반으로 수행될 수 있다. 소프트웨어의 기능과 구현이다.

실제 구현을 고려하지 않고 기능을 테스트할 때는 블랙박스 테스트라고 한다. 다른 측면은 기능 테스트뿐만 아니라 구현 방식도 분석하는 화이트박스 테스트가 있다.

 

 

완벽한 테스트를 위한 가장 바람직한 방법은 입력 및 출력 값 범위에서 가능한 모든 값을 주고 테스트하는 것이다.

하지만 프로그램의 입출력 값의 범위가 큰 경우 실제 시나리오에서 모든 값을 다 테스트할 수 없다. 따라서 결함을 효과적으로 찾아내기 위한 테스트 케이스의 선택이 중요하다.

 

더보기

검증과 확인

테스트와 관련된 개념으로 검증(verification)확인(validation)을 구별할 필요가 있다. 구별을 하면 찾고자 하는 결함 유형을 명확하게 하는 데 도움이 되기 때문이다. 간단히 말하면, 확인은 유효성 검사라고 할 수 있는 사용자의 예상 기대치에 대한 테스트다. 검증은 명세에 대해 테스트하는 것이다.

 

확인은 "올바른 제품을 만들고 있는가?"라는 질문의 대답이다. 검증은 "제품을 올바르게 구축하고 있는가?"라는 질문의 대답이다.

 

검증의 원어인 verification은 '진실'을 의미하는 라틴어 베리타스에서 온 말이며 확인이 원어인 validation은 '가치'를 의미하는 라인터 valere에서 온 말이다. 따라서 검증은 작업 제품이 요구 명세의 기능, 비기능 요구사항을 얼마나 잘 준수하는지 측정하는 작업이다. 반면에 확인은 작업 제품이 사용자의 기대를 얼마나 잘 충족시키는지를 측정한다.

 

 

 

 

1. 테스트 기초

테스트는 소프트웨어에 결함이나 원치 않는 동작을 찾아내고 소프트웨어가 요구와 제약에 맞는지 검증하는 작업이다.

테스트는 소프트웨어 공학적 원리가 적용되어 정확성을 확증하는 과정이다. 원리라는 측면에서 보면 효율적인 테스트 방법과 과정을 연구하고 개발하고 검증하고 교육하는 것이다.

 

 

테스트란 "시스템이 정해진 요구를 만족하는지, 예상과 실제 결과가 어떤 차이를 보이는지 수동 또는 자동 방법을 동원하여 검사하고 평가하는 일련의 과정"이라고 정의할 수  있다. 주문받은 소프트웨어가 생산된 후에는 발주자의 요구에 맞는다는 사실을 확인하여야 한다.

 

 

요구 사항은 명료하게 기술된 것(explict)이 있고 묵시적인(implicit) 것이 있다. 시스템이 제공해야 할 기능, 발주자가 따라주기 원하는 규정이나 제약 등이 명료하게 기술된 요구이다. 묵시적인 요구는 신뢰성이나 완벽성(robustness) 등이다. 발주자는 개발된 시스템에 버그(bug)가 있어서는 안 되며 비정상적인 조건에서도 제대로 기능을 발휘해 주기를 기대한다.

 

 

앞서 설명한 대로 테스트는 오류를 발견하는 과정이나 기술이다. 따라서 좋은 테스트란 숨어 있는 오류를 잘 발견할 수 있어야 한다. 새로운 오류를 많이 발견하는 테스트는 성공적인 것이다.

 

 

 

 

1.1 버그, 오류, 결함, 고장

버그, 오류, 결함, 고장을 구별하면 테스트 작업에 도움이 된다.

 

 

버그라는 용어는 오랫동안 소프트웨어 엔지니어링 분야의 전문 용어였다. 버그는 문제, 결함 또는 난이도를 나타내는 데 일반적으로 사용되는 용어다. 버그는 그 출처에 대한 비난이나 결함을 피하기 위해 무의식적으로 사용될 수 있으나 정확한 의미는 없다.

 

  • 오류(error) - 개발자가 잘못하여 설계나 코딩에 실수한 것이다. 프로그램의 출력과 예상하는 출력에 차이가 있다면 오류로 간주된다.
  • 결함(defect) - 오류가 있는 경우 결함이 발생한다. 결함은 시스템이 고장을 일으키게 하는 오류의 결과라 할 수 있다.
  • 고장(failure) - 고장은 시스템이 원하는 작업을 실행할 수 없는 상황을 말한다. 시스템에 결함이 있다면 고장이 발생한다.

 

오류(error)는 제품에 결함이 있도록 만든 사람의 실수다. 결함(fault)은 코드 또는 문서에 오류가 있다고 선언된 것이라 할 수 있다. 고장(failure)은 잘못된 결과다. 즉 프로그램의 실제 동작이 예상된 동작과 같지 않을 때 일어나는 현상이다. 고장 현상이 없다고 하더라도 결함이 있을 수 있다. 즉, 프로그램에는 사용자에게 영향을 미치지 않는 결함이 있을 수 있다.

 

 

프로그램의 고장은 오류가 있음을 나타내는 명백한 증상이지만 고장 현상이 일어났다고 해서 반드시 결함으로 발견되지 않을 수 있다. 입력에 오류가 없고 프로그램에 오류가 많지만, 고장을 일으키지 않을 수도 있다.

 

 

결함 유형을 알아두면 프로그램 상태를 추적하고 보고하는 데 유용하다. 설계, 인터페이스, 논리, 구문, 표준, 데이터, 성능 및 문서화 등으로 나눌 수 있는데 각 결함에 대해 정보를 추적하면 소프트웨어 프로세스 개선에 도움이 된다.

 

 

 

 

1.2 테스트 원리

테스트 개념에 대하여 정확이 이해하지 못하면 테스트에 대한 설계가 올바르게 이루어질 수 없다.

다음은 테스트에 관한 오해를 막기 위하여 테스트 작업의 원리와 특징을 설명한다.

 

 

1. 테스트는 오류를 발견하려고 프로그램을 실행시키는 것이다.

테스트의 잘못된 관점은 프로그램이 작동한다는 것은 보여주려는 것이다. 이러한 관점에 의하면 테스트는 간단한 시범 입력을 넣고 실행시키면 되기 때문에 결함을 발견하기 어려울 수 있다. 반면에 오류를 발견하려는 테스트는 어렵고 복잡하지만, 품질이 좋은 소프트웨어를 만들려고 많은 노력을 하게 된다. 오류를 발견하려는 테스트가 더 성공적인 테스트라는 것이다.

 

 

2. 완벽한 테스트는 불가능 하다.

테스트에 문제가 없다고 하여 프로그램에 오류가 없다고 할 수는 없다. 프로그램 테스트는 증명과는 다르다. 소프트웨어를 완벽하게 테스트할 수 있는 테스트 케이스 작성은 이론적으로는 가능한 일이나 시간과 비용이 문제가 된다. 따라서 가장 효율적인 테스트 케이스의 부분 집합을 골라내서 테스트하는 방법이다.

 

 

3. 테스트는 창조적인 일이며 힘든 일이다.

테스트는 결함을 찾기 위하여 단순하고 반복적인 작업을 하므로 어렵고 힘든 일로 여길 수 있다. 하지만 테스트와 유지보수는 창의력을 요구하며 소프트웨어 전문가에게는 흥미의 대상이다. 효율적인 테스트를 하기 위해서는 프로그램이 무엇을 하는지 잘 이해하여야 하며 테스트 기법을 잘 알아야 하고 효율적으로 이런 방법들을 적용할 수 있는 기술이 필요하다.

 

 

4. 테스트는 오류의 유입을 방지할 수 있다.

테스트를 개발 초기 단계부터 계획하여 꾸준히 시행하는 것으로 본다면 단순히 오류를 발견하는 작업만은 아니다.

오류나 문제의 존재를 빨리 알수록 이를 수정하는 데 필요한 비용이 적어지기 때문에 요구 분석, 설계 단계에 오류가 유입되는 것을 적극 막는 활동이 필요하다.

 

 

5. 테스트는 구현과 관계없는 독립된 팀에 의하여 수행되어야 한다.

초보 프로그래머들이 자신의 프로그램을 테스트하는 경우 몇 가지 단순한 데이터로 테스트하고 서둘러 일을 마치는 경우가 많다. 이러한 완성된 프로그램은 통합하는 과정에 오류가 속출하게 된다. 프로그램 당사자는 제3자처럼 객관적인 입장으로 자신이 일한 결과를 대하지 못한다. 따라서 프로그램 작성자 이외의 다른 사람이 테스트하여야 더욱 효과적인 테스트가 가능하다.

 

 

 

 

1.3 테스트 작업 과정

테스트하려는 소프트웨어를 실행시킨 후의 결과가 예상한 결과와 비교하여 차이가 있으면 오류가 있는 것이라고 하였다.

테스트 작업은 다음과 같은 다섯 가지 단계로 준비에 의하여 이루어진다.

 

 

1. 테스트에 의하여 무엇을 점검할 것인지 정한다.

테스트를 설계하기 전에 테스트의 목표가 무엇인가를 결정해야 한다. 기능의 완벽성을 테스트하는 것인가? 아니면 신뢰도를 측정하기 위한 테스트인가?

 

 

2. 테스트 방법을 결정한다.

무엇을 테스트할 것인가를 정했으면 어떻게 테스트할 것인지 방법을 모색한다. 검사, 증명, 블랙박스 테스트, 화이트박스 테스트, 자동화 도구 등 여러 가지 방법이 있다.

 

 

3. 테스트 케이스를 개발한다.

테스트 방법이 결정되면 그 방법에 맞춰 테스트 케이스를 작성한다. 테스트 케이스란 테스트 자료나 실행될 조건을 말한다.

 

 

4. 테스트의 예상되는 올바른 결과를 작성한다.

실제 테스트가 수행되기 전에 올바른 결과가 무엇인지를 알아야 한다. 올바른 결과를 미리 구체적으로 예상하여 작성하지 않고 테스트하면 오류를 찾아내기가 어렵게 된다. 테스트 케이스 실행이 통과되었는지 실패하였는지 판단하기 위한 기준을 테스트 오라클(test oracle)이라고 한다.

 

 

5. 테스트 케이스로 실행시킨다.

테스트를 실행하는 단계이다. 때로는 시스템의 일부 기능만 시험하기 위하여 소프트웨어에 변경을 가하는 경우도 있다. 이를 테스트 하니스(test harness)라고 한다. 완전히 테스트가 끝나면 이를 제거한다.

테스트 작업 과정

 

더보기

테스트 단계

테스트 작업은 여러 단계로 나누어 진행한다. 즉, 단위 테스트(unit testing), 통합 테스트(integration testing), 시스템 테스트(system testing), 인수 테스트(acceptance testing)다.

 

  • 단위 테스트 - 각 모듈을 시험하는 것을 단위 테스트라고 부른다. 단위 테스트는 대부분 모듈을 구현한 프로그래머가 실시한다. 단위 테스트의 주요 목적은 모듈을 정확하게 구현하였는가, 예정한 기능을 제대로 발휘하는가를 점검하는 것이다.
  • 통합 테스트 - 전체 시스템을 이루는 모듈을 모아 통합적으로 시험하는 것을 말한다. 시스템이 요구된 기능을 제대로 수행하는가를 점검하고 모듈 사이의 인터페이스를 시험하는 것이 주목적이다.
  • 시스템 테스트 - 시스템 테스트는 완성된 제품에 대한 시험이다. 시스템 테스트의 목적은 시스템이 사용될 준비가 다 되었다고 드러내 보이는 것이다.
  • 인수 테스트 - 사용될 환경에 설치하여 사용자가 직접 사용함으로써 시험하는 것이다. 시스템의 문서도 이때 점검한다.
  • 리그레션 테스트 - 시스템이 설치된 후 유지보수 단계에서 이루어지는 테스트 작업이다. 리그레션 테스트는 수정이 이루어진 부분과 그에 의한 영향을 시험해보는 작업으로 구성된다.
테스트 단계와 소프트웨어 개발 단계의 관계

 

 

 

 

1.4 테스트 케이스

성공적인 테스트를 위하여 무엇보다 중요한 것은 결함의 존재를 잘 드러내는 좋은 테스트 케이스를 찾아내는 것이다. 그 이유는 프로그램에 결함이 있더라도 테스트 입력에 따라서 여전히 정상적인 결과를 낼 수 있기 때문이다. 즉 프로그램에 있는 결함을 검사할 수 있는 입력이 있어야 테스트를 위하여 실행할 수 있다.

 

 

테스트 케이스는 시험 대상 단위별로 묶어 미리 준비한다. 테스트 케이스에는 일반적으로 시험조건, 테스트 데이터, 예상 결과를 포함시켜야 한다. 테이블 형식으로 테스트 케이스를 작성하는데 먼저 시험 대상을 적는다. 시험 대상이란 기능시험의 경우 요구 고유번호, 단위 시험이라면 모듈 번호 등을 표시한다. 다음은 시험조건 즉, 테스트를 하기 위하여 준비할 조건을 기술한다. 또한, 테스트를 실행할 때 입력할 데이터를 적고 테스트 후 통과 여부를 판단할 기준인 예상 결과를 기입한다.

 

 

경우에 따라 테스트 결과를 기록하기 위하여 몇 개의 칸이 추가될 수 있다. 테스트 케이스 명세서는 테스트 결과의 기록을 위하여 사용되기도 한다. 그 결과는 통과 또는 실패로 기록되며 여러 번의 시험을 반복하고 그 기록을 다른 칸에 남기는 경우도 있다.

 

 

테스트 케이스 작성은 테스트 작업에서 중요한 과정이다. 테스트 방법이 제안하는 조건을 만족하는 테스트 케이스를 신중히 선택하는 것이 관건이다. 테스트 케이스를 어떤 근거로 선택할 것인가? 이것이 테스트 작업의 중요한 관심사이며 무엇을 근거로 하느냐에 따라 다른 방법이 된다.

반응형