"XUnit.net"의 두 판 사이의 차이
36번째 줄: | 36번째 줄: | ||
|[TestInitialize] | |[TestInitialize] | ||
|Constructor | |Constructor | ||
− | |We believe that use of [SetUp] is generally bad. However, you can implement a parameterless constructor as a direct replacement. See Note 2 | + | |We believe that use of [SetUp] is generally bad. However, you can implement a parameterless constructor as a direct replacement. See [[XUnit.net#Note%202|Note 2]] |
|- | |- | ||
|[TearDown] | |[TearDown] | ||
|[TestCleanup] | |[TestCleanup] | ||
|IDisposable.Dispose | |IDisposable.Dispose | ||
− | |We believe that use of [TearDown] is generally bad. However, you can implement IDisposable.Dispose as a direct replacement. See Note 2 | + | |We believe that use of [TearDown] is generally bad. However, you can implement IDisposable.Dispose as a direct replacement. See [[XUnit.net#Note%202|Note 2]] |
|- | |- | ||
|[OneTimeSetUp] | |[OneTimeSetUp] | ||
|[ClassInitialize] | |[ClassInitialize] | ||
|IClassFixture<T> | |IClassFixture<T> | ||
− | |To get per-class fixture setup, implement IClassFixture<T> on your test class. See Note 3 | + | |To get per-class fixture setup, implement IClassFixture<T> on your test class. See [[XUnit.net#Note%203|Note 3]] |
|- | |- | ||
|[OneTimeTearDown] | |[OneTimeTearDown] | ||
|[ClassCleanup] | |[ClassCleanup] | ||
|IClassFixture<T> | |IClassFixture<T> | ||
− | |To get per-class fixture teardown, implement IClassFixture<T> on your test class. See Note 3 | + | |To get per-class fixture teardown, implement IClassFixture<T> on your test class. See [[XUnit.net#Note%203|Note 3]] |
|- | |- | ||
|''n/a'' | |''n/a'' | ||
|''n/a'' | |''n/a'' | ||
|ICollectionFixture<T> | |ICollectionFixture<T> | ||
− | |To get per-collection fixture setup and teardown, implement ICollectionFixture<T> on your test collection. See Note 3 | + | |To get per-collection fixture setup and teardown, implement ICollectionFixture<T> on your test collection. See [[XUnit.net#Note%203|Note 3]] |
|- | |- | ||
|[Ignore("reason")] | |[Ignore("reason")] | ||
73번째 줄: | 73번째 줄: | ||
[XxxData] | [XxxData] | ||
− | |Theory (data-driven test). See Note 4 | + | |Theory (data-driven test). See [[XUnit.net#Note%204|Note 4]] |
|} | |} | ||
92번째 줄: | 92번째 줄: | ||
{ | { | ||
var person = new Person(null!); | var person = new Person(null!); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===== Note 2 ===== | ||
+ | 각 테스트를 실행하기 전에 실행할 코드를 지정할 때 사용한다.<syntaxhighlight lang="csharp"> | ||
+ | // Use TestInitialize to run code before running each test | ||
+ | [TestInitialize()] | ||
+ | public void MyTestInitialize() | ||
+ | { | ||
+ | // To generate code for this test, select "Generate Code for Coded | ||
+ | // UI Test" from the shortcut menu and select one of the menu items. | ||
+ | // For more information on generated code, see | ||
+ | // http://go.microsoft.com/fwlink/?LinkId=179463 | ||
+ | |||
+ | // You could move this line from the CodedUITestMethod1() method | ||
+ | this.UIMap.LaunchCalculator(); | ||
+ | } | ||
+ | |||
+ | // Use TestCleanup to run code after each test has run | ||
+ | [TestCleanup()] | ||
+ | public void MyTestCleanup() | ||
+ | { | ||
+ | // To generate code for this test, select "Generate Code for Coded | ||
+ | // UI Test" from the shortcut menu and select one of the menu items. | ||
+ | // For more information on generated code, see | ||
+ | // http://go.microsoft.com/fwlink/?LinkId=179463 | ||
+ | |||
+ | // You could move this line from the CodedUITestMethod1() method | ||
+ | this.UIMap.CloseCalculator(); | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
===== Note 3 ===== | ===== Note 3 ===== | ||
− | <br /> | + | 클래스의 첫 번째 테스트를 실행하기 전에 실행할 코드를 지정한다.<syntaxhighlight lang="csharp"> |
+ | using System; | ||
+ | |||
+ | namespace SampleClassLib | ||
+ | { | ||
+ | public class DivideClass | ||
+ | { | ||
+ | public static int DivideMethod(int denominator) | ||
+ | { | ||
+ | return (2 / denominator); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight>테스트 코드<syntaxhighlight lang="csharp"> | ||
+ | using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
+ | using SampleClassLib; | ||
+ | using System; | ||
+ | using System.Windows.Forms; | ||
+ | |||
+ | namespace TestNamespace | ||
+ | { | ||
+ | [TestClass()] | ||
+ | public sealed class DivideClassTest | ||
+ | { | ||
+ | [AssemblyInitialize()] | ||
+ | public static void AssemblyInit(TestContext context) | ||
+ | { | ||
+ | MessageBox.Show("AssemblyInit " + context.TestName); | ||
+ | } | ||
+ | |||
+ | [ClassInitialize()] | ||
+ | public static void ClassInit(TestContext context) | ||
+ | { | ||
+ | MessageBox.Show("ClassInit " + context.TestName); | ||
+ | } | ||
+ | |||
+ | [TestInitialize()] | ||
+ | public void Initialize() | ||
+ | { | ||
+ | MessageBox.Show("TestMethodInit"); | ||
+ | } | ||
+ | |||
+ | [TestCleanup()] | ||
+ | public void Cleanup() | ||
+ | { | ||
+ | MessageBox.Show("TestMethodCleanup"); | ||
+ | } | ||
+ | |||
+ | [ClassCleanup()] | ||
+ | public static void ClassCleanup() | ||
+ | { | ||
+ | MessageBox.Show("ClassCleanup"); | ||
+ | } | ||
+ | |||
+ | [AssemblyCleanup()] | ||
+ | public static void AssemblyCleanup() | ||
+ | { | ||
+ | MessageBox.Show("AssemblyCleanup"); | ||
+ | } | ||
+ | |||
+ | [TestMethod()] | ||
+ | [ExpectedException(typeof(System.DivideByZeroException))] | ||
+ | public void DivideMethodTest() | ||
+ | { | ||
+ | DivideClass.DivideMethod(0); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===== Note 4 ===== | ||
+ | 데이터 기반 단위 테스트<syntaxhighlight lang="csharp"> | ||
+ | public int AddIntegers(int first, int second) | ||
+ | { | ||
+ | int sum = first; | ||
+ | for( int i = 0; i < second; i++) | ||
+ | { | ||
+ | sum += 1; | ||
+ | } | ||
+ | return sum; | ||
+ | } | ||
+ | </syntaxhighlight>테스트 클래스에 TestContext 추가<syntaxhighlight lang="csharp"> | ||
+ | private TestContext testContextInstance; | ||
+ | public TestContext TestContext | ||
+ | { | ||
+ | get { return testContextInstance; } | ||
+ | set { testContextInstance = value; } | ||
+ | } | ||
+ | </syntaxhighlight>테스트 메서드 작성<syntaxhighlight lang="csharp"> | ||
+ | [DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0; Data Source=C:\Data\MathsData.sdf;", "Numbers")] | ||
+ | [TestMethod()] | ||
+ | public void AddIntegers_FromDataSourceTest() | ||
+ | { | ||
+ | var target = new Maths(); | ||
+ | |||
+ | // Access the data | ||
+ | int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]); | ||
+ | int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]); | ||
+ | int expected = Convert.ToInt32(TestContext.DataRow["Sum"]); | ||
+ | int actual = target.IntegerMethod(x, y); | ||
+ | Assert.AreEqual(expected, actual, | ||
+ | "x:<{0}> y:<{1}>", | ||
+ | new object[] {x, y}); | ||
+ | } | ||
+ | </syntaxhighlight><br /> | ||
{{DEFAULTSORT:xUnit.net}} | {{DEFAULTSORT:xUnit.net}} |
2021년 6월 14일 (월) 12:36 판
목차
Document
https://xunit.net/#documentation
Comparing xUnit.net to other frameworks
https://xunit.net/docs/comparisons
NUnit 3.x | MSTest 15.x | xUnit.net 2.x | Comments |
[Test] | [TestMethod] | [Fact] | Marks a test method. |
[TestFixture] | [TestClass] | n/a | xUnit.net does not require an attribute for a test class; it looks for all test methods in all public (exported) classes in the assembly. |
Assert.That
Record.Exception |
[ExpectedException] | Assert.Throws
Record.Exception |
xUnit.net has done away with the ExpectedException attribute in favor of Assert.Throws. See Note 1 |
[SetUp] | [TestInitialize] | Constructor | We believe that use of [SetUp] is generally bad. However, you can implement a parameterless constructor as a direct replacement. See Note 2 |
[TearDown] | [TestCleanup] | IDisposable.Dispose | We believe that use of [TearDown] is generally bad. However, you can implement IDisposable.Dispose as a direct replacement. See Note 2 |
[OneTimeSetUp] | [ClassInitialize] | IClassFixture<T> | To get per-class fixture setup, implement IClassFixture<T> on your test class. See Note 3 |
[OneTimeTearDown] | [ClassCleanup] | IClassFixture<T> | To get per-class fixture teardown, implement IClassFixture<T> on your test class. See Note 3 |
n/a | n/a | ICollectionFixture<T> | To get per-collection fixture setup and teardown, implement ICollectionFixture<T> on your test collection. See Note 3 |
[Ignore("reason")] | [Ignore] | [Fact(Skip="reason")] | Set the Skip parameter on the [Fact] attribute to temporarily skip a test. |
[Property] | [TestProperty] | [Trait] | Set arbitrary metadata on a test |
[Theory] | [DataSource] | [Theory]
[XxxData] |
Theory (data-driven test). See Note 4 |
Attribute Notes
Note 1
기대되는 예외지정
#nullable enable
public class Person
{
public Person(string name) => Name = name ?? throw new ArgumentNullException(nameof(name));
public string Name { get; }
}
테스트 코드
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public void NullNameShouldThrowTest()
{
var person = new Person(null!);
}
Note 2
각 테스트를 실행하기 전에 실행할 코드를 지정할 때 사용한다.
// Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
// To generate code for this test, select "Generate Code for Coded
// UI Test" from the shortcut menu and select one of the menu items.
// For more information on generated code, see
// http://go.microsoft.com/fwlink/?LinkId=179463
// You could move this line from the CodedUITestMethod1() method
this.UIMap.LaunchCalculator();
}
// Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
// To generate code for this test, select "Generate Code for Coded
// UI Test" from the shortcut menu and select one of the menu items.
// For more information on generated code, see
// http://go.microsoft.com/fwlink/?LinkId=179463
// You could move this line from the CodedUITestMethod1() method
this.UIMap.CloseCalculator();
}
Note 3
클래스의 첫 번째 테스트를 실행하기 전에 실행할 코드를 지정한다.
using System;
namespace SampleClassLib
{
public class DivideClass
{
public static int DivideMethod(int denominator)
{
return (2 / denominator);
}
}
}
테스트 코드
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SampleClassLib;
using System;
using System.Windows.Forms;
namespace TestNamespace
{
[TestClass()]
public sealed class DivideClassTest
{
[AssemblyInitialize()]
public static void AssemblyInit(TestContext context)
{
MessageBox.Show("AssemblyInit " + context.TestName);
}
[ClassInitialize()]
public static void ClassInit(TestContext context)
{
MessageBox.Show("ClassInit " + context.TestName);
}
[TestInitialize()]
public void Initialize()
{
MessageBox.Show("TestMethodInit");
}
[TestCleanup()]
public void Cleanup()
{
MessageBox.Show("TestMethodCleanup");
}
[ClassCleanup()]
public static void ClassCleanup()
{
MessageBox.Show("ClassCleanup");
}
[AssemblyCleanup()]
public static void AssemblyCleanup()
{
MessageBox.Show("AssemblyCleanup");
}
[TestMethod()]
[ExpectedException(typeof(System.DivideByZeroException))]
public void DivideMethodTest()
{
DivideClass.DivideMethod(0);
}
}
}
Note 4
데이터 기반 단위 테스트
public int AddIntegers(int first, int second)
{
int sum = first;
for( int i = 0; i < second; i++)
{
sum += 1;
}
return sum;
}
테스트 클래스에 TestContext 추가
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
테스트 메서드 작성
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0; Data Source=C:\Data\MathsData.sdf;", "Numbers")]
[TestMethod()]
public void AddIntegers_FromDataSourceTest()
{
var target = new Maths();
// Access the data
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
int actual = target.IntegerMethod(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}