개요
- C#의 주요 유닛테스트 프레임워크
- xUnit을 선택한 이유
- 가장 유명한 것이 NUnit인데, 이를 개선했다는 점에서 기대
- 종속성이 자유로움
- 확장성이 좋음
- Visual Studio 2022에서 "보기>테스트 탐색기"를 열어서 실행
코드 및 출력
Logic.cs
namespace Study
{
public class Calculator : IDisposable
{
public int Sum(params int[] ints)
{
var result = 0;
foreach(var val in ints)
{
result += val;
}
return result;
}
public void Dispose()
{
}
}
}
단일 클래스(종속성 하)
namespace XUnitTestStudy
{
public class CalculatorUnitTest : IDisposable
{
private ITestOutputHelper _testOutputHelper;
private Study.Calculator _calculator;
public CalculatorUnitTest(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
_calculator = new Study.Calculator();
}
public void Dispose()
{
_calculator.Dispose();
}
[Fact]
public void Sum_OneTwo_ReturnsThree()
{
var result = _calculator.Sum(1, 2);
_testOutputHelper.WriteLine($"HashCode: {_calculator.GetHashCode()}");
Assert.Equal(3, result);
}
[Fact]
public void Sum_TwoOne_ReturnsThree()
{
var result = _calculator.Sum(2, 1);
_testOutputHelper.WriteLine($"HashCode: {_calculator.GetHashCode()}");
Assert.Equal(3, result);
}
}
}
--------------------------------Output-----------------------------------------
XUnitTestStudy.CalculatorUnitTest.Sum_OneTwo_ReturnsThree
HashCode: 13273752
XUnitTestStudy.CalculatorUnitTest.Sum_TwoOne_ReturnsThree
HashCode: 34717384
- 코드상으로는 하나의 Calculator 객체를 두개의 테스트 함수에서 공유하는 것으로 보이지만, Calculator 객체를 각각 생성
일반 상속(종속성 하)
namespace XUnitTestStudy
{
public class CalculatorParent : IDisposable
{
protected ITestOutputHelper _testOutputHelper;
protected Study.Calculator _calculator;
public CalculatorParent(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
_calculator = new Study.Calculator();
}
public void Dispose()
{
_calculator.Dispose();
}
}
public class CalculatorChildUnitTest : CalculatorParent
{
public CalculatorChildUnitTest(ITestOutputHelper testOutputHelper) : base(testOutputHelper) {}
[Fact]
public void Sum_OneTwo_ReturnsThree()
{
var result = _calculator.Sum(1, 2);
_testOutputHelper.WriteLine($"HashCode: {_calculator.GetHashCode()}");
Assert.Equal(3, result);
}
[Fact]
public void Sum_TwoOne_ReturnsThree()
{
var result = _calculator.Sum(2, 1);
_testOutputHelper.WriteLine($"HashCode: {_calculator.GetHashCode()}");
Assert.Equal(3, result);
}
}
}
--------------------------------Output-----------------------------------------
XUnitTestStudy.CalculatorChildUnitTest.Sum_OneTwo_ReturnsThree
Consteructor
HashCode: 49538252
Dispose
XUnitTestStudy.CalculatorChildUnitTest.Sum_TwoOne_ReturnsThree
Consteructor
HashCode: 31071611
Dispose
- 단일 클래스와 동일하게 상속을 받아도 테스트 함수마다 객체를 생성
IClassFixture(종속성 중)
namespace XUnitTestStudy
{
public class CalculatorFixture : IDisposable
{
public Study.Calculator Calculator { get; set; }
public CalculatorFixture()
{
Calculator = new Study.Calculator();
}
public void Dispose()
{
Calculator.Dispose();
}
}
public class CalculatorFixtureUnitTest : IClassFixture<CalculatorFixture>
{
ITestOutputHelper _testOutputHelper;
CalculatorFixture _fixture;
public CalculatorFixtureUnitTest(ITestOutputHelper testOutputHelper, CalculatorFixture fixture)
{
_testOutputHelper = testOutputHelper;
_fixture = fixture;
}
[Fact]
public void Sum_OneTwo_ReturnsThree()
{
var result = _fixture.Calculator.Sum(1, 2);
_testOutputHelper.WriteLine($"HashCode: {_fixture.Calculator.GetHashCode()}");
Assert.Equal(3, result);
}
[Fact]
public void Sum_TwoOne_ReturnsThree()
{
var result = _fixture.Calculator.Sum(2, 1);
_testOutputHelper.WriteLine($"HashCode: {_fixture.Calculator.GetHashCode()}");
Assert.Equal(3, result);
}
}
}
--------------------------------Output-----------------------------------------
XUnitTestStudy.CalculatorFixtureUnitTest.Sum_OneTwo_ReturnsThree
HashCode: 6451435
XUnitTestStudy.CalculatorFixtureUnitTest.Sum_TwoOne_ReturnsThree
HashCode: 6451435
- IClassFixture를 참조하면 하나의 클래스 내에서만 객체을 공유함
ICollectionFixture(종속성 상)
namespace XUnitTestStudy
{
public class CalculatorFixture : IDisposable
{
public Study.Calculator Calculator { get; set; }
public CalculatorFixture()
{
Calculator = new Study.Calculator();
}
public void Dispose()
{
Calculator.Dispose();
}
}
[CollectionDefinition("CalculatorCollection")]
public class CalculatorCollection : ICollectionFixture<CalculatorFixture> {}
[Collection("CalculatorCollection")]
public class CalculatorCollectionUnitTest1
{
ITestOutputHelper _testOutputHelper;
CalculatorFixture _fixture;
public CalculatorCollectionUnitTest1(ITestOutputHelper testOutputHelper, CalculatorFixture fixture)
{
_testOutputHelper = testOutputHelper;
_fixture = fixture;
}
[Fact]
public void Sum_OneTwo_ReturnsThree()
{
var result = _fixture.Calculator.Sum(1, 2);
_testOutputHelper.WriteLine($"HashCode: {_fixture.Calculator.GetHashCode()}");
Assert.Equal(3, result);
}
[Fact]
public void Sum_TwoOne_ReturnsThree()
{
var result = _fixture.Calculator.Sum(2, 1);
_testOutputHelper.WriteLine($"HashCode: {_fixture.Calculator.GetHashCode()}");
Assert.Equal(3, result);
}
}
[Collection("CalculatorCollection")]
public class CalculatorCollectionUnitTest2
{
ITestOutputHelper _testOutputHelper;
CalculatorFixture _fixture;
public CalculatorCollectionUnitTest2(ITestOutputHelper testOutputHelper, CalculatorFixture fixture)
{
_testOutputHelper = testOutputHelper;
_fixture = fixture;
}
[Fact]
public void Sum_OneTwo_ReturnsThree()
{
var result = _fixture.Calculator.Sum(1, 2);
_testOutputHelper.WriteLine($"HashCode: {_fixture.Calculator.GetHashCode()}");
Assert.Equal(3, result);
}
[Fact]
public void Sum_TwoOne_ReturnsThree()
{
var result = _fixture.Calculator.Sum(2, 1);
_testOutputHelper.WriteLine($"HashCode: {_fixture.Calculator.GetHashCode()}");
Assert.Equal(3, result);
}
}
}
--------------------------------Output-----------------------------------------
XUnitTestStudy.CalculatorCollectionUnitTest1.Sum_OneTwo_ReturnsThree
HashCode: 64685481
XUnitTestStudy.CalculatorCollectionUnitTest1.Sum_TwoOne_ReturnsThree
HashCode: 64685481
XUnitTestStudy.CalculatorCollectionUnitTest2.Sum_OneTwo_ReturnsThree
HashCode: 64685481
XUnitTestStudy.CalculatorCollectionUnitTest2.Sum_TwoOne_ReturnsThree
HashCode: 64685481
- ICollectionFixture를 참조하고 CollectionDefinition 속성을 정의하고, 공유할 클래스에서 Collection 속성으로 지정하면, 다수의 클래스에서 객체 공유 가능
결론
- IClassFixture, ICollectionFixture를 통해 종속성을 자유롭게 조정 가능
- 확장성 측면에서는, 다른 테스트 프레임워크에 비해 속성 개수가 적어서 코드가 간결하고 학습하기 용이
참고문헌