소프트웨어 테스팅에 대한 공식 / 수학 이론이 있습니까?


12

인터넷 검색 "소프트웨어 테스팅 이론"은 단어의 부드러운 의미에서 이론을 제공하는 것 같습니다. 나는 수학적, 정보 이론적 또는 다른 과학 분야의 의미에서 이론으로 분류 할 수있는 것을 찾을 수 없었습니다.

내가 찾고있는 것은 테스트가 무엇인지, 사용 된 개념, 테스트 케이스가 무엇인지, 테스트 가능성, 테스트 실용성, 테스트 대상 범위, 공식 정의 / 설명을 공식화하는 것입니다. 코드 커버리지 등

업데이트 : 또한 공식 검증과 내가 요청한 것 사이의 연결에 대해 직관적으로 확실하지 않지만 분명히 어떤 종류의 연결이 있습니다.


1
소프트웨어 테스트는 매우 중요하지만 (예 : 단위 테스트 실시) 이론에는 항상 약간의 문제가 있습니다. 이 고전적인 예를 생각해 봅시다 . 수학 선생님 double pihole(double value) { return (value - Math.PI) / (value - Math.PI); }에게서 배웠습니다 . 이 코드에는 정확히 하나의 구멍 이 있으며 블랙 박스 테스트만으로는 자동으로 검색 할 수 없습니다. 수학에는 그런 구멍이 없습니다. 미적분학에서는 한쪽 한계가 같으면 구멍을 닫을 수 있습니다.
rwong

4
- 이것은 당신이 찾고있는 무엇의 일부가 될 수 en.wikipedia.org/wiki/Formal_verification
enderland

1
@enderland의 제안에 이어 두 번째입니다. 테스트에 대한 접근 방식이 얼마나 엄격한지는 중요하지 않습니다. 일부 버그는 여전히 균열을 극복하고 테스트를 통해 더 많은 코드를 다루면 새로운 버그를 찾는 데 드는 비용이 증가합니다. 이것이 아마도 테스트 개념을 공식화하는 데 어려움을 겪지 않은 사람이있는 이유 일 것입니다. "휴리스틱"접근 방식은 교육 수준이 낮 으면 거의 효과가 있습니다.
Doval

나는 의존 유형을 통해 공식 검증의 땅에 익숙해졌으며 @Doval과 enderland에 완전히 동의 할 수 있습니다.
Erik Kaplun

1
@rwong 분자와 분모가 모두 0이 될 가능성을 암시한다고 가정합니다. 부분적으로 문제는이 기능의 설계가 잘못 되었기 때문입니다. 수학적 공식 검증에 대해 이야기 할 때는 올바른 데이터 유형에 따라 함수를 임의로 작성하지 않고 공식 규칙을 따라야합니다. 이 예제에서는 올바르게 작성하려면 나누기 함수를 사용해야합니다.이 함수 (a,b)=>a/b는 오버플로 값으로 확장해야합니다.
Dmitri Zaitsev

답변:



5

나는 좋은 온라인 자료 (이 주제에 관한 영어 위키 백과 기사는 개선 될 수없는 경향이 있음)를 가리킬 수 없지만, 기본적인 테스트 이론을 다루는 강의를 요약 할 수 있습니다.

테스트 모드

단위 테스트 또는 통합 테스트 와 같은 다양한 테스트 클래스가 있습니다 . 단위 테스트는 일관성있는 코드 조각 (함수, 클래스, 모듈)이 예상대로 작동한다고 주장하는 반면 통합 테스트는 그러한 여러 조각이 올바르게 함께 작동한다고 주장합니다.

테스트 사례는 특정 테스트 입력을 사용하거나 다른 클래스를 조롱하여 코드 조각이 실행되는 알려진 환경 입니다. 그런 다음 코드의 동작을 예상 된 동작 (예 : 특정 반환 값)과 비교합니다.

테스트는 버그의 존재 만 증명할 수 있으며 모든 버그가없는 것은 아닙니다. 테스트는 프로그램 정확성에 상한을 두었습니다 .

코드 범위

코드 커버리지 메트릭을 정의하기 위해 소스 코드를 각 노드에 코드의 선형 세그먼트가 포함 된 제어 흐름 그래프 로 변환 할 수 있습니다 . 제어는 각 블록의 끝에서만 이러한 노드 사이를 흐르며 항상 조건부입니다 (조건 인 경우 노드 A로 이동하고 그렇지 않으면 노드 B로 이동). 그래프 갖는 하나 개의 시작 노드와 하나 개의 엔드 노드.

  • 이 그래프에서 명령문 범위 는 모든 방문한 노드 대 모든 노드의 비율입니다. 완전한 진술 범위는 철저한 테스트에 충분하지 않습니다.
  • 분기 범위 는 CFG의 노드 간 방문 된 모든 에지 대 모든 에지의 비율입니다. 루프 테스트가 불충분합니다.
  • 경로 적용 범위 는 모든 방문 경로와 모든 경로의 비율이며, 여기서 경로는 시작부터 끝 노드까지의 모든 가장자리 시퀀스입니다. 문제는 루프를 사용하면 무한한 수의 경로가있을 수 있으므로 전체 경로 적용 범위를 실제로 테스트 할 수 없다는 것입니다.

따라서 조건 범위 를 확인하는 것이 종종 유용합니다 .

  • 에서 간단한 조건 범위 , 각 원자 상태는 한 번 true와 false 번이다 - 그러나 이것은 전체 문장 커버리지를 보장하지 않습니다.
  • 에서 여러 조건 범위 , 원자 조건의 모든 조합에 촬영 한 truefalse. 이는 전체 지점 범위를 의미하지만 다소 비쌉니다. 프로그램에는 특정 조합을 제외시키는 추가 제한 조건이있을 수 있습니다. 이 기술은 브랜치 커버리지를 얻는 데 유용하고 데드 코드를 찾을 수 있지만 잘못된 조건 에서 발생하는 버그는 찾을 수 없습니다 .
  • 에서는 최소한의 여러 조건에 따르면 , 각각 원과 합성 조건은 참과 거짓 번이다. 여전히 전체 지사 범위를 의미합니다. 여러 조건 범위의 하위 집합이지만 테스트 사례가 더 적습니다.

조건 범위를 사용하여 테스트 입력을 구성 할 때는 단락을 고려해야합니다. 예를 들어

function foo(A, B) {
  if (A && B) x()
  else        y()
}

요구 사항은 테스트 할 foo(false, whatever), foo(true, false)그리고 foo(true, true)완벽하게 최소한의 여러 조건 적용.

여러 상태에있을 수있는 객체가있는 경우 흐름 제어와 유사한 모든 상태 전이를 테스트하는 것이 합리적입니다.

좀 더 복잡한 범위 메트릭이 있지만 일반적으로 여기에 제시된 메트릭과 유사합니다.

이들은 화이트 박스 테스트 방법이며 부분적으로 자동화 할 수 있습니다. 단위 테스트 스위트는 선택한 메트릭 으로 높은 코드 적용 범위를 목표로 하지만 100 %가 항상 가능한 것은 아닙니다. 특정 위치에 결함을 주입해야하는 예외 처리를 테스트하는 것은 특히 어렵습니다.

기능 테스트

그런 다음 구현을 블랙 박스로보고 코드가 사양을 준수 하는지 확인 하는 기능 테스트 가 있습니다. 이러한 테스트는 단위 테스트 및 통합 테스트 모두에 유용합니다. 가능한 모든 입력 데이터로 테스트 할 수 없기 때문에 (예 : 가능한 모든 문자열로 문자열 길이 테스트) 입력 (및 출력)을 동등한 클래스로 그룹화하는 것이 유용합니다 (올 length("foo")바르면 올바른 경우 ) foo("bar"). 입력과 출력 동등성 클래스 사이의 각 가능한 조합에 대해, 하나 이상의 대표 입력이 선택되고 테스트됩니다.

추가로 테스트해야합니다

  • 에지의 경우 length(""), foo("x"), length(longer_than_INT_MAX),
  • 언어에 의해 허용 아닌 함수의 계약에 의해되는 값 length(null), 및
  • 가능한 정크 데이터 length("null byte in \x00 the middle")...

숫자를 사용하면 이는 테스트를 의미 0, ±1, ±x, MAX, MIN, ±∞, NaN하고 부동 소수점 비교는 두 개의 인접 플로트를 테스트합니다. 또 다른 추가로, 등가 클래스에서 무작위 테스트 값을 선택할 수 있습니다. 디버깅을 쉽게하려면 사용 된 시드를 기록해 두는 것이 좋습니다.

비 기능 테스트 :로드 테스트, 스트레스 테스트

소프트웨어에는 작동하지 않는 요구 사항이 있으므로 테스트해야합니다. 여기에는 정의 된 경계에서의 테스트 (부하 테스트)와 그 너머 (스트레스 테스트)가 포함됩니다. 컴퓨터 게임의 경우, 이것은로드 테스트에서 초당 최소 프레임 수를 주장 할 수 있습니다. 예상보다 두 배나 많은 방문자가 서버를 공격하는 경우 응답 시간을 관찰하기 위해 웹 사이트에 스트레스 테스트를 수행 할 수 있습니다. 이러한 테스트는 전체 시스템뿐만 아니라 단일 엔터티와도 관련이 있습니다. 해시 테이블이 어떻게 백만 항목으로 저하됩니까?

다른 종류의 테스트는 시나리오가 시뮬레이션되는 전체 시스템 테스트 또는 개발 계약이 이행되었음을 입증하는 승인 테스트입니다.

비 테스트 방법

리뷰

품질 보증에 사용할 수있는 비 테스트 기술이 있습니다. 연습, 공식 코드 검토 또는 페어 프로그래밍이 그 예입니다. 일부 부품은 자동화 될 수 있지만 (예 : 린터 사용) 시간이 많이 소요됩니다. 그러나 숙련 된 프로그래머의 코드 검토는 높은 버그 발견 속도를 가지며 자동화 된 테스트가 불가능한 설계 중에 특히 유용합니다.

코드 검토가 너무 좋은데 왜 여전히 테스트를 작성합니까? 테스트 스위트의 가장 큰 장점은 (대부분) 자동으로 실행될 수 있으며 회귀 테스트에 매우 유용하다는 것입니다 .

공식 검증

공식적인 확인은 가고 증명 코드의 특정 속성을. 수동 검증은 대부분 중요 부품에 대해 실행 가능하며 전체 프로그램에 대해서는 덜 유효합니다. 증명은 프로그램 정확성에 하한을 둡니다. 예를 들어 정적 유형 검사기를 통해 증거를 어느 정도 자동화 할 수 있습니다.

assert명령문 을 사용하여 특정 불변량을 명시 적으로 확인할 수 있습니다 .


이러한 모든 기술은 그 자리에 있으며 보완 적입니다. TDD는 기능 테스트를 미리 작성하지만 일단 코드가 구현되면 커버리지 메트릭으로 테스트를 판단 할 수 있습니다.

테스트 가능한 코드 작성은 개별적으로 테스트 할 수있는 작은 코드 단위를 작성하는 것을 의미합니다 (적절한 세분성, 단일 책임 원칙을 가진 도우미 기능). 각 함수의 인수가 적을수록 좋습니다. 이러한 코드는 또한 예를 들어 의존성 주입을 통해 모의 객체를 삽입하는 데 적합합니다.


2
나는 정교한 대답을 주셔서 감사합니다,하지만 난 그것이 내가 질문 :하지만과는 거의 무관 두려워, 운이 좋게, programmers.stackexchange.com/questions/78675/...는 그것이 내가 무엇에수록 가까운 것 같다 목표로.
Erik Kaplun

이것은 좋은 물건입니다. 책이나 물건을 추천 해 줄 수 있습니까?
Marcin

4

아마도 "사양 기반 테스트"도 귀하의 질문에 답변합니다. 이 테스트 모듈을 확인하십시오 (아직 사용하지 않은). 선택한 단일 데이터 값을 사용하여 단위 테스트를 작성하지 않고 수학 표현식을 작성하여 테스트 값 세트를 지정해야합니다.

테스트 :: Lectrotest

필자가 말했듯이이 Perl 모듈은 Haskell의 Quick-Check Module에서 영감을 받았습니다 . 이 페이지에 더 많은 링크가 있는데 그 중 일부는 죽었습니다.


2

수학적 기반 접근법 중 하나는 모든 쌍 테스트 입니다. 아이디어는 대부분의 버그가 단일 구성 옵션 선택에 의해 활성화되고 나머지는 대부분 특정 옵션 쌍에 의해 동시에 활성화된다는 것입니다. 따라서 대부분의 "모든 쌍"을 테스트하여 잡을 수 있습니다. 수학적 설명 (일반화)은 다음과 같습니다.

AETG 시스템 : 조합 설계를 기반으로 한 테스트 방법

(더 많은 참조가 있습니다)


2

사용되는 수학 방정식이 있지만 사용중인 소프트웨어 테스트 유형에 따라 다릅니다. 예를 들어, 치명적 결함 가정 에서는 실패가 2 개 이상의 동시 결함으로 인한 것이 아니라고 가정 합니다. 다음 방정식은 다음과 같습니다. f = 4n + 1. f = 주어진 변수 수에 대한 테스트 사례 수를 계산하는 함수 ( n) + 1 은 모든 변수가 공칭 값을 가정하는 상수를 더한 것입니다.

수학 방정식이 필요한 또 다른 유형의 테스트는 견고성 테스트 (Robustness Testing )로 테스트 프로세스에서 테스트 사례의 견고성 또는 정확성을 테스트하는 것입니다. 이 테스트에서는 합법적 인 입력 범위 내의 변수를 입력하고 (정확한 테스트 사례) 입력 범위 밖의 변수를 입력합니다 (더러운 테스트 사례). 다음 수학 방정식을 사용합니다 : f = 6n + 1 . 6n 은 각 변수가 6 개의 다른 값을 가정하고 다른 값은 공칭 값을 가정해야 함을 나타냅니다. * + 1 *는 상수 1의 추가를 나타냅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.