[C#] xUnit 유닛 테스트

natae·2022년 9월 4일
0

Csharp

목록 보기
6/9

개요

  • C#의 주요 유닛테스트 프레임워크
    • MSTest
      • MS에서 기본으로 제공
    • NUnit
      • Java의 JUnit을 C#으로 포팅
    • xUnit
      • NUnit을 개선
  • 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()
        {
            // Implementation required if there are resources to 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를 통해 종속성을 자유롭게 조정 가능
  • 확장성 측면에서는, 다른 테스트 프레임워크에 비해 속성 개수가 적어서 코드가 간결하고 학습하기 용이

참고문헌

profile
서버 프로그래머

0개의 댓글