테스팅은 프로그램이 의도한 대로 작동하는지(a program does what it is intended to do), 사용 전에 프로그램 결함을 발견(to discover program defect)하기 위해 수행됩니다.
소프트웨어를 테스트할 때, artificial data(인공 데이터)를 사용하여 프로그램을 실행합니다.
테스트 결과를 검토하여 오류, 이상 현상 또는 프로그램의 비기능적 속성에 대한 정보를 확인합니다.
오류의 존재만을 나타내며(the presence of error), 그 부재를 나타내지는 않습니다.(Not their absence)
테스팅은 정적 검증 기법도 포함하는 보다 일반적인 검증 및 확인 과정의 일부입니다.
Program testing goals(프로그램 테스트 목표)
개발자와 고객에게 소프트웨어가 요구 사항을 충족함을 보여줍니다.
맞춤형 소프트웨어의 경우, 요구 사항 문서의 모든 요구 사항에 대해 적어도 하나의 테스트(at least one test for every requirement)가 있어야 합니다.
일반 소프트웨어 제품의 경우, 시스템 기능의 모든 테스트와 이러한 기능의 조합(tests for all of the system features, plus combinations of these features) 이 제품 출시에 포함되어야 합니다.
소프트웨어의 동작이 잘못되었거나 명세에 맞지 않는 상황을 발견합니다.
Validating Testing(검증 테스팅)
개발자와 시스템 고객에게 소프트웨어가 요구 사항을 충족한다는 것을 보여줍니다.
성공적인 테스팅은 의도한 대로 시스템이 작동하는 것(the system operates as intented)을 보여준다
Defect Testing(결함 테스팅)
소프트웨어의 동작이 잘못되었거나, 명세와 일치하지 않는 소프트웨어의 결함을 발견합니다.
성공적인 테스팅은 시스템이 잘못 동작하도록 하여 시스템의 결함을 노출시키는 것이다
성공적인 테스트는 시스템이 의도한 대로 작동함을 보여줍니다.
An input-output model of program testing(프로그램 테스트의 입력-출력 모델)
입력 테스트 데이터에서 시스템을 통해 출력 테스트 결과로 이어집니다.
입력이 이상 동작을 일으킨다면, 출력은 결함의 존재를 드러냅니다.
Verification vs validation
Verification:
"우리가 제품을 올바르게 구축하고 있는가?"
소프트웨어는 명세에 반드시 부합해야 한다
validation: "우리가 올바른 제품을 구축하고 있는가?"
소프트웨어는 사용자의 실제 요구 사항을 충족해야 합니다.
Inspections and testing(검사 및 테스트)
Software inspections(소프트웨어 검사)는 정적 시스템 표현을 분석하여 문제를 발견하는 데 중점을 둡니다.(static verification)
tool-based document와 코드 분석을 통해서 수행된다
Software testing(소프트웨어 테스트)는 테스트 데이터로 시스템을 실행하고 동작을 관찰하는 데 중점을 둡니다.(dynamic verification)
따라서 Software testing 의 경우 테스트 케이스 작성이 필요함
Software testing은 NFR 체크가 가능하다
둘 다 IDE에서 많이 제공해준다
코드 분석같은 소프트웨어 검사 / 실행 시간 분석, 디버깅과 같은 소프트웨어 테스트
Inspection and testing are complementary(검사와 테스팅은 보완적이며), verification에 어긋나지 않으며, V & V 과정 중 사용되어야 합니다.
Inspection(검사)는 명세에 대한 conformance(일치, 준수)를 확인할 수 있지만 고객의 실제 요구 사항 준수는 확인할 수 없습니다.
검사는 성능, 사용성 등의 비기능적 특성을 확인할 수 없습니다.(Inspections cannot check non-fuctional characteristics)
Stages of testing(테스팅 단계)
개발 중에 시스템을 테스트하여 버그와 결함을 발견하는 개발 테스팅(Development testing).
제대로 코드를 작성했는지 test case를 가지고 testing
사용자에게 출시되기 전에 시스템의 완전한 버전을 테스트하는 출시 테스팅(Release testing).
유저에게 제공되기 전에 이 릴리즈에 문제가 없는지 체크
사용자 또는 잠재 사용자가 자신의 환경에서 시스템을 테스트하는 사용자 테스팅(User testing).
유저가 통제된 환경에서 실제 테스트를 해보는 것
ex) 게임 beta test
Development testing(개발 테스팅)
Development testing은 팀이 시스템 개발 중 수행하는 모든 테스팅 활동을 포함합니다.
테스팅 활동은 테스트되는 구성 요소 수준에 따라 분류될 수 있습니다.
Unit testing은 개별 프로그램 단위 또는 객체 클래스를 테스트합니다.
Unit testing은 객체나 메서드의 기능성을 테스트하는데에 중점을 둬야 한다
Component testing(컴포넌트 테스팅)은 여러 개별 단위를 통합하여 복합 구성 요소를 생성합니다.
따라서 이 단계에서는 Interface쪽 테스트를 많이 함
보통 Unit이 모아지면 Component가 구성되고, 결국엔 Component, Unit testing이 System testing을 형성하게 됨
System testing은 시스템 일부 또는 전체 구성요소가 통합되어 시스템 전체가 테스트되는 테스트입니다.
System testing은 component interaction을 테스트하는 것에 중점을 둬야 한다
Unit testing
Unit testing은 개별 구성 요소를 독립적으로 테스트하는 과정입니다.
결함 테스트 과정(defect testing process)입니다.
테스트 단위는 다음과 같을 수 있습니다:
객체 내의 개별 함수 또는 메서드(Individual functions or methods within an object)
여러 속성 및 메서드를 가진 객체 클래스(Object classes with several attributes and methods)
대부분 framework이 Individual --> Object 테스트에 집중되어 있음
정의된 인터페이스를 사용하여 기능에 접근하는 복합 구성 요소(Composite components with defined interfaces used to access their functionality)
Object class testing(객체 클래스 테스트)
클래스의 완전한 테스트 범위는 다음을 포함한다
객체와 관련된 모든 operations을 테스트
--> 모든 메서드에 대해서 테스트가 필요하다
ex) Inspection 과정에서 특정 private 메서드가 사용되지 않는지 체크
모든 객체 속성을 설정하고 및 조회하는 것
가능한 모든 상태에서 객체를 운용하는 것
위 두 개는 작성하기 쉬운데, 요거는 작성하는데 난이도가 있음
ex) View에 라이트모드와 다크 모드가 존재한다면, 테스트 해야 할 state가 2개 --> 테스트 해야하는 상황이 많아짐
상속은 테스트 정보가 지역화되지 않기 때문에 객체 클래스 테스트 설계를 더 어렵게 만듭니다.
Automated testing(자동화된 테스트)
Test Framework이 반복되는 테스트에 대한 기능을 지원해줌
가능한 경우, 단위 테스트는 수동 개입 없이 자동화되어 실행 및 확인되어야 합니다.
자동화된 단위 테스트에서는 테스트 자동화 프레임워크(예: JUnit)를 사용하여 프로그램 테스트를 작성하고 실행합니다.
단위 테스트 프레임워크는 특정 테스트 사례를 생성하기 위해 확장할 수 있는 일반적인 테스트 클래스를 제공합니다.
이를 통해 구현한 모든 테스트를 실행하고, GUI를 통해 테스트의 성공 여부를 보고할 수 있습니다.
Automated test components(자동화된 테스트 구성 요소)
초기화 부분(setup)에서 시스템을 테스트 케이스, 즉 입력 및 예상 출력과 함께 초기화합니다.
test input : 파라미터를 넘긴다던지, 클래스의 인스턴스를 만들어서 method invoke를 하는 등등
호출(call) 부분에서 테스트할 객체 또는 메서드를 호출합니다.
test input 을 던져서 call -> output
assertion 부분에서 호출의 결과를 예상 결과와 비교합니다.
output이 expected result와 일치하는지
테스트가 참으로 평가되면 성공한 것이고, 거짓이면 실패한 것입니다.
tear-down(in korean : 해체 단계)부분에서는 리소스 해제 또는 임시 파일 정리와 같이 시스템 상태를 원래 상태로 복원합니다.
처음 두 part에서는 자동화된 테스트 연구에 더욱 주의를 기울인다
Types of Unit Test Cases(단위 테스트 사례 유형)
테스트 사례는 예상대로 사용될 때 테스트하는 구성 요소가 의도한 대로 작동함을 보여줘야 합니다.
구성 요소에 결함이 있는 경우(defects in the component), 이는 테스트 사례에 의해 드러나야 합니다.
이는 두 가지 유형의 단위 테스트 사례로 이어집니다:
첫 번째 유형은 프로그램의 정상 작동을 반영(reflect normal operation of a program)하고 구성 요소가 예상대로 작동함을 보여야 합니다(show that the component works as expected).
다른 유형의 테스트 사례는 일반적인 문제가 발생하는 경험을 기반으로 한다
비정상적인 입력을 사용하여 이러한 입력이 적절하게 처리되고 구성 요소를 충돌시키지 않는지 확인해야 합니다.(user abnormal inputs to check that these are properly processed and do not crash the component)
ex) 값이 NULL로 나오거나, A / B에서 B == 0일 때 문제 없이 작동하는지?
Testing strategies(테스팅 전략)
Partitioning testing(분할 테스트): 입력 그룹을 식별하고, 같은 방식으로 처리되어야 하는 공통 특성을 가집니다.
각 그룹 내에서 테스트를 선택해야 한다.
파티션을 나눠서 대표적인 값을 뽑고, 모든 파티션에 대해서 테스트 될 수 있도록 한다
(Guideline-based testing)가이드라인 기반 테스팅: 테스트 가이드라인을 사용하여 테스트 사례를 선택합니다.
이러한 가이드라인은 구성 요소를 개발할 때 프로그래머가 자주 저지르는 오류를 반영합니다.
"이런 코드에 대한 이런 실수를 많이 하더라"를 바탕으로 체크하는 test case를 만든다.
Partition testing(분할 테스트)
입력 데이터와 출력 결과는 종종 클래스의 모든 멤버가 서로 연관되어 있는 다른 클래스로 나뉩니다.
각 클래스는 동등한 분할 또는 도메인으로, 프로그램이 각 클래스의 모든 멤버에 대해 동등하게 작동하는 곳입니다.
각 분할에서 테스트 사례를 선택해야 합니다.
ex) int n의 input으로 올 수 있는 것 --> (0, 자연수, 음수) or (0 이상, 음수)
ex) 4 / 2 나 2 / 3의 경우에 대한 output group
Equivalence partitioning(동등 분할)
Testing guidelines(collections) / 테스팅 가이드라인 (컬렉션)
단일 값만 포함하는 collections을 사용하여 소프트웨어를 테스트합니다.
예) List list = new ArrayList(); list.add(0);
다양한 크기의 컬렉션을 사용하여 다른 테스트를 수행합니다.
첫 번째, 중간, 마지막 요소가 접근되도록 테스트를 구성합니다.
ex) index 0, list.size() - 1
길이가 0인 컬렉션으로 테스트합니다.
General testing guidelines(일반 테스팅 가이드라인)
시스템이 모든 오류 메시지를 생성하도록 입력을 선택합니다.
예) Java try/catch. 모든 catch 블록을 고려합니다.
입력 버퍼가 오버플로우되도록 입력을 설계합니다.
ex) int 형의 범위, floating point decision
같은 입력이나 일련의 입력을 여러 번 반복합니다.
유효하지 않은 출력이 생성되도록 강제합니다.
계산 결과가 너무 크거나 작아지도록 강제합니다.
ex) int a * b 에서, a==2^16, b==2^16이면 int형의 범위를 넘는다
ex) DB 접속 : Connection 후 close 할 때 Try-catch에서 닫아줘야 함(finally절 사용), 이에 대한 Test case 작성
Component testing(컴포넌트 테스팅)
소프트웨어 컴포넌트는 종종 여러 상호 작용하는 객체로 구성된 복합 컴포넌트입니다.
예를 들어, 소프트웨어는 사용자 데이터를 읽고 데이터를 분석할 수 있는 별도의 부분을 가질 수 있으며, 다양한 출처에서 얻은 데이터를 동일한 기술로 분석할 수 있습니다.
정의된 컴포넌트 인터페이스를 통해 이러한 객체의 기능에 접근합니다.
메서드가 다른 메서드를 사용할 때 Interface 규약이 존재함(자바에서는 javdoc)
ex) Input parameter를 올바르게 넘기고 있는지 Check
div (a, b) -> a / b 가 아니라 b / a를 리턴하도록 코드를 작성했을 수도 있음
복합 컴포넌트 테스팅은 컴포넌트 인터페이스가 그 명세에 따라 동작함을 보여줘야 합니다.
컴포넌트 내 개별 객체에 대한 unit tests가 완료되었다고 가정할 수 있습니다.
Interface testing(인터페이스 테스팅)
목표는 인터페이스 오류나 인터페이스에 대한 잘못된 가정으로 인한 결함을 탐지하는 것입니다.
프로세스가 여러 개이거나, 멀티 쓰레드 환경에서 주로 발생하는 것들을 check
인터페이스 유형:
Parameter interfaces(매개변수 인터페이스): 한 메서드나 프로시저에서 다른 것으로 데이터가 전달됩니다.
Shared memory interfaces(공유 메모리 인터페이스): 메모리 블록이 프로시저나 함수 간에 공유됩니다.
Procedural interfaces(절차 인터페이스): 하위 시스템이 다른 하위 시스템에 의해 호출될 일련의 절차를 캡슐화합니다.
ex) Deadlock 테스트
Message passing interfaces(메시지 전달 인터페이스): 하위 시스템이 다른 하위 시스템으로부터 서비스를 요청합니다.
Interface errors(인터페이스 오류)
Interface misuse(인터페이스 오용)
호출 컴포넌트가 다른 컴포넌트를 호출하고 그 인터페이스 사용에서 오류를 범합니다.
예) 매개변수 순서가 잘못되었습니다.
Interface misunderstanding
호출 컴포넌트가 호출된 컴포넌트의 동작에 대한 잘못된 가정을 포함합니다.
예) null 대신 비어 있거나 기본 객체를 반환합니다.
Timing errors(타이밍 오류)
호출된 컴포넌트와 호출 컴포넌트가 다른 속도로 작동하고 시간 정보에 접근이 이루어질 때 오류가 발생합니다.
ex) Shared resource에 대한 raise condition
Interface testing guidelines(인터페이스 테스트 가이드라인)
호출된 프로시저에 대한 매개변수가 그 범위의 극단적인 끝에 있을 때 테스트를 설계하세요.
코너 케이스나 경계 케이스입니다.
항상 null 포인터를 가진 포인터 매개변수를 테스트하세요.
컴포넌트가 실패하도록 테스트를 설계하세요.
메시지 전달 시스템에서 스트레스 테스트를 사용하세요.
공유 메모리 시스템에서는 컴포넌트가 활성화되는 순서를 변경하세요.
System testing(시스템 테스트)
개발 중 시스템 테스트는 컴포넌트를 통합하여 시스템 버전을 만든 다음 통합된 시스템을 테스트하는 것을 포함합니다.
시스템 테스트의 초점은 컴포넌트 간의 상호작용을 테스트하는 것입니다(testing the interactions between components).
Component 테스트를 위해 testcode를 짜게 되는데, 시스템을 전부 돌려보는 등으로 체크함
시스템 테스트는 컴포넌트가 올바르게 상호작용하고 인터페이스를 통해 적절한 시간에 올바른 데이터를 전송하는지 확인합니다.
시스템 테스트는 시스템의 긴급 동작(the emergent behaviour of a system)을 테스트합니다.
System and component testing(시스템 및 컴포넌트 테스트)
시스템 테스트 중에는 별도로 개발된 재사용 가능한 컴포넌트와 시판용(off-the-shelf) 시스템이 새로 개발된 컴포넌트와 통합될 수 있습니다.
그런 다음 전체 시스템이 테스트됩니다.
다른 팀 멤버 또는 하위 팀에 의해 개발된 컴포넌트는 이 단계에서 통합될 수 있습니다.
여태까지 개발한 테스트를 모아서 System testing이 되는 것에 가까움
시스템 테스트는 개별적인 프로세스가 아닌 집단적인 프로세스입니다.
일부 회사에서는 설계자 및 프로그래머의 참여 없이 별도의 시스템 테스트 팀이 관여할 수 있습니다.
ex) 회사 QA 팀에서 Component를 모아서 System testing을 한다
Use-case testing(유스케이스 테스트)
시스템 상호작용을 식별하기 위해 개발된 use-cases는 시스템 테스트의 기초로 사용될 수 있습니다.
각 use case는 일반적으로 여러 시스템 컴포넌트를 포함하므로 테스트 중에 이러한 상호작용이 발생하도록 합니다.
use case 에 연관된 순서 다이어그램은 테스트되고 있는 구성요소 및 상호작용을 설명할 수 있습니다.
ex) UML, 복잡한 코드의 메서드 호출 순서(A->B->C...)
Testing Policies(테스트 정책)
철저한 시스템 테스트는 불가능하므로 필요한 시스템 테스트 커버리지를 정의할 수 있는 테스팅 정책이 개발될 수 있습니다.
이 정도까지 테스트 하면 괜찮다 를 정의
테스팅 정책 예시:
메뉴를 통해 접근되는 모든 시스템 기능을 테스트해야 합니다.
같은 메뉴를 통해 접근되는 기능 조합(예: 텍스트 포맷팅)을 테스트해야 합니다.
각 기능을 조합했을 때 문제가 없는지 check
사용자 입력이 제공되는 경우, 모든 기능은 정확한 입력과 잘못된 입력 모두에서 테스트되어야 합니다.
원자로 시스템 같은 경우에는 더 엄격한 Testing Policy를 가짐
Test-driven Development
Test-driven development(테스트 주도 개발(TDD)은 테스트와 코드 개발을 교차 진행하는 프로그램 개발 방식입니다.
테스트는 코드 작성 전에 작성되며, 테스트 통과가 개발의 주요 동인입니다.
Setup, call, assertion 단계 중에서 Setup에서 어려움을 주로 겪음
코드를 점진적으로 개발하며, 그 단계에 맞는 테스트를 함께 개발합니다.
다음 단계로 넘어가기 전에 개발된 코드가 그 테스트를 통과해야 합니다.
TDD는 익스트림 프로그래밍과 같은 애자일 방법의 일부로 소개되었습니다.
하지만, 계획 주도 개발 과정에서도 사용될 수 있습니다.
Benefits of Test-driven Development
Code coverage(코드 커버리지)
작성하는 모든 코드 세그먼트에는 적어도 하나의 테스트가 연결되어 모든 코드가 테스트를 받습니다.
내가 작성한 코드에 대해서 test case를 가지고 있기 때문에, code Coverage가 올라감
Regression testing(회귀 테스트)
새로운 코드를 작성해도 기존 코드가 잘 작동하는지
프로그램이 개발됨에 따라 점진적으로 회귀 테스트 모음(suite)이 개발됩니다.
Simplified debugging(디버깅 간소화)
왜 오류가 발생하는지 하나씩 실행을 해야하는데, test를 돌려봄으로써 어떤 부분에 문제가 있는지 체크할 수 있고, 이 부분을 자동화 할 수 있음
테스트 실패 시 문제가 있는 위치가 명확해지며, 새로 작성된 코드를 확인하고 수정해야 합니다.
System documentation(시스템 문서화)
Agile에서는 documentation을 최소화해야하는데, test case가 Specification과 같은 역할을 해준다
테스트 자체가 코드가 수행해야 할 작업을 설명하는 문서 형태로 작용합니다.
Regression Testing
Regression Testing(회귀 테스트)는 시스템을 테스트하여 변경 사항이 이전에 작동하던 코드를 '깨트리지' 않았는지 확인합니다.
ex) method X를 수정할 때, X를 호출하는 다른 메서드에서 문제가 발생하지 않는지 확인한다
수동 테스팅 과정에서 회귀 테스트는 비용이 많이 들지만, 자동화 테스팅을 사용할 경우 간단하고 직관적입니다.
변경이 이루어질 때마다 모든 테스트를 다시 실행합니다.
테스트는 변경 사항이 커밋되기 전에 '성공적으로' 수행되어야 합니다.
TDD는 회귀 테스트를 확보하는 좋은 방법입니다.
Code Coverage
Statement Coverage(or Line Coverage) / 구문 커버리지(또는 라인 커버리지)
statement가 실행되면 충족됩니다.
일반적으로 Code Coverage라고 함은 Statement Coverage를 말함
Branch Coverage(or Decision Coverage)
각 branch(분기)가 실행되면 충족됩니다.
코드 상에서 Branch가 발생하는 경우 (실행 경로가 달라지는 경우)에 실행할 수 있는 서로 다른 경로가 잘 실행되는지
ex) if-else 문에서 실행 경로가 갈리짐
Condition Coverage(조건 커버리지)
branch(분기) 내 각 조건이 테스트되면 충족됩니다.
ex) (A && B) || C 에서 A, B, C의 T/F
Increasing Code Coverage
테스트 케이스의 setup 부분과 call 부분을 신중하게 설계함으로써 코드 커버리지를 높일 수 있습니다.
자바에서는 private 메소드가 public 메소드에 의해 호출되어야 합니다.
테스트가 모든 public 메소드를 호출하고, 메소드 내의 모든 분기를 취하면 이론적으로 100% 라인/분기 커버리지를 달성할 수 있습니다.
만약 private 메서드를 호출 안한다면 그냥 그 메서드를 지우고, 필요할 때 commit log를 확인해서 가져다 쓰자
이를 위해 적절한 객체 인스턴스를 생성하는 것이 중요하며, 이는 메소드를 호출하는 데 사용될 수 있습니다.
좋은 모듈화는 프로그램의 각 단위에 대한 테스트 케이스를 작성하기 쉽게 만듭니다.
Tip
메서드가 100줄이라고 하면, Unit test에서는 input을 던져서 100줄 다 Cover 할 수 있도록 하자
이를 위해서 if() A, else B라고 하면 A와 B를 다른 메서드로 분리해줄 수 있다(Clean-Code에 있는 내용인 듯)
java에서는 mockito의 Mock-up을 이용해서 커버리지를 올릴 수 있다
테스트 스윗의 라인 커버리지가 99%라고 하더라도, 에러를 더 잘 발견한다고 보기 어렵다. 적절한 Input을 구성해야 함
Limitation of Code Coverage
코드 커버리지는 테스트 스위트의 품질 또는 성능을 평가하는 데 사용됩니다.
코드의 얼마나 많은 부분이 테스트 되었나요?
자동화 테스트 연구는 종종 분기 커버리지를 사용합니다.
RandooP, EvoSuite 같은 도구가 JUnit 테스트 케이스 생성에 사용됩니다.
물론, 이렇게 해서 커버리지를 올려도 실제로 오류 발견 확률이 올라가지 않을 수 있음
최근 연구에 따르면 코드 커버리지만으로는 테스트 스위트 평가에 충분하지 않습니다.
실제로 결함을 감지하는지에 대한 질문이 제기됩니다.
Mutation testing(돌연변이 테스트): 코드를 자동으로 변형하여 결함을 심고, 테스트가 결함을 감지할 수 있는지 확인합니다.
Java 돌연변이 테스트를 위한 PIT 도구가 사용됩니다.
코드 일부를 변형한다면(ex. If문을 제거하거나, a = b와 같은 statement 제거) 에러가 발생해야 하는데, 이를 체크한다
TDD Example
// NFR test(계산 속도)
@Test
@Timeout(value = 1, unit = TimeUnit.SECONDS)
void testFibonnaci2() {
assertTimeout(Duration.ofMillis(1), () —> {
SimpleMath.fibonacci(50);
});
}
// 메서드 구현 코드
public static int fibonacci(int n) {
return fibonacci(n-1, 1, 1);
}
private static int fibonacci(int n, int pp, int p) {
if (n <= 2) {
return p;
} else {
return fibonacci(n-1, p, pp*p);
}
}
Release Testing
릴리즈 테스팅은 개발 팀 외부에서 사용하도록 의도된 특정 릴리즈의 시스템을 테스트(testing a particular release of a system that is intended for use outside of the development team)하는 과정입니다.
릴리즈 테스팅의 주요 목표는 시스템 공급자에게 시스템이 사용에 충분히 좋다는 것을 확신시키는 것입니다.
따라서, 릴리즈 테스팅은 시스템이 지정된 기능, 성능 및 신뢰성을 제공하며 정상 사용 중에 실패하지 않음을 보여야 합니다.
릴리즈 테스팅은 일반적으로 블랙박스 테스팅 과정으로, 테스트는 시스템 명세에서만 파생됩니다.
화이트박스 테스팅과 대조됩니다.
Release testing and system testing(릴리스 테스팅과 시스템 테스팅)
릴리스 테스팅은 시스템 테스팅의 한 형태입니다.
중요한 차이점:
시스템 개발에 참여하지 않은 별도의 팀이 릴리스 테스팅을 담당해야 합니다.
개발 팀에 의한 시스템 테스팅은 시스템 내 버그를 발견하는 데 중점을 둬야 합니다 (결함 테스팅) / focus on discovering bus in the system(defct testing).
릴리스 테스팅의 목적은 시스템이 요구 사항을 충족하고 외부 사용에 충분히 좋은지 확인하는 것입니다 (검증 테스팅). / to check that the system meets its requirements and is good enough for external use(validation testing)
Requirements based testing(요구 사항 기반 테스팅)
요구 사항 기반 테스팅(Requirements-based testing)은 각 요구 사항을 검토하고 이에 대한 테스트를 개발하는 것을 포함합니다.
이미 중간 릴리스 목록에 대한 요구 사항 기반 테스팅 경험이 있습니다.
개발된 테스트가 반드시 자동화된 테스트일 필요는 없습니다.
단순히 시나리오를 정의하여 요구 사항이 충족되는지 확인할 수 있습니다.
Performance testing(성능 테스팅)
릴리스 테스트의 일부에는 성능 및 안정성과 같은 시스템의 새로운 속성 테스트가 포함될 수 있습니다.
테스트는 시스템 사용 프로필을 반영해야 합니다.
성능 테스트는 일반적으로 시스템 성능이 수용할 수 없을 때까지 부하를 점진적으로 늘리는 일련의 테스트를 계획하는 것을 포함합니다.
스트레스 테스트는 시스템을 고의로 과부하 상태로 만들어 그 실패 행동을 테스트하는 성능 테스트의 한 형태입니다.
ex) API request가 10000개 일 때, 5초 안에 return 해줘야 한다
보통 Development 팀이 아니라 외부 team(ex. QA team)이 이런 것들을 test 함
User testing(사용자 테스팅)
사용자 또는 고객 테스팅은 사용자 또는 고객이 시스템 테스팅에 대한 의견을 제공하는 테스트 과정의 단계입니다.
사용자 테스팅은 포괄적인 시스템 및 릴리스 테스팅이 수행된 후에도 필수적입니다.
이는 사용자의 작업 환경에서 발생하는 영향(influnces from the user's working environment have a major effect)이 시스템의 신뢰성, 사용성 및 견고성에 주요한 영향을 미치기 때문입니다.
target env랑, working env를 고려해야 한다.
ex) MAC의 Javadoc과 Linux의 Javadoc 차이 존재
이러한 것들은 테스트 환경에서 재현할 수 없습니다.
Types of user testing(사용자 테스팅의 유형)
Alpha testing(알파 테스팅)
소프트웨어의 사용자가 개발자 사이트에서 개발 팀과 함께 소프트웨어를 테스트합니다.
ex) 유저를 초청해서 Test하거나, 회사 내부에서 테스트를 진행하는 등
Beta testing(베타 테스팅)
소프트웨어의 릴리스가 사용자에게 제공되어 시스템과 관련된 문제를 발견하고 제기할 수 있도록 합니다.
불특정 다수를 대상으로 Release를 배포하여 feedback을 받는다
Acceptance testing(승인 테스팅)
고객이 시스템을 테스트하여 시스템 개발자로부터 배포되고 고객 환경에서 사용할 준비가 되었는지를 결정합니다. 주로 맞춤형 시스템에 사용됩니다.
User Testing for Different Types of Software(다양한 소프트웨어 유형에 대한 사용자 테스팅)
소프트웨어가 사용자 테스팅에 충분히 개발되었음에도 불구하고 아직 테스팅 단계에 있습니다.
이 기간 동안 발견되지 않은 오류가 발생할 수 있습니다.
따라서 다양한 소프트웨어 유형에 대해 사용자 테스팅을 설계하고 수행할 필요가 있습니다.
예를 들어, 온라인 게임의 베타 테스팅은 자율 주행 소프트웨어나 금융 소프트웨어에 비해 더 쉽게 수행될 수 있습니다.
Agile methos and acceptance testing(애자일 방법론 및 승인 테스팅)
애자일 방법에서 사용자/고객은 개발 팀의 일부이며 시스템의 수용성에 대한 결정을 내리는 책임이 있습니다.
테스트는 사용자/고객에 의해 정의되며 변경이 이루어질 때 자동으로 실행되도록 다른 테스트와 통합됩니다.
여기서 주요 문제는 내장된 사용자가 '전형적'이고 모든 시스템 이해관계자의 이익을 대표할 수 있는지 여부입니다.
Acceptance testing(ex. 계약맺고 개발하여 제공하고, 돈을 정산 받는 구조) --> Agile은 이런 과정이 아님
요약
Program testing은 verification 및 validation 과정에서 중요한 부분입니다.
테스팅의 두 가지 주요 목표는 요구 사항 확인과 결함 발견입니다.
Software inspection는 문제를 발견하기 위한 static verification이며, software testing은 프로그램 동작을 관찰하기 위한 dynamic verification입니다.
프로그램 테스팅은 development testing, release testing and user testing으로 구성됩니다.
TDD는 테스트와 코드 개발을 교차하여 진행하는 접근 방식으로, 개발된 프로그램이 통과해야 하는 테스트 케이스 작성부터 시작합니다.