paint-brush
테스트 알고리즘 개선: 소프트웨어 테스팅의 수학적 접근 방식~에 의해@shad0wpuppet
23,888 판독값
23,888 판독값

테스트 알고리즘 개선: 소프트웨어 테스팅의 수학적 접근 방식

~에 의해 Konstantin Sakhchinskiy7m2024/01/24
Read on Terminal Reader
Read this story w/o Javascript

너무 오래; 읽다

이 기사에서는 테스트 방법론을 살펴보고 코드 적용 범위 최적화에서 수학적 모델의 역할을 강조합니다. 논리식 최소화, 쌍별 테스트 최적화, 알고리즘을 사용하여 시스템 상태 변경 테스트에 대해 설명합니다. 주요 결론은 최소한의 노력으로 최대 테스트 범위를 달성하는 데 있어 이러한 방법의 효율성을 강조합니다. 이러한 알고리즘을 다양한 시스템에 적용하는 데에는 어려움과 통찰력이 있습니다. 효과적인 테스트를 위해서는 이론적 기초를 이해하는 것이 중요합니다.
featured image - 테스트 알고리즘 개선: 소프트웨어 테스팅의 수학적 접근 방식
Konstantin Sakhchinskiy HackerNoon profile picture
0-item

새로운 테스트 설계 방법론이 항상 동시에 나타나는 것은 아닙니다. 현대 테스트 방식의 상당 부분은 수학적 모델을 적용하는 세심한 이론 및 실험 작업을 통해 발전해 왔습니다. 좋은 테스터가 되기 위해 수학자일 필요는 없지만 테스트 방법의 이론적 기초를 이해하는 것이 도움이 될 수 있습니다.

커버리지 최대화 및 테스트 케이스 수 최소화

수학적 논리를 적용하여 시스템의 코드 적용 범위를 최적화할 수 있습니다. 조건에 두 개의 분기와 긴 논리 공식이 포함된 "if" 문이 있는 간단한 예를 살펴보겠습니다.

 if ( (& a2) & (!(a2 || a4) ) || a3 ) { # action 1 } else { # action 2 }


두 가지를 모두 다루려면 공식의 구조를 이해하는 것이 필요합니다. 어떤 사람은 무엇을 할 수 있는지 궁금할 것입니다. 언제든지 이 코드 조각(논리적 공식)을 철저하게 테스트하여 16개의 테스트를 수행할 수 있습니다. 하지만 이는 꽤 많은 양이므로 테스트 횟수를 줄이기 위한 노력이 필요합니다. MC/DC(Modified Condition/Decision Coverage) 방법을 사용하면 테스트 횟수를 줄일 수 있습니다(11~12개 테스트 생성). 위험 테스트에 분기 적용 범위가 충분하다면 두 가지 테스트만 필요하지만 어떤 테스트인지는 확실하지 않습니다.


이 문제를 해결하기 위해 논리식에 부울 대수학을 적용할 수 있습니다.

 if( (& a2) & (! (a2 || a4) ) || a3 ) = = ( (& a2) & ( (!a2 || !a4) ) || a3 ) = = ( a1 & a2 & !a2 & !a4 || a3 ) = = 0 || a3 = a3


원래 공식을 변환한 후에는 단 하나의 변수 a3 만이 실제로 진리값에 영향을 미친다는 것이 분명해졌습니다. 결과적으로 테스트 사례를 얻는 것이 더 간단해집니다(하나는 a3 == false 로, 다른 하나는 a3 == false 로). 더욱이 하나의 변수에만 의존하여 복잡한 논리식을 갖는 것이 이상하기 때문에 코드가 최적화되지 않았다는 것이 분명해집니다. 불행하게도 이러한 상황은 실제로 매우 흔하며 제공된 예는 비교적 간단합니다.


결론적으로:

  • 철저한 테스트를 사용하는 경우 2개의 테스트

  • MC/DC 방법을 사용한 2가지 테스트

  • Branch Coverage가 적용되는지 2번 테스트


일반적으로 논리식은 대수학, 수학적 방법, 알고리즘을 사용하여 단순화(최소화)할 수 있습니다. 적어도 세 가지 유사한 방법이 있습니다. 위에서 설명한 대로 부울 대수를 사용한 직접 변환은 항상 작동합니다. 수학과 논리뿐만 아니라 해당 도메인의 특성에 의존하여 특정 도메인의 특성을 고려한 표현 최소화 방법을 찾아 적용할 수 있습니다.

쌍별 테스트 최적화

쌍별 테스트 방법은 철저한 테스트(시간이 많이 걸리고 리소스 집약적일 수 있음)를 통해 입력 매개변수의 가능한 모든 조합을 테스트하는 대신 각 매개변수 값이 모든 매개변수 값과 결합되도록 테스트 세트를 설계하는 방식으로 테스트 세트를 생성하는 것입니다. 테스트된 다른 매개변수의 값을 한 번 이상. 이렇게 하면 테스트 사례 수가 크게 줄어듭니다.


잘 정립되어 자주 사용되는 방법입니다. 그러나 불행하게도 시스템이 더욱 복잡해짐에 따라 이 방법이 항상 작동하는 것은 아닙니다. 질문이 생깁니다: 수많은 입력 매개변수가 있는 복잡한 시스템을 철저하게 테스트하는 데 쌍별 테스트가 충분한가요? 이 질문은 미국 국립표준기술연구소(NIST)를 비롯한 많은 테스트 전문가와 연구자들의 흥미를 끌었습니다.

  • Pairwise finds 65-97% of errors
  • 3-way finds 89-99% of errors
  • 4-way finds 96-100% of errors
  • 5-way finds 96-100% of errors
  • 6-way finds 100% of errors

연구에 따르면 쌍별 검정에서는 65~97%의 사례에서 오류를 발견합니다. 매개변수 쌍이 아닌 3배나 4배의 결합을 시작하면, 즉 k-way 테스트를 사용하면 더 많은 수의 테스트를 얻을 수 있지만 더 많은 오류를 포착할 수도 있습니다.


예를 들어, 시스템에 각각 3개의 값을 갖는 2개의 매개변수와 각각 2개의 값을 갖는 3개의 매개변수가 있다고 가정합니다.

  • Pairwise: 10 tests with 14% coverage
  • 3-way: 18 tests with 25% coverage
  • 4-way: 36 tests with 50% coverage
  • 5-way: 72 tests with 100% coverage

만족스러운 수준의 테스트 적용 범위와 허용되는 테스트 사례 수를 선택할 수 있습니다.

쌍별의 기초는 n-튜플(쌍, 삼중, 사중, ...) 값을 동일한 횟수로 포함하는 직교 배열입니다.


쌍별 및 k-방향 테스트의 일반적인 기반은 OA(N, V^k, t) 입니다. 여기서:

  • N은 행 수입니다.

  • k는 열 수입니다.

  • V는 열에 있는 서로 다른 값의 수입니다.

  • t는 강도입니다(쌍별 경우 t=2).


OA에서 각 t 열 집합에는 모든 t 튜플이 동일한 횟수만큼 포함됩니다.

직교행렬 대신 커버행렬을 사용하는 것이 더 좋습니다. 이러한 행렬은 각 값 집합이 "동일한 횟수"가 아닌 적어도 한 번 발생한다는 점에서 직교 행렬과 다릅니다. 이 경우에는 테스트 수가 약간 적습니다. 행렬을 포함하면 잘못된 테스트 사례가 발생할 수 있지만 전반적으로 테스트 프로세스가 훨씬 빠릅니다. 따라서 테스트 프로세스가 크게 단순화되었습니다.

CA(N, V^k, t), 여기서:

  • N은 행 수입니다.
  • k는 열 수입니다.
  • V는 열에 있는 서로 다른 값의 수입니다.
  • t는 강도입니다(쌍별 경우 t=2).

CA에서 각 t 열 집합에는 모든 t 튜플이 적어도 한 번 포함됩니다. 커버링 행렬을 사용하면 테스트 수를 크게 늘리지 않고도 쌍별 테스트에서 k-방향 테스트로 이동할 수 있습니다.

시스템 상태 및 시스템 상태 변경 테스트

일반적으로(거의 항상) 시스템에는 "작동 중"과 "작동하지 않음"이라는 두 가지 이상의 상태가 있습니다. 재고 주문이 있는 주의 일부를 고려해 보겠습니다. 주식을 사고 파는 주문은 거래가 완료되기 위해 일련의 상태를 거쳐야 합니다. 먼저 주문이 생성된 후 거래소를 통해 확인된 후 수많은 소액 매수 거래가 이루어지고 마지막으로 필요한 수량만큼의 주식이 매수 또는 매도됩니다. 주식 주문의 모든 상태는 거래 시스템에 반영되며, 물론 모든 전환과 상태도 테스트되어야 합니다.


거의 항상 모든 상태 또는 모든 전환이 테스트되지만 둘 다 확인되는 경우가 더 많습니다. 전체 적용 범위를 달성할 수 있지만 시간과 비용이 많이 들고 리소스 집약적입니다.


그래프와 유한 오토마타

여행하는 세일즈맨(commi voyager) 문제와 de Bruijn 알고리즘을 고려해 보겠습니다. 알고리즘을 통해 그래프에서 탐색하여 완전히 포괄할 수 있는 최적 또는 충분히 최적의 짧은 경로 집합을 얻을 수 있다는 점을 이해하는 것만으로도 충분합니다. 엄밀히 말하면 유사한 작업을 수행하는 다른 알고리즘을 사용할 수 있거나 다음을 발명할 수 있습니다. 사용자 정의 알고리즘).

  • 먼저, 시스템의 초기 상태를 취하고 정점이 원본 그래프의 전환에 해당하는 새 그래프를 만듭니다.
  • 다음으로, 새 그래프의 꼭지점, 즉 이전 그래프의 전환을 다룹니다.
  • 일부 경로는 명확하고 매우 짧습니다(시스템 상태 및 전환을 테스트하는 데 매우 편리함).
  • 계속해서 다른 경로를 구축하세요. 결과적으로 너무 길어질 수 있습니다(그리고 좋지 않습니다).


상황을 분석하기 위해 다음 예를 고려해 보겠습니다.

테스터는 3명입니다. 첫 번째는 첫 번째 테스트를 수행하고 두 번째는 두 번째 테스트, 세 번째는 세 번째 테스트를 수행합니다. 처음 두 개는 경로가 짧기 때문에 처음 두 테스트를 매우 빠르게 완료하지만(세 번째 테스트에 비해 처음 두 경로가 짧기 때문에) 마지막 테스트는 매우 오랜 시간이 걸립니다(세 번째 경로가 매우 길기 때문에). 긴).

de Bruijn 알고리즘이 적용되면 세 번째 시퀀스를 여러 개의 짧은 시퀀스로 "절단"할 수 있으며 모든 테스트의 실행을 효율적으로 병렬화할 수 있습니다.


더 많은 테스트로 끝날 수 있지만 병렬 실행의 경우 테스트가 더 짧기 때문에 테스트가 훨씬 빨리 완료됩니다.


또한 테스트가 많을수록 실행 유연성도 높아집니다. 모든 테스트를 동시에 실행할 수도 있고, 흥미롭지 않고 덜 중요한 테스트를 제거할 수도 있습니다. 시스템의 가장 중요한 상태를 통과하는 테스트에 더 높은 우선순위를 할당할 수 있습니다. 알고리즘 결과를 활용하는 방법에는 여러 가지가 있습니다.


게다가 알고리즘은 도메인별 항목을 사용하지 않습니다. 이는 시스템의 완전히 추상적인 상태와 전환과 함께 작동합니다.


이 기술에서는 알고리즘이 어떻게 사용되는지에 따라 많은 것이 달라집니다. 가장 극단적인 경우, 테스터는 상태 간 전환 뒤에 숨은 논리에 대해 전혀 알지 못할 수도 있습니다. 이러한 상황에서 상태 전환의 긴 체인은 알고리즘에 의해 여러 개의 짧은 체인으로 "절단"됩니다. 이러한 체인 중 일부는 의미가 없는 것으로 판명될 수 있습니다. 따라서 획득한 체인은 합리성과 테스트에 중요하고 의미 있는 체인을 평가해야 합니다. 무의미하고 중요하지 않지만 시스템 상태를 변경하는 가능한 경로를 통해 시스템의 어느 부분에 수정이 필요한지 이해할 수 있으며 정확히 어느 부분이 명확해질 것입니다.


주요 결론은 다음과 같이 고려될 수 있습니다:


  • 논리식을 최소화하는 알고리즘은 최소한의 노력으로 최대 테스트 범위를 제공합니다. 최소화 알고리즘을 사용하는 것이 항상 필요한 것은 아닙니다. 때로는 시간 낭비입니다. 보편적인 접근 방식이 존재합니다.
  • 병렬화, 자동화, 유연성 및 독립성이 용이한 짧은 테스트 사례의 작은 세트를 통해 완전한 테스트 적용 범위를 달성할 수 있습니다.
  • 실제 조건에서 애플리케이션 사용에 대한 통계 분석을 통해 기존 테스트 설계 기술을 최적화 및 적용하고 필요한 테스트 적용 범위를 달성하여 애플리케이션 품질을 보장할 수 있습니다.
  • 쌍별 테스트를 수정하면 표준 알고리즘보다 더 넓은 테스트 범위와 거의 동일한 리소스를 사용하여 더욱 심층적인 테스트가 가능해집니다.
  • 일부 알고리즘은 표준 테스트 설계 기술이 덜 효율적인 경우에 효과적일 수 있습니다.
  • 조합 테스트 설계 기술의 실패 에는 몇 가지 문제가 있습니다.
  • 획득된 알고리즘은 다양한 시스템에 쉽게 적용할 수 있으며 도메인에 대한 특별한 지식이 필요하지 않습니다.


사소한 단점에 대해서는 주목할 가치가 있습니다.


  • 일부 알고리즘은 효과적이지만 모든 경우에 관련되는 것은 아닙니다. 많은 상황에서 표준 테스트 설계 기술은 동일하거나 때로는 훨씬 더 효과적입니다.
  • 알고리즘을 적용하려면 약간의 수학적 지식이 필요하고 때로는 적용에 더 많은 시간이 필요하므로 이는 많은 상황에서 중요한 요소가 될 수도 있습니다.

QA 전문가로서 이러한 미묘한 차이를 이해하는 것이 중요합니다. 어떤 경우에는 이론적이지만 조합 테스트 설계 기술의 복잡성을 이해하면 QA 전문가가 앱의 복잡한 비즈니스 로직을 효과적으로 테스트하고 사용자에게 고품질 소프트웨어를 제공할 수 있습니다.