본문 바로가기
CS 지식/소프트웨어 공학

Software Testing(소프트웨어 테스팅)과 개발 테스팅

by 코딩하는 동현😎 2024. 12. 1.

Program Testing

구현 -> unit test -> low level design 이렇게 cycle이 반복된다.

  • 목적: 프로그램이 의도한 대로 동작하는지 확인하고, 프로그램을 실제로 사용하기 전에 결함을 발견하는 과정입니다.
    • 소프트웨어 테스트는 가상 데이터를 사용하여 프로그램을 실행하고, 테스트 실행 결과에서 오류, 이상 현상, 또는 비기능적 특성에 대한 정보를 확인합니다.
    • 테스트는 오류의 존재는 밝혀낼 수 있지만, 부재는 증명할 수 없습니다.
    • 위 뜻은 테스팅으론 아무리 열심히 해도 100% 에러를 찾지 못합니다. 오류가 없다고 '증명'하는것이 절대 아닙니다.
    • 테스트는 검증 및 검토 (V&V) 과정의 일부입니다. V&V 기법중 30%가 Testing이라고 볼수 있습니다.

Two Types of Program Testing

  1. Validation Testing: 이해관계자의 need, concern
    • 목적: 개발자와 고객에게 "소프트웨어가 사용자 요구 사항을 충족한다"는 것을 입증하기 위한 테스트.
    • 성공적인 테스트는 시스템이 의도대로 작동함을 보여줍니다.
    • 주어진 테스트 케이스가 시스템의 예상 사용을 반영할 때, 시스템이 올바르게 동작해야 한다는 기대가 있습니다.
  2. Verification Testing: Spec, SRS에 맞게 동작
    • 목적: "소프트웨어 동작이 잘못되었거나, 원하지 않는 방식으로 동작하거나, 명세와 일치하지 않는 상황을 발견"하는 과정.
    • 성공적인 테스트는 시스템이 잘못 동작하도록 유도하여 시스템의 결함을 드러내는 테스트입니다.
    • Defect Testing = 결함을 노출시키기 위한 테스트 케이스 설계.
    • defect(fault, bugX)를 찾는 것이다. bug는 실수 일뿐이다.

Verification and Validation (V&V)

  • Validation: "우리는 올바른 소프트웨어를 만들고 있는가?"
    • 목표: 소프트웨어가 사용자의 실제 요구를 충족하는지 확인.
  • Verification: "우리는 명세대로 소프트웨어를 잘 만들고 있는가?"
    • 목표: 소프트웨어가 요구사항 명세를 충족하는지 확인.

 

Validation같은 경우는 stackholder의 need에 맞는지 여부라 꼭 코드일 필요는 없다.

Varification은 꼭 코드가 필요하다.

Validation의 대표주자 ex) review : 전문가가 코드를 훑어본다.


V-Model of V&V Activities

  • V-모델은 개발과 테스트 활동을 연결하여, 개발 단계에서 수행한 작업에 대응하는 테스트 활동을 설명합니다.
    • V-모델은 개발 활동(예: 요구사항 분석, 설계)과 이에 대응하는 테스트 활동(예: 요구사항 검증, 설계 검증)을 연결합니다

 

System Specifications : SW analysis

Subsystem Design/Specs : SDS

Delivered Package : bug를 찾는 용도X. Custom SW같은 것을 User Acceptance Test등을 통해서 이해관계자의 Validation에 맞는지 최종을 Test하는 것이다. (validation reject당하면 다시 만들어야함)

Acceptance Test는 보통 custom SW만 이용하고, alpha, beta testcustom, generic SW 둘다 이용한다.

근데 사실 Acceptance Test를 큰 의미로 보면 Acceptance Test, alpha, beta test 이 세가지를 포함하는 말이다.

보통 UAT라고 하면 좁은 의미의 Acceptance Test이므로 Custom SW가 하는 테스트를 말한다.

 


V&V Confidence (SQA 기획)

level : ISO 26262

  • 목표: 시스템이 '목적에 맞게' 동작한다는 신뢰를 확립하는 것입니다.
  • V&V 신뢰도는 다음에 따라 달라집니다:
    • 소프트웨어 목적: 소프트웨어의 중요성에 따라 신뢰도 수준이 달라집니다.
    • 사용자 기대: 일부 소프트웨어는 사용자 기대가 낮을 수 있습니다.
    • 마케팅 환경: 제품 출시가 결함 발견보다 더 중요할 수 있기 때문에 초기 출시가 더 중요할 수 있습니다.

3 Axes of V&V

  1. Optimistic Inaccuracy:(낙관적)
    • 일부 프로그램이 요구되는 속성을 가지지 않아도 이를 수용할 수 있습니다. 모든 위반을 탐지하지 못할 수 있습니다.
    • 검증 과정에서 문제가 있는 프로그램을 통과시키는 오류를 의미합니다. 즉, 실제로는 결함이 있는 프로그램이 테스트에서 발견되지 않고, "정상"으로 간주되는 상황입니다.
    • 예: Testing(불충분한 cases) -> Dynamic code Analysis (실행이 되어야하므로 컴파일이 되어야함)
  2. Pessimistic Inaccuracy:(비관적)
    • 프로그램이 해당 속성을 가질지라도 잘못 판단할 수 있습니다. 이는 잘못된 경고로 인한 문제일 수 있습니다.
    • 실제로는 결함이 없는 프로그램을 테스트나 검증 도구가 잘못된 것으로 판단하는 경우입니다.(False alarm)
    • 예: Automated program analysis -> Static code Analysis(자동화 도구가 읽고 notation, graph를 해준다.)
    • 대신 false alarm(문제가 없는데 있다고 하는 허위 경고) 30% 확률이 있다
  3. Simplified Properties:
    • 속성을 단순화(모델링)하여 자유도를 줄여서 검증을 용이하게 합니다.
    • 복잡한 소프트웨어 속성을 간소화해 평가를 진행하는 경우를 의미합니다. 즉, 정확성과 현실성을 일부 포기하고 더 단순한 기준으로 분석합니다.
    • 예: Model Checking(FSM 검증하기) : formal(정형) 검증(코드까지 안내려가고 모델에서만)

Software Testing Stages

소프트웨어 테스트는 여러 단계로 나뉘며, 각 단계에서 다른 활동을 진행합니다:

  1. Development Testing: Unit, Integration Test (개발자가 한다)
    • 개발 중에 시스템을 테스트하여 버그와 결함을 발견합니다.
  2. Release Testing: release전에 전문 테스팅 그룹(제 3자가 하기도한다)이 System Testing을 한다.
    • 별도의 테스트 팀이 시스템의 전체 버전을 테스트하여, 사용자에게 배포하기 전에 검증합니다.
  3. User Testing: Acceptance, alpha, beta
    • 사용자나 잠재적 사용자가 실제 환경에서 시스템을 테스트하여 사용성 및 안정성을 확인합니다.

Software Testing Process

소프트웨어 테스트 과정은 전체 개발 프로세스에서 중요한 부분을 차지하며, 시스템의 기능과 품질을 보장하는 데 중요한 역할을 합니다.

 

case(모호) -> data(코드, 구체적인 값)

test cases : 코드 나오기전 Design 단계에서 나온다

test data : test instantation, generation

 

Uniform한 테스팅이 중요하다.(테스트를 일관되고 균일하게 수행해야 한다)


Development Testing

Development Testing는 시스템을 개발하는 팀이 수행하는 모든 테스트 활동을 포함합니다.

  • Unit Testing: 개별 프로그램 단위나 객체 클래스를 테스트합니다. 이 테스트는 객체나 메소드의 기능을 테스트하는 데 집중합니다.
  • Integrated Testing: 여러 개별 단위를 통합하여 복합 컴포넌트를 생성하고, 컴포넌트 간의 인터페이스와 상호작용을 테스트합니다.
  • System Testing: 시스템의 일부 또는 모든 구성 요소를 통합하여 시스템 전체를 테스트합니다. 시스템 테스트는 시스템의 모든 기능을 통합적으로 테스트하는 데 집중합니다.
  • Regression Testing: 시스템이 변경된 후 기존에 잘 작동하던 코드가 깨지지 않았는지 확인하는 테스트입니다. 개발 및 유지보수 단계에서 수행됩니다.

Unit Testing

  • Unit Testing은 개별 구성 요소를 독립적으로 테스트하는 과정입니다.
    • Defect Testing: 객체나 메소드의 모든 작업을 테스트하여 결함을 찾는 작업입니다.
    • 유닛은 다음과 같습니다:
      • 개별 함수 또는 메소드
      • 속성과 메소드가 포함된 객체 클래스
      • 객체와 관련된 모든 작업을 설정하고, 객체 상태를 검사합니다.
      • 객체를 다양한 상태에서 실행하여 모든 가능한 상태를 테스트합니다.

The Weather Station: Unit Testing for Objects(객체 지향)

  • 객체의 모든 작업을 모든 상태에서 테스트하기 위해 테스트 케이스를 정의해야 합니다.
    • 상태 모델을 통해 테스트할 상태 전환 시퀀스와 해당 전환을 유발하는 이벤트 시퀀스를 식별할 수 있습니다.
    • 예:
      • Shutdown -> Running -> Shutdown
      • Configuring -> Running -> Testing -> Transmitting -> Running
      • Running -> Collecting -> Running -> Summarizing -> Transmitting -> Running

객체 지향일때는 identifier(식별자)에 따라 결과가 달라져서 전부 test 해줘야 한다.


Automated Testing

  • 가능하면 유닛 테스트는 자동화되어야 합니다. 테스트는 수동 개입 없이 실행되고 확인됩니다.
  • 반복해서 할 수 있다는 장점이 있다. 
    • Unit Testing Frameworks: 테스트 클래스의 기본 클래스를 제공하여 구체적인 테스트 케이스를 생성합니다. 모든 테스트를 실행하고, 결과를 GUI를 통해 보고합니다. 예: JUnit, xUnit 등.
    • 구성 요소:
      1. Setup Part: 테스트 케이스에 필요한 입력값과 예상 결과로 시스템을 초기화합니다.
      2. Call Part: 테스트할 객체나 메소드를 호출합니다.
      3. Assertion Part: 호출 결과를 예상 결과와 비교합니다. 예상 결과가 맞으면 테스트가 성공한 것입니다. 틀리면 실패한 것입니다.

Developing Unit Test Cases

  • 유닛 테스트 케이스는 두 가지 유형으로 나눌 수 있습니다:
    1. Positive Test Cases: 프로그램이 정상적으로 작동하는지 확인하는 테스트입니다. (기능대로 작동하는지)
    2. Negative Test Cases: 잘못된 입력을 통해 프로그램이 올바르게 처리되고 충돌하지 않는지 확인하는 테스트입니다. (엉뚱한 값을 넣었을때 대처를 잘했는가 :  방어코드 Secure code를 잘 작성해야된다)

Unit Testing Strategies

  1. Partition Testing: 전반적으로 고루하게 빠짐없이
    • 입력 데이터와 출력 결과는 종종 공통 특성을 가진 여러 클래스로 나눠질 수 있습니다.
    • 각 클래스는 동일한 방식으로 처리되어야 하므로, 각 클래스에서 테스트 케이스를 선택해야 합니다.
  2. Guideline-based Testing
    • 테스트 가이드라인을 사용하여 테스트 케이스를 선택합니다. 이 가이드라인은 개발자가 자주 실수하는 오류 유형을 기반으로 합니다.
    • Brute-force Testing (막 테스트):
    • 시스템에서 모든 오류 메시지를 발생시키거나, 입력 버퍼가 오버플로우되게 하거나, 동일한 입력을 여러 번 반복하여 오류를 찾습니다.
    • 잘못된 출력을 발생시키거나, 계산 결과가 너무 크거나 작게 만들기도 합니다.

Partition Testing

  • 입력 데이터와 출력 결과는 종종 서로 다른 클래스에 속하며, 각 클래스의 구성원은 동일한 방식으로 프로그램이 동작합니다.
    • 각 클래스는 Equivalence Partition 또는 Domain이라 불리며, 각 클래스 내의 구성원은 동일한 방식으로 처리됩니다.
    • 테스트 케이스는 각 파티션에서 선택되어야 합니다.

Equivalence Partitions with Boundary Value Analysis(test case를 만드는 기법)

  • Boundary Value Analysis는 파티션 경계를 기준으로 테스트를 설계하는 방법입니다. 예를 들어, 입력 값이 특정 범위 내에 있어야 하는 경우, 그 범위의 경계를 테스트하는 방법입니다.

경계에서 Error가 자주 발생한다


Functional Testing – Techniques Overview

  • Functional Testing은 시스템의 기능이 의도된 대로 동작하는지 확인하는 테스트입니다.

Integration Testing

  • 소프트웨어 컴포넌트는 종종 여러 개의 상호작용하는 객체들로 구성된 복합 컴포넌트입니다.
    • Integration Testing은 복합 컴포넌트를 테스트하는 과정입니다.
    • 목표: 컴포넌트 인터페이스가 명세대로 동작하는지, 컴포넌트 간 상호작용이 올바른지 확인합니다.
    • 전제 조건: 개별 객체에 대한 유닛 테스트가 완료되었음을 가정합니다.

A, B, C등을 합칠때, A, B, C라는 I/O 인스턴스를 만들어서 test case를 입력을 한다.

-> ABC가 같이 섞여있는 것들로 = interface testing


Guidelines for Integration Testing

  • Interface Testing Guidelines:
    • 호출된 절차의 매개변수가 범위의 극단적인 끝에 있을 때 테스트를 설계합니다.
    • 포인터 매개변수는 항상 Null 포인터로 테스트합니다.
    • 컴포넌트가 실패하는 경우를 유도하는 테스트를 설계합니다.
    • 메시지 전달 시스템에서는 Stress Testing을 사용합니다.
    • 공유 메모리 시스템에서는 컴포넌트가 활성화되는 순서를 변경하여 테스트합니다.

System Testing

  • System Testing은 시스템의 구성 요소들이 통합되어 버전으로 만들어진 후, 전체 시스템을 테스트하는 과정입니다. (전체 시스템에서만 보고 안쪽을 아에 보지 않는다.)
    • 목표: 컴포넌트가 호환되고, 올바르게 상호작용하며, 데이터가 정확하게 전달되는지 확인합니다.
    • 시스템의 emergent behavior (상호작용에서 발생하는 새로운 동작)를 테스트합니다.
    • System Testing은 팀워크가 중요한 과정입니다. 여러 팀이 개발한 재사용 가능한 컴포넌트나 상용 소프트웨어를 통합하여 시스템을 테스트합니다.

Collective Process

  • System testing은 집단적 과정입니다. 즉, 여러 팀이 협력하여 이루어집니다.
  • 재사용 가능한 컴포넌트상용 시스템이 이미 개발되어 있을 경우, 이를 새로운 컴포넌트와 결합하여 시스템을 구성하고 테스트합니다.
  • 다양한 팀이나 하위 팀에서 개발한 컴포넌트들이 시스템 통합 단계에서 결합될 수 있습니다.

Testing Team

  • 시스템 테스트는 별도의 독립적인 테스트 팀에 의해 수행될 수 있습니다. 이 팀은 시스템을 설계하거나 프로그래밍한 팀과는 별개로 작업을 하며, 최종적인 시스템의 동작을 검증합니다.

Release Testing


Developing System Test Cases

  • Use-caseSequence Diagram을 기반으로 테스트 케이스를 개발할 수 있습니다.
    • Use-case는 여러 시스템 컴포넌트를 포함하고, 이를 테스트하는 것은 여러 상호작용을 강제로 발생시킵니다.
    • Sequence Diagrams는 테스트할 구성 요소와 상호작용을 문서화합니다.

 actor가 우리 시스템, 다른 나머지가 외부 시스템이다. 서로의 오고가는 Testing case로 만들어야한다


Testing Policies

  • Exhaustive System Testing은 항상 불가능합니다. 대신 테스트 정책은 시스템 테스트 커버리지를 정의합니다.
    • 예시:
      • "메뉴를 통해 접근할 수 있는 모든 시스템 기능은 테스트해야 한다."
      • "같은 메뉴에서 접근 가능한 기능 조합을 모두 테스트해야 한다."
      • "사용자 입력이 제공되는 곳에서는 모든 기능을 올바른 입력과 잘못된 입력으로 테스트해야 한다."

Regression Testing

  • Regression Testing은 시스템이 변경된 후 이전에 잘 작동하던 코드가 제대로 작동하는지 확인하는 테스트입니다. (maintance 단계)
    • 수동 테스트에서는 비용이 많이 들지만, 자동화된 테스트에서는 간단하고 직관적입니다.
    • 모든 테스트는 프로그램 변경 시마다 다시 실행되며, 변경 사항이 커밋되기 전에 모든 테스트가 성공해야 합니다.
    • 이론적으로 연구가 많이 남았습니다. (테스팅을 가능한 적게 하기 위해)

Test-Driven Development (TDD)

TDD테스트 주도 개발로, 테스트코드 개발교차시키며 진행하는 개발 방식입니다. TDD의 핵심은 코드를 작성하기 전에 먼저 테스트를 작성(Specification을 잘봐야한다)하고, 그 테스트를 통과하는 것이 개발의 중요한 목표가 된다는 점입니다. 이는 코드를 점진적으로 개발하면서, 그 각 개발 단계마다 테스트를 작성하고, 테스트를 통과하지 않으면 다음 단계로 넘어가지 않는 방식을 의미합니다.

  • 주요 특징
    • 테스트를 먼저 작성하고 그 테스트를 통과하는 것이 개발을 이끄는 핵심입니다.
    • 코드를 점진적으로 개발하며, 각 코드 증분에 대해 테스트를 작성합니다.
    • 코드는 반드시 그 테스트를 통과한 후에만 다음 증분으로 넘어갑니다.
  • TDD의 기원
    • TDD는 애자일 방법론의 일환으로, XP (Extreme Programming) 등에서 도입되었습니다.
    • 그러나 TDD는 계획 중심 개발(Plan-driven development) 방식에서도 사용할 수 있습니다.

TDD와 TFD는 교집합은 있지만 포함되지 않는다.

TFD -> 테스트가 제일 중요하다

TDD -> 테스트를 먼저 만들고 개발한다. (만약에 변경됐을때도 테스트를 우선적으로 한다는 보장은 없어서 TFD 어길수도 있다)


TDD의 장점

  1. 코드 커버리지
    • 작성한 모든 코드에는 최소한 하나의 테스트가 연관되어 있어, 모든 코드가 테스트됩니다.
  2. Regression testing을 도와준다
    • 프로그램 개발 중에 회귀 테스트 스위트를 점진적으로 개발합니다.
    • 코드 변경 시, 이전에 작동하던 코드가 깨지지 않았는지 테스트를 반복하여 확인합니다.
  3. 디버깅 간소화
    • 테스트가 실패할 경우, 문제의 원인이 새로 작성된 코드에 있음을 명확하게 파악할 수 있습니다. (Fault localization에 도움)
  4. 시스템 문서화
    • 작성된 테스트 자체가 코드가 무엇을 해야 하는지 설명하는 문서화의 역할을 합니다.
    • TDD의 unit testcase = unit specification(문서)

Release Testing

Release Testing은 개발 팀 외부에서 사용할 시스템의 특정 버전을 테스트하는 과정입니다. 이 테스트의 목표는 시스템이 사용자에게 적합한지 확인하는 것입니다.

  • 목표:
    • 시스템이 명시된 기능, 성능, 신뢰성을 제공하는지 확인합니다.
    • 시스템이 정상적으로 사용되는 중에 작동 실패가 없도록 해야 합니다.
  • 주요 특징:
    • 블랙박스 테스트(사용자가 직접 사용하는 기능) 방식으로 진행됩니다. 이는 시스템 명세만을 바탕으로 테스트가 생성된다는 의미입니다.
    •  

Release Testing vs. System Testing

  • Release TestingSystem Testing의 한 형태입니다.
  • 중요한 차이점:
    • 독립적인 팀이 Release Testing을 담당해야 하며, 시스템 개발에 참여하지 않은 팀이 테스트를 진행합니다.
    • 시스템 테스트는 시스템의 버그를 찾는 것에 집중합니다 (결함/검증 테스트).
    • Release Testing은 시스템이 요구 사항을 충족하는지와 외부 사용에 적합한지 확인하는 데 중점을 둡니다 (검증 테스트).
  • 성능 테스트 (Performance Tests):
    • 시스템의 성능이 수용 한계에 도달할 때까지 점진적으로 부하를 증가시키며(Load testing) 테스트합니다.
  • 스트레스 테스트 (Stress Testing):
    • 시스템을 의도적으로 과부하시키며 실패 행동을 테스트합니다. (load를 과하게)

User (Acceptance) Testing

User Testing은 사용자가 실제로 시스템을 사용하고 피드백을 제공하는 과정입니다. 사용자 환경에서 발생하는 효율성, 성능, 사용성, 견고성 등의 특성은 테스트 환경에서는 재현하기 어렵기 때문에, 사용자 테스트는 시스템의 신뢰성에 중요한 영향을 미칩니다.

  • 사용자 테스트의 유형:
    1. 알파 테스트 (Alpha Testing): 사용자를 회사로 부른다
      • 사용자가 개발 팀과 함께 개발 환경에서 시스템을 테스트합니다.
    2. 베타 테스트 (Beta Testing): 집 또는 PC방에서 자유롭게 테스팅
      • 시스템의 베타 버전을 사용자에게 제공하여, 사용자들이 직접 사용해보고 문제를 발견하여 개발자에게 피드백을 주는 방식입니다.
    3. Acceptance Testing: Customized SW에 적용
      • 고객이 시스템을 테스트하여 시스템이 배포 준비가 되었는지, 고객 환경에서 사용 가능한지 결정하는 단계입니다. 주로 맞춤형 시스템에 대해 사용됩니다.
반응형

댓글