Program Testing
- 프로그램이 제대로 작동하는 지 확인하기 위해선 테스트가 필요하다.
- 테스트는 프로그램이 정확히 작동하는지, 오류가 생기지 않는지, 원하는 방식으로 작동하는지 등을 확인한다.
- 테스트를 실행할 때, 실제 데이터가 없으므로 가상으로 만들어진 데이터를 이용한다. 잘 만들어진 가상의 데이터를 통해 실제 데이터로 실행하는 것과 같은 역할을 해주며, 버그/에러/falut 등을 찾아낸다.
- 프로그램 사이즈가 일정 수준 이상 되면 테스트를 잘 만들어도 오류가 생기지 않는다는 보장을 할 수 없다. 테스트는 완벽한 프로그램을 만든다긴 보단 치명적인 오류를 찾아내는 과정이라고 생각해야 한다.
- 테스팅이라는 용어보단 V&V(verification and validation)이라는 용어가 많이 쓰인다.
V&V

Validation testing
- 고객의 요구사항을 만족시키는지 확인하기 위한 테스팅이다.
- 오류를 찾는 테스트가 아니다.
- “소프트웨어가 고객의 실제 요구사항을 만족하는가?”
Verification testing
- 성능이나 동작을 확인하기 위한 테스팅이다.
- 오류를 찾는 테스팅이며, 시스템이 원하는 동작방식으로 동작하는지 확인하는 테스팅이다.
- “소프트웨어가 요구사항 공학을 통해 나온 내용대로 작동하는가?”
V-Model

- 제일 작은 단위인 Unit단위로 먼저 테스트한다.
- Unit단위에서 오류가 없으면 Unit이 여러개 모여서 하나의 기능을 하는 Sybsystem을 테스트한다.
- Subsystem단위에서 오류가 없으면 전체 시스템을 테스트한다.
- 만들어진 전체 시스템은 임시 시스템이다. 고객의 요청사항이나 허락을 받아(alpha, beta test) 실제 프로그램을 출시한다.
- 중간에 고객의 리뷰나 요청을 받아서 각각의 요소들을 수정한다.
V&V confidence
- V&V의 목표는 "시스템이 목적에 맞는가?"를 확인하는 것이다.
- 테스팅을 오랜기간 많이 하는 것은 비용과 시간이 많이 들고 불필요한 과정일 수 있다.
- V&V confidence는 시스템의 보장성으로, 시스템이 문제가 없으며 목적에 맞는지를 말한다.
- V&V confidence는 다음 요소들로 구성되어 있다.
- Software purpose : 소프트웨어가 어떻게 작동하며 치명적인 문제가 없어야 한다.
- User expectations : 고객은 사용하는 소프트웨어에 대해 낮은 이해도를 가지고 있는 경우가 많으므로 예측하지 못한 상황을 대비해야 한다.
- Marketing environment : 시장의 환경을 잘 고려해야 한다. 경쟁사보다 빠르게 프로그램을 만드는 등이 여기 해당한다.
3+1 Axes of V&V

- Optimistic Inaccuracy
- 어느 정도 규모가 있는 프로그램은 잠재적인 오류가 있을 수 밖에 없다.
- 우리는 프로그램이 오류를 가질 수 있다는 것을 인정해야 한다.
- 알파 / 베타 테스트를 거쳐도 오류는 계속해서 나오며, 아직 안 나오고 숨어있는 오류들은 무궁무진하므로, 최대한 줄일려는 노력을 해야지 없애려고 하면 힘들다.
- Example : Testing
- Pessimistic Inaccuracy
- 테스팅은 코드와 가상 데이터를 가지고 어떤 일이 일어나는지 예측한다.
- 프로그램이 실제로는 오류가 없어서 제대로 돌아가는 상황에도 false alarm 때문에 오류가 난다고 할 수 있다.
- 논리적으로는 문제가 없어도, 실제 상황에 들어가면 성능이나 시간 때문에 오류가 생기는 경우가 많다.
- 그러므로 실제 테스트를 통해 오류가 일어나는지 확인해야 한다.
- Example : Automated Program analysis
- Simplified Properties
- 모델의 자율성을 낮추어 확인이 간편하도록 해야 한다.
- Example : Model Checking
- Review
Software Testing Stages
- Development testing : 개발 과정 도중에 테스트를 통해 버그와 오류를 찾아낸다.
- Release testing : 고객에게 배포하기 전에 전문화된 테스트 팀을 통해 시스템의 오류를 찾아낸다.
- User testing : 고객들에게 오류에 대한 정보를 받아 오류를 찾아내고 고친다.

Development Testing
- Unit testing
- 제일 작은 개별의 프로그램인 unit이나 object class를 테스트한다.
- 유닛 테스팅은 각각의 unit이 맡은 기능을 제대로 수행하는지에 집중한다.
- Integrated testing
- unit들이 기능을 수행하는 게 보장되었으면 이들을 합치는 Integrated testing을 수행한다.
- 개별로 잘 작동한다 해서 합치면 많은 문제가 일어날 수 있으므로 합치는 과정이 중요하다.
- System testing
- 위에서 합친 프로그램을 모두 합쳐 하나의 시스템을 만든다.
- 전체적으로 합쳐서 하나의 시스템을 만드는 것을 목표로 한다.
- Regression testing
- 코드를 refactoring하거나 Clean code로 바꾸는 경우에 원래 기능을 똑같이 수행하는지를 확인한다.
- 유지보수 단계에서 수행한다.
Unit testing
- Unit testing은 독립적인 요소들을 전체 시스템에서 고립시켜서 테스트하는 것이다.
- 독립적인 요소(unit)가 기능적으로 잘 작동하는지를 확인한다.
- unit의 종류는 다음과 같다.
- 독립적인 함수
- 변수와 함수를 가진 클래스
- 여러가지 인터페이스(interface)를 사용하는 컴포넌트
- Unit testing은 상태도(state model)를 가지고 하는 경우가 많다.
Automated Testing
- 테스트를 인간이 직접 하는건 너무 복잡하고 어려운 일이다.
- 그러므로 가능하면, unit testing은 자동화(automated)되어야 한다.
- 이를 도와주는 것이 Unit testing frameworks다.
- 일반적인 기능에 대해 테스트 할 수 있다.
- 특별한 상황(오류)에 대해 테스트할 수 있다.
- 만든 모든 테스트를 수행하고, 이에 대한 보고를 내며, 성공적으로 수행될 수 있또록 한다.
- JUnit, xUnit...
- 3가지 과정으로 나뉜다.
- Setup part : 맨 처음 하는 과정으로 test case들을 만들고, input과 output을 설정한다.
- Call part : 함수나 요소를 테스트한다(테스트하도록 부른다).
- Assertion part : 내가 예상한 결과와 테스트 결과를 비교한다. 만약 둘이 같다면 테스트가 성공적으로 진행된 것이고, 다르면 실패한 것이다.
Developing Unit Test Cases
- Unit Test Case는 테스트하는 상황에 따라 2가지로 나뉜다.
- Positive
- 기능대로 동작하는지를 확인한다.
- 내가 짠 프로그램이 원하는 방식으로 동작하는지 확인한다.
- Negative
- 오류를 잘 처리하는지 확인한다.
- 예상하지 못한 input이 들어오거나 overflow등 시스템적인 한계를 마주하면 뒤따르는 오류를 잘 처리하는지를 확인한다.
Unit Testing Strategies
- Partition Testing
- input들의 모둠을 짓고 그에 따라 테스트를 수행한다.

- 예를 들어 4~10사이에 있는 수를 구별하는 프로그램이 있으면 다음을 수행해본다.
- 4보다 작은 수, 4, 4보다 크고 10보다 작은 수, 10, 10보다 큰 수
- 이는 4보다 작은 수 / 4 ~ 10 / 10보다 큰 수 3가지로 모둠지어 테스트를 수행한 것이다.
- Guideline-basefd testing
- 가이드 라인에 따라 테스트를 "잘" 한다.
- 이 가이드 라인은 프로그램에서 발생하는 주된 오류들이 포함된다.
- 또한 개발자가 직접 만들면서 발생했던 오류들을 해결하는 가이드 라인이 추가된다.
- 다시말해, Brute-force testing(막 테스트)하는 것이다.
Integration Testing
- Integration Tesitng은 Unit Testing이 끝나고 나온 component(unit)들을 서로 병합한다.
- 이 과정에서 오류가 생길 가능성이 많으므로 잘 작동하는 지를 테스트한다.

- 컴포넌트들 간에 상호작용하는 것을 중요하게 본다.
- 컴포넌트들의 기능(interface)들이 합쳐져도 잘 작동하는지를 중요하게 본다.
- Intergration Testing은 비슷한 기능들끼리 묶어서 하나의 시스템으로 만드는 것이다.
- 예를 들어 멀티플레이 게임을 만든다 하자.
- 게임의 전투 부분을 합치고, 설정 부분을 합치고, 멀티플레이 부분을 합치고... 등등 각각의 기능들을 유사한 기능끼리 합친다.
System Testing
- System testing은 Integration Testing으로 만든 기능들을 하나로 합쳐서 최종 시스템을 만든다.
- 이미 만들어진 기능을 다시 확인하는 것은 하지 않는다. 왜냐하면 Unit test, Integrating test에서 기능이 보장되어야만 System testing으로 오기 때문이다.
- 그렇기에 각각의 부분이 어떻게 작동하는지는 중요하지 않으며, input을 넣었을 때 원하는 output이 나오는 것만 본다.
- 이들을 병합하는 것은 쉬울수도 있고, 어려울 수도 있다.
- 어떤 시스템은 각각의 기능들이 연결 부분이 많이 없어 로봇의 각 부분처럼 붙이기만 하면 된다.
- 혹은 어떤 시스템은 기능끼리 소통하는 부분이 많아 로봇의 전선을 연결하고 납땜질을 해야할 수 있다.
Regression Testing
- 코드는 오류 수정이나 성능 향상을 위해서 변경될 때가 있다.
- 코드가 변경되면, 이에 영향을 받는 모든 주변 기능은 작동이 달라질 수 있다.
- 어떤 코드가 변경되도 영향을 받지 않는다.
- 어떤 코드가 변경되면 영향을 받지만, 똑같이 동작한다.
- 어떤 코드가 변경되면, 동작이 달라진다.
- 이에 따라 코드가 변경되면 주변 기능이 동일하게 작동하는지 테스트해야 한다. 이를 Regression Testing이라고 한다.
- Regression Testing은 비용이 비싸지만, 자동화된 시스템을 사용하기 때문에 간단하다.
- Regression Testing의 비용이 비싸므로, 범위를 정해서 테스트하는 방법이 있다. 비용을 줄일 수 있지만, 범위가 축소되므로 확실하지 않을 수 있다.
Test-Driven Development
- Test-Driven Development(TDD)는 개발을 어떻게 해야 할 지 알려주는 개발 방법론이다.
- 지금까지는 코드(Unit)를 먼저 만들고 테스트를 통과할 때 까지 고쳤다.
- TDD는 코드를 구현하기 전 Test Case를 먼저 만드는 개발 방법이다.
- 아무것도 없는데 Test Case를 먼저 만드는 것은 힘드므로, Specification에 대한 이해도가 높아야 하며 코드에 대한 대략적인 구상을 해야한다.
- TDD가 된다고 TFD가 되는 건 아니다.

- TDD를 사용함으로써 얻는 이득은 다음과 같다,
- 모든 작성될 코드는 작성한 테스트를 통과해야 하므로 모든 코드가 적어도 하나의 테스트를 통과하게 된다.
- 테스트를 기반으로 코딩했으므로 Test 자동화가 쉽게 완료되며 이에 따르는 Regression Testing이 쉬워진다.
- 코드를 짜면 바로 테스트를 하기 때문에 Debugging하는 것이 쉬워진다.
- 코드가 무엇을 해야하는지를 테스트로 구현해놓았기 때문에 문서로 작성하기 쉽다.
Release Testing
- Release Testing은 사용자에게 직접 주기 전에 해보는 Testing을 의미한다.
- 대부분 Testing Team이 있으며, 그만큼 Release Testing은 중요하다.
- Black-box Testing은 사용자가 직접 사용할 기능들을 가지고 안에 구조는 보지 않은채 테스트를 한다.
- White-box Testing은 구조를 파악하고 구조에 맞는 테스트를 한다.
- 대부분 Black-box Testing을 많이 하는데, 구조를 몰라도 되며 사용자가 할 만한 행동들이 대부분이므로 사용자 친화적인 Testing이기도 하다. 그렇기에 negative testing과도 비슷한 부분이 있다.
Release Testing vs. System Testing
- Release Testing은 System Testing의 종류 중 하나이다.
- Systme Testing은 개발 팀에서 구조를 보면서 버그를 찾아내기 위함이다.
- Release Testing은 어떤 상황에도 대응이 되어야 하며, 사용자가 사용하기 좋아야 함을 기반으로 한다.
- Release Testing은 성능 테스트나 스트레스 테스트를 진행한다.
- 성능 테스트는 시스템이 요구하는 최소 성능을 확인하는 것이며, 최소 성능이 높으면 범용성이 떨어지므로 최소 성능을 낮추어야 한다.
- 스트레스 테스트는 시스템이 사용자에게 좋지 않는 경험을 주는 것으로, 버퍼링이나 렉 같은 요소들이 해당된다. 이는 사용자 경험에 좋지 않은 영향을 주므로 빠르게 개선해야한다.
User Testing
- User / Customer testing은 시스템을 필요한 사용자에게 제공하며 테스트해보는 것이다.
- 개발자나 테스트 팀이 아닌 실제 사용자의 테스트이므로, 여러 환경이나 요소들에 대한 정보를 수집할 수 있으므로 도움이 된다.
- 또한 사용자 PC나 여러 환경들에 설치되어 있는 프로그램과의 충돌들도 발견해 낼 수 있어 여러모로 이점이 있다.
- 인터넷 기반의 시스템이 User Testing을 많이 한다.
- User Testing의 종류는 다음과 같다.
- Alpha Testing : 유저가 개발자의 site(인터넷 사이트나, 개발자의 개발 환경, 테스트벤치 등...)에 접속해서 테스트한다.
- Beta Testing : 시스템을 발매하고 유저가 직접 받아서 자신의 환경에서 테스트한다.
- Acceptance Testing :