돌연변이 테스트는 단위 테스트의 품질을 평가하는 방법입니다. 돌연변이 테스트의 경우 Stryker.NET 도구는 코드에서 자동으로 변형을 수행하고, 테스트를 실행하고, 결과와 함께 자세한 보고서를 생성합니다.
테스트 시나리오 예제
할인을 고려하여 가격을 계산하는 메서드를 사용하여 샘플 Calculate 클래스를 고려합니다.
public class PriceCalculator
{
public decimal CalculatePrice(decimal price, decimal discountPercent)
{
if (price <= 0)
{
throw new ArgumentException("Price must be greater than zero.");
}
if (discountPercent < 0 || discountPercent > 100)
{
throw new ArgumentException("Discount percent must be between 0 and 100.");
}
var discount = price * (discountPercent / 100);
var discountedPrice = price - discount;
return Math.Round(discountedPrice, 2);
}
}
위의 메서드는 다음 단위 테스트에서 다룹니다.
[Fact]
public void ApplyDiscountCorrectly()
{
decimal price = 100;
decimal discountPercent = 10;
var calculator = new PriceCalculator();
var result = calculator.CalculatePrice(price, discountPercent);
Assert.Equal(90.00m, result);
}
[Fact]
public void InvalidDiscountPercent_ShouldThrowException()
{
var calculator = new PriceCalculator();
Assert.Throws<ArgumentException>(() => calculator.CalculatePrice(100, -1));
Assert.Throws<ArgumentException>(() => calculator.CalculatePrice(100, 101));
}
[Fact]
public void InvalidPrice_ShouldThrowException()
{
var calculator = new PriceCalculator();
Assert.Throws<ArgumentException>(() => calculator.CalculatePrice(-10, 10));
}
앞의 코드는 두 개의 프로젝트를 강조 표시합니다. 하나는 PriceCalculator 역할을 하는 서비스에 대한 프로젝트이고 다른 하나는 테스트 프로젝트입니다.
전역 도구 설치
먼저 Stryker.NET설치합니다. 이렇게 하려면 다음 명령을 실행해야 합니다.
dotnet tool install -g dotnet-stryker
stryker실행하려면 단위 테스트 프로젝트가 있는 디렉터리의 명령줄에서 호출합니다.
dotnet stryker
테스트가 실행되면 콘솔에 보고서가 표시됩니다.
Stryker.NET StrykerOutput 디렉터리에 자세한 HTML 보고서를 저장합니다.
이제 돌연변이가 무엇이고 '살아남은' 및 '죽임을 당했다'는 것이 무엇을 의미하는지 생각해 보십시오. 돌연변이는 Stryker가 의도적으로 만드는 코드의 작은 변경 내용입니다. 아이디어는 간단합니다: 테스트가 좋은 경우 변경 사항을 잡아내고 실패해야 합니다. 계속 통과한다면, 테스트가 충분히 강하지 않을 수 있습니다.
이 예제에서 돌연변이는 식 price <= 0을(를) price < 0으로 대체한 후 단위 테스트가 실행됩니다.
Stryker는 다음과 같은 여러 유형의 돌연변이를 지원합니다.
| 유형 | 설명 |
|---|---|
| 상응 | 해당 연산자는 연산자를 해당하는 연산자로 바꾸는 데 사용됩니다. 예를 들어 x < y은 x <= y이 됩니다. |
| 산술 | 산술 연산자는 산술 연산자를 해당하는 연산자로 바꾸는 데 사용됩니다. 예를 들어 x + y은 x - y이 됩니다. |
| 문자열 | 문자열 연산자는 문자열을 해당하는 문자열로 바꾸는 데 사용됩니다. 예를 들어 "text"은 ""이 됩니다. |
| 논리적인 | 논리 연산자는 논리 연산자를 해당하는 연산자로 바꾸는 데 사용됩니다. 예를 들어 x && y은 x \|\| y이 됩니다. |
추가 돌연변이 유형은 Stryker.NET: 돌연변이 설명서를 참조하세요.
점진적 개선
코드를 변경한 후 단위 테스트가 성공적으로 통과하면, 테스트가 충분히 견고하지 않으며 돌연변이가 살아남았다는 것입니다. 돌연변이 검사 후에, 5개의 돌연변이는 살아남습니다.
경계 값에 대한 테스트 데이터를 추가하고 변형 테스트를 다시 실행해 보겠습니다.
[Fact]
public void InvalidPrice_ShouldThrowException()
{
var calculator = new PriceCalculator();
// changed price from -10 to 0
Assert.Throws<ArgumentException>(() => calculator.CalculatePrice(0, 10));
}
[Fact] // Added test for 0 and 100 discount
public void NoExceptionForZeroAnd100Discount()
{
var calculator = new PriceCalculator();
var exceptionWhen0 = Record.Exception(() => calculator.CalculatePrice(100, 0));
var exceptionWhen100 = Record.Exception(() => calculator.CalculatePrice(100, 100));
Assert.Null(exceptionWhen0);
Assert.Null(exceptionWhen100);
}
여기서 볼 수 있듯이, 해당하는 돌연변이를 수정한 후에는 문자열 변형만 남게 되므로 예외 메시지의 텍스트를 확인하여 쉽게 '종료'할 수 있습니다.
[Fact]
public void InvalidDiscountPercent_ShouldThrowExceptionWithCorrectMessage()
{
var calculator = new PriceCalculator();
var ex1 = Assert.Throws<ArgumentException>(() => calculator.CalculatePrice(100, -1));
Assert.Equal("Discount percent must be between 0 and 100.", ex1.Message);
var ex2 = Assert.Throws<ArgumentException>(() => calculator.CalculatePrice(100, 101));
Assert.Equal("Discount percent must be between 0 and 100.", ex2.Message);
}
[Fact]
public void InvalidPrice_ShouldThrowExceptionWithCorrectMessage()
{
var calculator = new PriceCalculator();
var ex = Assert.Throws<ArgumentException>(() => calculator.CalculatePrice(0, 10));
Assert.Equal("Price must be greater than zero.", ex.Message);
}
돌연변이 테스트는 더 신뢰할 수 있는 테스트를 개선할 기회를 찾는 데 도움이 됩니다. 이렇게 하면 '행복한 경로'뿐만 아니라 복잡한 경계 사례도 확인하여 프로덕션에서 버그가 발생할 가능성을 줄입니다.
.NET