AutoFixture로 테스트 인지 복잡성 감소
테스트를 여전히 읽을 수 있고 해당 변수의 설정으로 인해 부풀어 오르지 않도록 하는 것은 상당히 어려울 수 있지만 더 이상 AutoFixture 을 사용하지 않기를 바랍니다. 방법을 살펴보겠습니다!
설정
If you want to, you can make the same manipulations as I am doing, like a small hands on lab on AutoFixture. If not, you may skip this chapter and head directly to the case study.
여기의 설정은 정말 최소한입니다. 새로운 테스트 프로젝트를 생성하기만 하면 됩니다. 나는 xUnit을 사용할 것이지만 NUnit도 괜찮을 것입니다.
~$ dotnet new xunit -o AutoFixtureExample
이제 선택한 편집기에서 새 프로젝트를 열고 생성된 파일
UnitTest1.cs
을 삭제할 수 있습니다.사례 연구
AutoFixture가 귀하의 프로젝트에서 자산이 될 수 있는 이유를 이해하기 위해 창고와 의류 주문을 고려하여 주문 처리를 확인하거나 거부하는 간단한 사례 연구를 수행할 것입니다.
새 파일
Warehouse.cs
에서 먼저 엔티티를 추가해 보겠습니다.// Warehouse.cs
public record Cloth(string Name);
public record Order(Cloth cloth, int UnitsOrdered, double Discount);
public class Warehouse
{
}
마지막으로
Warhouse
클래스 내부에 간단한 주문 유효성 검사를 추가합니다.// Warehouse.cs
public bool IsValid(Order order)
{
if (order.UnitsOrdered < 1) return false;
// Some more checks on the stocks
return true;
}
이제 로직이 있으므로 새
WarehouseTest.cs
파일에서 테스트할 수 있습니다.// WarehouseTest.cs
public class WarehouseTest
{
[Fact]
public void OrderingWithAnInvalidUnitsCount()
{
var order = new Order(new Cloth("sweat"), -1, 0);
var result = new Warehouse().IsValid(order);
Assert.False(result);
}
}
이제 테스트를 실행하여 테스트가 통과되었는지 확인할 수 있습니다.
약간의 문제
우리의 테스트는 통과할 수 있지만 우리가 원하는 만큼 잘 작성되지 않을 수 있습니다.
가독성 및 의도
여기에서 가독성일 수 있는 첫 번째 문제를 해결해 보겠습니다.
우리의 예에서 테스트는 매우 간단하지만 프로젝트에 새로 온 사람은
-1
가 실제로 무엇을 의미하는지 모를 수 있으며 여기서 만드는 천의 종류가 관련이 없다는 것을 모를 수도 있습니다.변수 이름을 지정하여 명확하게 할 수 있습니다.
// WarhouseTest.cs
public class WarehouseTest
{
[Fact]
public void OrderingWithAnInvalidUnitsCount()
{
- var order = new Order(new Cloth("sweat"), -1, 0);
+ var invalidUnitsCount = -1;
+ var cloth = new Cloth("This does not matter for the test");
+ var irrelevantDiscount = 0;
+ var order = new Order(cloth, invalidUnitsCount, irrelevantDiscount);
var result = new Warehouse().IsValid(order);
Assert.False(result);
}
}
Variables that are purposely created to indicate that they does not matter are also sometimes referred as anonymous variables in AutoFixture.
이제 좀 더 장황하지만 테스트의 의도가 더 명확해지고 새로운 사람이 매개변수가 무엇인지 파악하는 데 도움이 될 수 있습니다.
Notice that strings can hold their intents (ex:
"My value does not matter"
) but other types may not such as int, double, etc. That's why we had to name our variable holding the discount with this explicit name.
생존 리팩토링
직면할 수 있는 또 다른 문제는 테스트에 사용되는 클래스가 진화한다는 것입니다.
Cloth
클래스에 마케팅 날짜도 포함되어 있다고 가정해 보겠습니다. 결과적으로 테스트를 업데이트해야 합니다.// Warehouse.cs
- public record Cloth(string Name);
+ public record Cloth(string Name, DateTime MarketingDate);
// WarehouseTest.cs
public class WarehouseTest
{
[Fact]
public void OrderingWithAnInvalidUnitsCount()
{
var invalidUnitsCount = -1;
- var cloth = new Cloth("This does not matter for the test");
+ var cloth = new Cloth("This does not matter for the test", DateTime.Now);
var irrelevantDiscount = 0;
var order = new Order(cloth, invalidUnitsCount, irrelevantDiscount);
var result = new Warehouse().IsValid(order);
Assert.False(result);
}
}
최소한의 예에서도 이 변경 사항이 이미 테스트에 영향을 미쳤습니다.
Cloth
를 사용하는 테스트나 객체가 더 많다면 더 많은 리팩토링을 수행해야 합니다.You may also notice that we are passing
DateTime.Now
here, which is yet not very readable regarding its intent.
AutoFixture 소개
우리 테스트는 이러한 초기화로 인해 점점 더 부풀어 오르고 있으며 클래스 중 하나가 발전하면 더 커질 수 있습니다.
AutoFixture 을 사용하여 크게 단순화할 수 있기를 바랍니다.
AutoFixture은 명시적으로 중요하지 않은 것으로 표시될 수 있는 변수를 생성할 수 있는 NuGet입니다.
README를 한 눈에 보면 정확히 우리에게 필요한 것 같습니다.
AutoFixture is designed to make Test-Driven Development more productive and unit tests more refactoring-safe. It does so by removing the need for hand-coding anonymous variables as part of a test's Fixture Setup phase.
AutoFixture를 추가하고 변경 사항을 살펴보겠습니다!
~/AutoFixtureExample$ dotnet add package AutoFixture
// WarehouseTest.cs
public class WarehouseTest
{
private static readonly IFixture Fixture = new Fixture();
[Fact]
public void OrderingWithAnInvalidUnitsCount()
{
var invalidUnitsCount = -1;
var cloth = Fixture.Create<Cloth>();
var discount = Fixture.Create<double>();
var order = new Order(cloth, invalidUnitsCount, discount);
var result = new Warehouse().IsValid(order);
Assert.False(result);
}
}
이제 어떤 값이 관련이 있고 어떤 값이 관련이 없는지 지정할 필요가 없기 때문에 조금 더 좋습니다. 그러나 테스트는 여전히 꽤 길며 AutoFixture의 빌더를 활용하여 훨씬 더 간단한 방법으로 주문을 생성할 수 있습니다.
// WarehouseTest.cs
public class WarehouseTest
{
private static readonly IFixture Fixture = new Fixture();
[Fact]
public void OrderingWithAnInvalidUnitsCount()
{
- var invalidUnitsCount = -1;
- var cloth = Fixture.Create<Cloth>();
- var discount = Fixture.Create<double>();
- var order = new Order(cloth, invalidUnitsCount, discount);
+ var order = Fixture.Build<Order>()
+ .With(order => order.UnitsOrdered, -1)
+ .Create();
var result = new Warehouse().IsValid(order);
Assert.False(result);
}
}
이제 중요한 변수만 명시적으로 설정되고 클래스가 변경되더라도 수정할 필요가 없는 테스트가 있습니다.
테이크 아웃
AutoFixture를 사용하여 테스트의 가독성을 크게 개선하고 의도를 명확히 하는 동시에 클래스의 정의가 변경될 때마다 중단되지 않도록 했습니다.
물론 개체 생성을 사용자 지정하는 방법, 시퀀스를 만드는 방법 등과 같이 이 라이브러리에 대해 배울 것이 훨씬 더 많습니다. AutoFixture를 사용하기 위한 좋은 출발점이 될 수 있는 GitHub 및 관련cheat sheet을 참조할 수 있습니다. .
Reference
이 문제에 관하여(AutoFixture로 테스트 인지 복잡성 감소), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/sfeircode/reduce-your-tests-cognitive-complexity-with-autofixture-2dm4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)