소프트웨어 개발 - 테스트

Bam·2023년 10월 4일
0

소프트웨어공학

목록 보기
8/10
post-thumbnail

테스트

소프트웨어 개발 과정의 구현 단계에서 발생한 사소한 오류는 크고 작은 문제들을 발생시킵니다. 그리고 이러한 문제는 품질 저하로 인한 신뢰성을 떨어뜨리게 됩니다.

이러한 오류들은 테스트라는 과정을 통해서 줄일 수 있습니다.

테스트는 개발 과정에서 생성되는 문서, 프로그램의 오류를 검출해내는 작업이라고 정의할 수 있습니다. 테스트는 오류를 검출할 뿐이지 프로그램에 완전히 오류가 없다고 확신할 수는 없습니다. 즉, 테스트의 목적은 소프트웨어가 정상적으로 실행될 수 있도록 오류를 찾아서 제거한다고 할 수 있습니다. 이 일은 소프트웨어의 신뢰성을 높여주므로, 테스트는 결국 소프트웨어의 신뢰성을 높이기 위한 작업이라고 할 수 있습니다.

테스트는 상당히 중요하고 필요한 작업이지만 다음과 같은 어려움들이 있습니다.

  • 테스트 케이스가 적으면 효과에 한계가 있다.
  • 완벽한 테스트 케이스를 도출하기 어렵다.
  • 테스트를 위한 실제 사용 환경 구축이 어렵다.
  • 작은 결함의 발견이 어렵다.
  • 테스트의 중요성에 대한 인식이 부족하다.

테스트특징은 다음과 같습니다.

  • 고객의 요구사항을 충족해야 한다.
  • 테스트 단계에서만 수행되는 것이 아닌 개발 사이클 전체에서 수행되어야 한다.
  • 파레토 원리를 적용할 수 있다.
  • 모듈 단위를 점점 확대해 나가며 진행한다.
  • 완벽한 테스트는 불가능하다.
  • 개발자와 다른 별도의 팀에서 수행한다.
  • 살충제 패러독스 문제 해결을 위해 테스트 케이스의 업데이트가 필요하다.

파레토 원리 pareto principle
파레토 원리는 전체의 20%의 자원이 80%의 성과를 낸다는 원리입니다.
이를 소프트웨어 테스트에 적용하면, 20%의 모듈에서 80%의 에러가 나오므로 핵심적인 20%를 집중 테스트하여 80%의 에러를 검출한다는 의미가 됩니다.

살충제 패러독스 presticide paradox
살충제 패러독스는 같은 살충제를 동일한 종의 벌레에게 계속 뿌리면 내성이 생겨 갈수록 해당 살충제의 효과가 사라지는 효과를 의미합니다.
이처럼 테스트 케이스도 동일한 케이스만 계속 사용하면 오류를 더 이상 검출하지 못하기에 테스트 케이스도 지속적인 업데이트가 필요합니다.

테스트에서 발견되는 결함들에 대한 용어는 다음과 같습니다.

  • 오류
    오류(error)는 개발자에 의해 생기는 실수 등으로 결함의 원인이 됩니다.
  • 결함
    결함(defuect, bug, fault)는 오류로 인해서 프로그램이 완전하지 않은 것으로 고장의 원인이 됩니다.
  • 고장, 실패, 문제, 장애
    고장, 실패, 문제, 장애는 시스템이 요구사항대로 작동하지 않는 것을 의미합니다.

테스트 절차

테스트는 다음과 같은 절차로 수행됩니다.

1. 테스트 계획

테스트 계획 단계에서는 테스트 목표를 정의하고 대상과 범위를 결정하며, 계획서를 작성하고 검토합니다.

2. 테스트 케이스 설계

테스트 케이스 설계 단계에서는 테스트 설계 기법을 정의하고, 결정된 기법에 다른 케이스를 도출합니다.

3. 테스트 실행 및 측정

테스트 실행 및 측정 단계에서는 테스트 환경을 구축하고 도출된 테스트 케이스를 이용해서 테스트를 실시합니다. 그리고 이 결과를 문서화합니다.

4. 테스트 결과 분석

테스트 결과 분석 단계에서는 계획서와 비교해서 결과를 비교/분석합니다. 그리고 이에 대한 보고서를 작성합니다.

5. 오류 추적 및 수정

오류 추적 및 수정 단계에서는 테스트 결과 어디에서 어떤 오류가 발생했는지 확인하고 수정합니다.


테스트 분류

테스트는 수많은 종류의 테스트가 있습니다. 따라서 이들을 몇 가지 기준으로 분류해서 그룹화하고 있습니다.

테스트 분류는 다음과 같습니다.

  • 시각에 따른 테스트
  • 사용 목적에 따른 테스트
  • 프로그램 실행 여부에 따른 테스트
  • 소프트웨어 개발 단계에 따른 테스트

시각에 따른 테스트

시각은 개발자의 시각과 사용자의 시각으로 나뉩니다. 그래서 이 테스트는 개발자의 시각과 사용자의 시각에서 테스트를 수행하는데 이를 각각 확인(verification)과 검증(validation) 테스트(V & V)라고 부르게 됩니다.

확인 테스트

확인 테스트는 각 단계에서 개발자의 시각으로 설계서대로 구현되었는지를 테스트합니다. 다시말해 이전 단계 산출물대로 생산되었는지를 확인합니다.

이 과정에서 이전 단계 산출물이 잘못되었다면, 확인 테스트를 통과하더라도 사용자가 원하는 소프트웨어를 개발할 수 는 없습니다. 따라서 확인 테스트 하나만으로는 요구사항을 완벽하게 반영할 수 없습니다.

검증 테스트

검증 테스트는 사용자가 원하는 것을 만들었는지 또는 요구사항을 전부 충족했는지를 사용자의 시각에서 테스트합니다.

확인 테스트와 검증 테스트를 함께 사용해서 강력한 테스트가 되며 보통 묶인 개념(V & V)로 함께 사용됩니다.

사용 목적에 따른 테스트

성능 테스트

성능 테스트는 효율성을 진단하는 테스트입니다. 요구사항에서 성능에 대한 부분을 얼마나 충족하는 지를 테스트합니다. (실행 시간, 응답 시간, 처리 능력, 자원 사용량)

스트레스 테스트

스트레스 테스트는 일반적인 상황보다 더 많은 부하를 주어 시스템이 어떻게 반응하는지 확인하고 이때 발생하는 오류를 확인합니다.

보안 테스트

보안 테스트는 소프트웨어의 보안 시스템이 외부의 침입을 얼마나 잘 견디는지 테스트합니다.

안정성 테스트

안정성 테스트는 시스템이 얼마나 오래 안정적으로 수행되는지 알아보기 위한 테스트입니다. 테스트에서는 실제 사용 환경처럼 오랜시간 투자할 수 없기 때문에 과부하를 몇 일간 주면서 시스템의 상황을 관찰하게 됩니다.

복원 가능성 테스트

복원 가능성 테스트는 문제가 발생하여 시스템이 고장났을 때 얼마나 잘 복구가 되는지를 확인하는 테스트입니다.

프로그램 실행 여부에 따른 테스트

프로그램 실행 여부에 따른 테스트는 프로그램을 실행하거나 하지 않고 수행하는 테스트입니다. 방식에 따라 프로그램을 실행하지 않고 코드 검토를 수행하면 정적 테스트, 프로그램을 실행하면서 찾는 동적 테스트로 나뉩니다.

정적 테스트

정적 테스트는 프로그램을 실행하지 않고, 개발 과정에서 생성된 여러 산출물(문서, 코드 등)을 검토하여 결함(defect)를 찾는 테스트 방법입니다.

이는 다시 상황에 따라 공식 검토비공식 검토로 나눠집니다. 나눠지기는 하지만 상황에 따라 공식 검토였던 것이 비공식이 될 수도 있는 등 유연하게 나눠집니다.

  • 공식 검토
    공식 검토는 팀 동료와 기술 전문가들이 수행하는 품질 제어 활동입니다. 결함 파악을 위해 정의된 절차에 따라 계획되고 통제됩니다.

  • 비공식 검토
    비공식 검토는 개발 과정에서 생성된 문서, 프로그램 코드 등을 팀 동료와 함께 검사하는 것입니다.

정적 테스트에는 다음과 같은 종류가 있습니다.

개별 검토

개별 검토는 체크리스트를 통해 본인이 개발한 코드와 산출물을 검토하는 것입니다. 본인이 직접 수행하기 때문에 객관성이 떨어집니다.

동료 검토

동료 검토는 동료에게 개발한 코드나 산출물에 대해 검토를 의뢰해 결함을 찾습니다.

검토 회의

검토 회의는 개발자가 소집한 전문가들에 의해 개발자의 작업을 검토합니다.

소프트웨어 검사

소프트웨어 검사는 개발 전 과정에 거쳐 산출된 각 단계의 모든 산출물들을 포함해 분석하고 품질을 평가합니다.

동적 테스트

동적 테스트는 테스트 데이터를 가지고 프로그램을 실행해가며 오류를 찾는 테스트입니다. 이는 다시 명세 기반 테스트구현 기반 테스트로 나뉘어집니다.

명세 기반 테스트

명세 기반 테스트(블랙박스 테스트)는 코드를 직접 열어보기 보다는 입력 값에 대한 예상 출력 값을 정하고 이에 대한 결과를 확인함으로서 오류를 찾습니다. 즉, 사용자가 원하는 기능을 수행하는가를 테스트합니다.

명세 기반 테스트의 방식에는 신택스 기법, 동등 분할 기법, 경계 값 분석 기법, 원인-결과 그래프 기법, 의사결정 테이블 기법이 있습니다.

  • 신택스 기법
    신택스 기법은 문법에 기반을 둔 테스트 입니다. 특정 문법을 정하고 성공과 실패할 것으로 예상되는 입력 값에 따른 예상 결과가 제대로 나오는 지를 테스트합니다.

  • 동등 분할 기법
    동등 분할 기법은 특정 점수 구간이 정해져있는 경우, 각 영역에 해당하는 입력 값을 넣고 예상되는 출력 값이 나오는 지를 테스트합니다.

  • 경계 값 분석 기법
    이하, 미만, 이상, 초과는 프로그램에서 명확하게 나타내기 어렵습니다. 따라서 경계 값 분석 기법은 이때 발생하는 오류를 방지하고자 경계에 있는 값을 테스트 데이터로 이용해서 테스트하는 방법입니다. 경계 값, 경계 이전 값, 경계 이후 값 세 가지를 가지고 테스트합니다.

  • 원인-결과 그래프 기법
    원인-결과 그래프 기법은 원인에 해당하는 입력 조건과 그 원인(입력 값)에서 나오는 결과(출력 값)를 가지고 그리는 그래프를 사용해 테스트 케이스를 만드는 방법입니다.

구현 기반 테스트

구현 기반 테스트(화이트박스 테스트, 코드 기반 테스트)는 코드 내부의 변수나 서브루틴, 모듈 등의 오류를 찾기 위해 내부 구조를 테스트 설계의 기반으로 이용합니다. 입력 데이터를 가지고 실행 상태를 추적하며 오류를 찾습니다.

구현 기반 테스트 방식으로는 문장 검증 기준, 분기 검증 기준, 조건 검증 기준, 분기/조건 검증 기준, 다중 조건 검증 기준, 기본 경로 테스트가 있습니다.

  • 문장 검증 기준
    문장 검증 기준은 코드 내의 모든 문장이 최소 한 번 실행될 수 있는 테스트 케이스를 작성합니다.

  • 분기 검증 기준
    분기 검증 기준은 코드에 존재하는 조건문에 대해 true와 false가 되는 경우를 최소 한 번 실행될 수 있는 테스트 케이스를 작성합니다.

  • 조건 검증 기준
    조건 검증 기준은 전체 조건식은 무시하고, 개별 조건문에 대해서 true와 false가 되는 경우를 최소 한 번 실행될 수 있는 테스트 케이스를 작성합니다. 분기 조건 검증에서 발견하지 못하는 오류를 발견할 수 있습니다.

  • 분기/조건 검증 기준
    분기/조건 검증 기준은 개별 조건식을 모두 만족하면서 전체 조건식도 만족하는 테스트 케이스를 작성하는 것 입니다.
    이 방식은 마스크(mask) 문제가 발생할 수 있습니다.

마스크 문제
조건식 연결이 and(&&)일 때, 왼쪽 식이 false이면 오른쪽 식을 검사하지 않고 넘어갑니다. 그리고 or(||)일 경우에는 왼쪽이 true이면 오른쪽 식을 검사하지 않고 넘어갑니다.

이처럼 개별 조건식이 다른 조건식의 결과와 상관없이 결과가 결정되는 것을 마스크 문제라고 합니다.

  • 다중 조건 검증 기준
    다중 조건 검증 기준은 분기/조건 검증 기준에서 발생하는 마스크 문제를 해결하기 위해 등장한 검증 기준입니다.
    and의 경우 한 쪽이 false일 때, 검사하지 않게 되는 나머지 식이 true인 경우와 false인 경우를 각각 추가해 이를 만족시키는 테스트 케이스를 작성합니다. or의 경우도 마찬가지로 한쪽이 true일 때, 나머지 식이 true인 경우와 false인 경우를 각각 추가해 이를 만족시키는 테스트 케이스를 작성합니다.

  • 기본 경로 테스트
    기본 경로 테스트는 코드의 독립적인 경로가 최소한 한 번 실해외는 테스트 케이스를 찾아서 수행하는 방식입니다. 즉, 코드의 독립적인 경로를 모두 수행해보는 테스트입니다. 흐름 그래프순환 복잡도(CC, Cyclomatic Complexity)를 사용합니다.


    흐름 복잡도는 다음과 같이 노드와 화살표, 분기를 이용해서 표현합니다.

    순환 복잡도(CC)는 흐름 복잡도를 기반으로 계산합니다.

    • CC = R의 수
    • CC = E - N + 2
    • CC = P + 1
      R: 화살표와 노드로 둘러쌓인 구역 (위 그림에서는 3)
      E: 화살표 수
      N: 노드 수
      P: 분기 노드 수

이미지 출처


소프트웨어 개발 단계에 따른 테스트

소프트웨어 개발 단계에 따른 테스트는 개발 단계의 순서와 짝을 이루어 테스트를 진행하는 방식입니다. 이 방식은 프로젝트 초기 단계에서 테스트 계획을 세우고 테스트를 설계하는 과정이 함께 수행됩니다. 이 과정을 그래프로 그리면 영어 V와 모양이 비슷하다고 해서 V 모델이라고 부르기도 합니다.

이 과정은 다음과 같이 수행됩니다.

  • 단위 테스트 Unit Testing
  • 통합 테스트 Integration Testing
  • 시스템 테스트 System Testing
  • 인수 테스트 Acceptance Testing
  • 회귀 테스트 Regressiong Testing

이미지 출처

단위 테스트

단위 테스트는 프로그램의 기본 단위가 되는 모듈을 테스트합니다. 그래서 모듈 테스트라고 부르기도 합니다. 단위 테스트는 각 모듈의 개발이 완료되면 요구분석명세서대로 구현되었는지 테스트합니다.

하나의 모듈을 테스트하므로 상위나 하위 모듈이 필요한 경우가 있는데, 이 모듈들이 개발이 되지 않았을 경우 가상의 상위/하위 모듈을 만들어서 테스트합니다. 이때 가상의 상위 모듈을 테스트 드라이버(test driver)라고 하고, 가상의 하위 모듈을 테스트 스텁(test stub)이라고 합니다.

단위 테스트에선 다음과 같은 오류를 검출합니다.

  • 타입 오류(자료형 오류)
  • 잘못된 논리 연산자
  • 알고리즘 오류
  • 틀린 계산 수식
  • 탈출구가 없는 반복문

통합 테스트

통합 테스트는 테스트가 끝난 모듈을 통합하면서 생기는 오류를 찾는 테스트입니다. 즉, 모듈간의 상호작용이 정상적으로 이루어지는가에 주목을 합니다. 이때 통합을 한꺼번에 하냐, 점진적으로 하냐에 따라 나뉩니다.

  • 한꺼번에 통합하는 빅뱅 테스트
    모듈 통합을 한꺼번에 수행하는 경우에 빅뱅 테스트를 수행합니다. 이 방법은 단위 테스트가 끝난 모듈을 모두 모아 한 번에 통합한 후 테스트를 합니다. 주로 소규모 프로그램이나 프로그램 일부를 구현하는 과정에서 수행합니다.

  • 점진적 통합 - 하향식 기법
    하향식 기법은 모듈의 계층 구조에서 맨 위의 모듈부터 시작해 하위 모듈 방향으로 통합해나가는 방식입니다. 트리 구조의 계층에서 BFS, DFS 방식을 선택해 통합합니다.
    이 방식은 프로그램 전체에 영향을 주는 오류를 일찍 발견할 수 있습니다. 그러나 스텁이 불완전해 결과가 완전하지 않을 수도 있고, 스텁 자체를 만드는데도 시간이 오래 소요될 수 있습니다.
    그래서 모듈간의 상호작용이 정상적으로 잘 되는지 빠르게 파악하고자 하는 경우에 하향식 기법을 사용하게 됩니다.

  • 점진적 통합 - 상향식 기법
    상향식 기법은 가장 아래의 모듈부터 테스트를 시작합니다.
    이 방식은 하위 모듈을 충분히 테스트할 수 있고 정밀 계산, 데이터 처리에 사용하면 좋습니다. 하지만 상위 모듈에 오류가 발생하면 그와 관련된 하위 모듈을 다시 테스트해야하는 번거로운점이 있습니다.

시스템 테스트

시스템 테스트는 모듈의 통합이 끝난 후 전체적인 시스템이 제대로 동작하는지 확인하는 테스트입니다.

즉, 모듈 통합 이후 사용자의 요구사항대로 동작하는지 테스트하는 것입니다. 이 과정은 소프트웨어를 사용자에게 전달하기 전에 개발자가 진행하는 마지막 테스트입니다.

인수 테스트

인수 테스트는 시스템이 예상대로 동작하는지 확인하고 요구사항을 충족하는지 사용자가 수행하는 테스트입니다.

사용자가 주도하여 제품의 출시 여부를 판단하기 위해 수행하는 것이 목적입니다. 만약, 발주가 아닌 출시가 목적인 소프트웨어는 알파 테스트와 베타 테스트를 수행합니다.

  • 알파 테스트
    알파 테스트는 내부 필드 테스트라고 하며, 개발 완료된 소프트웨어를 내부에서 테스트하며 오류와 사용 문제점을 파악합니다.

  • 베타 테스트
    베타 테스트는 알파 테스트를 완료한 소프트웨어를 시장에 내놓기 전에 실제 시장의 피드백을 얻기 위해 수행하는 테스트입니다. 일부 사용자들에게 미리 소프트웨어를 배포해 사용자 입장에서 발생하는 피드백들을 받습니다.

회귀 테스트

회귀 테스트는 수정이 발생하면 그 부분에 대해 테스트를 수행한 후. 관련된 모듈들에 문제가 없는지 테스트하는 것입니다.

0개의 댓글