단위 10 / 11

거짓 신뢰 위험, 테스트 품질 및 돌연변이 테스트: 테스트 테스트

이득:

  • 유사 신뢰의 세 가지 측면(비주장적, 자기주장적, 사소한 주장)을 인식하고 이에 대한 해독제를 적용하는 능력
  • 도구나 손으로 적용하는 비율보다 더 정확한 품질 측정 방법으로 돌연변이 테스트 및 돌연변이 점수를 사용할 수 있는 기능
  • 칭찬의 함정에 빠지지 않고 테스트에 맞서 AI를 레드팀으로 포지셔닝하고 테스트의 허점을 찾아내는 능력

이 모듈의 핵심은 반복되는 경고입니다. 녹색으로 빛나는 테스트 패널은 품질의 증거가 아닙니다. 테스트를 통해 자신감을 얻었다면 그 자신감이 진짜인지 가짜인지 알아야 합니다. 인공지능(AI) 시대에 이 질문은 그 어느 때보다 중요합니다. 왜냐하면 AI는 유연하고 매끄럽게 보이지만 공허한 테스트를 생성하는 데 능숙하기 때문입니다. 잘못된 확신, 즉 테스트가 친환경적이기 때문에 소프트웨어가 정확하다고 믿는 것인데 실제로는 테스트에서 아무 것도 확인되지 않는 것이 QA 팀에 일어날 수 있는 가장 위험한 일입니다. 오류가 없다는 것이 아니라 오류를 볼 수 없다는 것을 숨기기 때문입니다. 이 단원은 전체 모듈의 검증 철학을 하나의 분야, 즉 테스트 테스트로 통합합니다.

테스트 품질 측정을 위한 표준: 돌연변이 테스트

테스트가 실제로 보호하는지 여부를 이해하는 가장 강력한 방법은 돌연변이 테스트(돌연변이 테스트 - 소스 코드에서 의도적인 작은 왜곡/돌연변이를 생성하고 테스트에서 이러한 왜곡을 감지하는지 여부를 측정하는 기술)입니다. 논리는 간단합니다. 의도적으로 코드를 분리하면(+를 -로, a >를 >=로, true를 false로) 좋은 테스트 스위트는 해당 손상을 포착하고 빨간색으로 변합니다. 그렇지 않은 경우 해당 중단은 살아남은 돌연변이이므로 테스트가 실제로 해당 동작을 보존하지 않습니다.

돌연변이 점수 = 돌연변이 사멸 / 전체 돌연변이. 라인 적용 범위가 90%인 패키지의 돌연변이 점수는 40%일 수 있습니다. 이는 라인이 작동하지만 동작이 확인되지 않았음을 나타냅니다. 돌연변이 점수는 적용 범위보다 품질을 훨씬 더 정직하게 측정합니다.

팁: 자동 변형 도구(Java용 PIT/Pitest, JavaScript/TypeScript용 Stryker, .NET용 Stryker.NET, Python용 mutmut)가 있습니다. 이들은 자동으로 수백 개의 돌연변이를 생성하고 테스트합니다. 도구가 없다면 수동으로 "코드 테스트를 중단하는" 방법도 중요한 기능에 매우 중요합니다.

사이비 신뢰의 세 가지 얼굴과 그 해독제

의사 신뢰 형식

증상

해독제

어설션 없이 테스트

코드는 작동하지만 아무것도 검증되지 않았습니다.

모든 테스트에서 True를 주장합니다. 돌연변이로 테스트

자가 확인 테스트

예상 = 코드 출력

기대값을 독립적으로 계산

사소한 주장

"null이 아님", "200이 반환됨"

비즈니스 규칙/실제 결과 검증

높은 범위의 오류

90% 라인, 낮은 보호

돌연변이 점수를 살펴보세요

깨지기 쉬운 테스트 내성

"또 막혔어, 패스"

근본 원인 + 결정론적 테스트

AI를 '레드팀'으로 활용

AI는 의사 신뢰를 생성할 수도 있고 이를 추적하는 데 있어 강력한 동맹자가 될 수도 있습니다. 자신의 테스트에 맞서 AI를 레드팀으로 활용하세요. "이 테스트를 통과했지만 잘못된 코드를 작성하세요" 또는 "이 테스트를 속일 전복을 찾아보세요"라고 질문하세요. AI가 테스트에서 허점을 발견하면 해당 허점은 실제 위험이 됩니다.

주의: AI에게 "내 테스트 품질이 좋은가?"라고 묻지 마세요. "예, 훌륭합니다"라는 대답을 확신으로 받아들입니다. AI는 친절한 경향이 있습니다. 대신 AI에게 "이러한 테스트를 통과하는 버그를 생성하라"는 구체적인 작업을 요구하세요. 오류가 발생할 수 있다면 테스트에서는 해당 오류를 인식할 수 없습니다.

동등한 돌연변이 및 점수의 한계

돌연변이 테스트는 강력하지만 문제가 있습니다. 일부 돌연변이는 코드 동작을 전혀 변경하지 않습니다. 이를 등가 돌연변이(equivalent mutation - 손상된 코드, 원본과 정확히 동일한 결과를 생성하는 돌연변이)라고 합니다. 예를 들어, 한 번도 사용되지 않은 변수의 초기값을 변경해도 출력에는 영향을 주지 않습니다. 어떤 테스트도 이것을 포착할 수 없고 포착해서는 안 됩니다. 따라서 100% 돌연변이 점수는 실제로 달성할 수 없는 경우가 많으며 목표도 아닙니다. 동등한 돌연변이를 손으로 제거하는 것은 노동 집약적입니다. 그러므로 돌연변이 점수를 절대적인 시험 점수로 읽지 말고 "내 테스트가 실제로 보호하는가?"에 대한 정직한 지표로 읽으십시오.

실용적인 접근 방식은 다음과 같습니다. 전체 코드 베이스에 걸쳐 지속적으로 돌연변이 테스트를 실행하는 대신 가장 위험하고 가장 복잡한 비즈니스 규칙이 포함된 모듈에서 실행합니다. 이 모듈에서 살아남은 돌연변이를 하나씩 검사합니다. 실제 차이가 있는 경우 테스트를 추가하세요. 동등한 돌연변이인 경우 정당성을 표시하고 통과시킵니다. AI는 살아남은 돌연변이가 동등한지 여부를 평가하는 초기 스크리닝을 수행할 수 있습니다. 그러나 최종 결정은 코드의 기능을 아는 사용자가 내립니다.

주의: 돌연변이 테스트는 계산 비용이 많이 듭니다(모든 관련 테스트는 각 돌연변이에 대해 다시 실행됩니다). 따라서 일반적이고 합리적인 전략은 모든 병합보다는 중요한 모듈에 대한 주간 또는 출시 전 심층 점검으로 일정을 잡는 것입니다.

약한 프롬프트 / 강한 프롬프트

약함: "내 테스트가 충분합니까?"
Strong: "이 기능과 테스트 스위트에 대해 레드팀으로 활동하십시오. (1) 종료될 수 있는 코드에서 8개의 돌연변이를 생성하십시오(연산자 대체, 경계 이동, 조건 반전, 반환 값 대체). (2) 각 돌연변이에 대해 기존 테스트 중 어떤 것이 이를 포착하고 어떤 것은 포착하지 않을 것인지 표시하십시오. (3) 살아남은 각 돌연변이에 대해 이를 죽이는 새로운 테스트를 작성하십시오. (4) 또한 이러한 테스트를 모두 통과하지만 비즈니스 규칙을 위반하는 코드 예제를 생성할 수 있는지 표시하십시오. 코드+테스트: [붙여넣기]"

강력한 프롬프트; AI를 칭찬 기계가 아닌 시험을 깨는 시험관으로 자리매김합니다.

복사 가능한 템플릿 4개

1) 수동 돌연변이 제어:

이 코드에 대해 산술 연산자 대체, 비교 제한(> vs >=), 논리 반전, 반환/상수 대체, 조건 건너뛰기 등 8개의 중요한 변형(사소한 의도적 중단)을 생성합니다. 각 돌연변이에 대해 사용 가능한 테스트 중 어떤 것이 이를 포착할지 예측합니다. 코드+테스트: [붙여넣기]

2) 살아남은 돌연변이를 죽이는 것:

다음 돌연변이 테스트 보고서에는 살아남은(잡히지 않은) 돌연변이가 포함되어 있습니다: [목록/보고서]. 각각에 대해 해당 돌연변이를 제거하는 최소한의 테스트를 작성하십시오(그런 식으로 깨지면 코드가 빨간색으로 변합니다). 테스트를 통해 확인된 동작에 대해 설명합니다.

3) 레드팀 - 피를 흘리며 테스트하라:

다음 테스트를 모두 통과하지만 비즈니스 규칙 [비즈니스 규칙]을 위반하는 코드를 작성할 수 있습니까? 그렇다면 이 테스트의 어떤 허점이 이를 허용합니까? 해당 허점을 닫을 테스트를 추가하십시오. 테스트: [붙여넣기]

4) 테스트 품질 검사:

품질을 확인하려면 이 테스트 모음을 확인하세요. 각 테스트에 대한 체크 표시:- 진정한 주장이 있습니까, 아니면 소품입니까?- 기대값이 코드에서 파생되어 독립적입니까?- 비즈니스 규칙이나 사소한 것을 확인합니까? 마지막으로 추정된 "진정한 어설션 점수"와 가장 약한 테스트 3개를 제공합니다. 테스트: [붙여넣기]

세 개의 미니 케이스

사례 1 - 적용 범위 92%, 돌연변이 점수 38%. 한 팀은 높은 적용 범위에 의존했습니다. Stryker를 사용하여 돌연변이 테스트를 실행했을 때 점수는 38%였습니다. 생성된 돌연변이의 대부분이 살아 남았습니다. 이는 테스트가 라인을 실행하지 않고 동작을 확인하지 않았다는 증거였습니다. 팀은 품질 테스트에 3주를 투자했습니다. 돌연변이 점수는 81%로 증가했으며, 다음 릴리스에서는 강화된 테스트를 통해 두 가지 실제 계산 오류가 발견되었습니다.

사례 2 - AI가 테스트를 속였습니다. 전문가는 '레드팀' 템플릿을 통해 기존 테스트를 통과했지만 할인 규칙을 위반한 코드를 AI에 요청했다. AI는 항상 할인율 0을 반환하는 코드를 작성했으며 실제 할인 값을 확인하는 테스트가 없었기 때문에 모든 테스트는 녹색으로 유지되었습니다. 공백이 확인되고 실제 주장이 추가되었습니다.

사례 3 - 칭찬의 함정. 후배 테스터가 AI에게 “내 테스트는 잘 됐나요?”라고 물었다. "매우 포괄적이다"라는 대답을 듣고 안도감을 느꼈습니다. 그의 선임 동료는 "테스트 품질 감사" 템플릿을 사용하여 동일한 테스트를 감사했습니다. 20개 테스트 중 12개 테스트는 장식(assert 또는 정크 제외)인 것으로 나타났습니다. 올바른 질문이 올바른 답을 가져왔습니다.

일반적인 실수

  • 품질 범위를 착각함. 높은 행 적용 범위에 의존하고 돌연변이 점수를 전혀 보지 않습니다.
  • AI의 칭찬을 신뢰합니다. "테스트는 잘 됐나요?"라고 묻습니다. 긍정적인 대답을 확신으로 간주합니다.
  • 코드에서 예상 값을 도출합니다. 잘못된 코드를 확인하는 자체 검증 테스트입니다.
  • 사소한 주장에 만족하십시오. "not null", "200이 반환됨"과 같이 실제 규칙의 유효성을 검사하지 않는 검사입니다.
  • 살아남은 돌연변이를 무시합니다. 돌연변이 신고서에 적발되지 않은 내용은 무시합니다.
  • 중요한 코드를 수동으로 변경하려고 시도하지도 않습니다. 도구를 사용할 수 없는 경우 "코드 해제 및 테스트" 단계를 건너뜁니다.

요약하면

의사 신뢰는 테스트가 친환경적이기 때문에 소프트웨어가 정확하다고 믿는 것입니다. 반면 테스트에서는 아무 것도 확인되지 않을 수 있습니다. 이를 측정하기 위한 최적의 표준은 돌연변이 테스트입니다. 의도적으로 코드를 깨고 테스트에서 코드를 포착하는지 여부를 측정하는 것입니다. 돌연변이 점수는 적용 범위보다 품질을 훨씬 더 정직하게 측정합니다. AI는 둘 다 의사 신뢰를 생성하고 이를 추적하는 강력한 레드팀이 됩니다. "이 테스트를 통과하는 버그를 생성해 보세요"라고 요청하세요. 테스트를 테스트하세요: 진정한 어설션, 독립적인 기대값, 비즈니스 규칙 검증, 종료된 돌연변이.

응용과제

자신의 프로젝트에서 비즈니스 규칙과 해당 테스트가 포함된 함수를 가져옵니다. 가능하다면 돌연변이 도구(Stryker/Pitest/mutmut)를 실행하고 돌연변이 점수를 측정합니다. 도구가 없는 경우 "수동 돌연변이 제어" 템플릿을 사용하여 최소 8개의 돌연변이를 생성하고 수동으로 시도해 보세요. 살아남은 각 돌연변이에 대해 "살아남은 돌연변이 죽이기" 템플릿을 사용하여 새 테스트를 작성합니다. 마지막으로 "레드팀" 패턴을 사용하여 AI가 테스트를 속이는 코드를 생성할 수 있는지 확인하세요. 시작 및 종료 돌연변이 점수(또는 발견된/총 돌연변이 비율)를 보고합니다.

체크리스트

  • [ ] 테스트 품질을 커버리지가 아닌 돌연변이 점수로 평가했습니다.
  • [ ] 중요한 코드에 대해 돌연변이 테스트(도구 또는 수동으로)를 실행했습니다.
  • [ ] 나는 살아남은 각 돌연변이에 대해 새로운 테스트를 작성했습니다.
  • [ ] 저는 AI를 레드팀으로 활용하고 테스트에서 허점을 찾았습니다.
  • [ ] 나는 AI의 "테스트가 좋다"는 칭찬을 안심으로 받아들이지 않았습니다.
  • [ ] 각 테스트에서 실제 주장, 독립적인 기대값, 비즈니스 규칙을 검증하는지 확인했습니다.