단위 테스트를 병렬이 아닌 직렬로 실행
내가 작성한 WCF 호스트 관리 엔진을 단위 테스트하려고합니다. 엔진은 기본적으로 구성에 따라 즉시 ServiceHost 인스턴스를 생성합니다. 이를 통해 새로운 서비스가 추가되거나 이전 서비스가 제거 될 때마다 서비스를 모두 종료하고 다시 시작할 필요없이 사용할 수있는 서비스를 동적으로 재구성 할 수 있습니다.
그러나 ServiceHost의 작동 방식으로 인해이 호스트 관리 엔진을 단위 테스트하는 데 어려움이 있습니다. 특정 끝점에 대해 ServiceHost가 이미 생성되고 열렸지만 아직 닫히지 않은 경우 동일한 끝점에 대해 다른 ServiceHost를 만들 수 없으므로 예외가 발생합니다. 최신 단위 테스트 플랫폼은 테스트 실행을 병렬화하기 때문에이 코드 조각을 단위 테스트 할 효과적인 방법이 없습니다.
확장 성 때문에 테스트를 직렬로 실행하도록 강제하는 방법을 찾을 수 있기를 바라면서 xUnit.NET을 사용했습니다. 그러나 나는 운이 없었습니다. 나는 여기 누군가가 비슷한 문제를 겪고 단위 테스트를 직렬로 실행하는 방법을 알고 있기를 바랍니다.
참고 : ServiceHost 는 Microsoft에서 작성한 WCF 클래스입니다. 나는 그 행동을 바꿀 능력이 없습니다. 각 서비스 엔드 포인트를 한 번만 호스팅하는 것도 적절한 동작이지만 단위 테스트에는 특별히 도움이되지 않습니다.
위에서 언급했듯이 모든 좋은 단위 테스트는 100 % 격리되어야합니다. 공유 상태 (예 : static
각 테스트에 의해 수정되는 속성 에 따라 다름)를 사용하는 것은 나쁜 습관으로 간주됩니다.
즉, xUnit 테스트를 순서대로 실행하는 것에 대한 질문에 답이 있습니다! 내 시스템이 정적 서비스 로케이터를 사용하기 때문에 똑같은 문제가 발생했습니다 (이상적임).
기본적으로 xUnit 2.x는 모든 테스트를 병렬로 실행합니다. 이것은 CollectionBehavior
테스트 프로젝트의 AssemblyInfo.cs에서 정의하여 어셈블리별로 수정할 수 있습니다 .
어셈블리 별 분리 사용 :
using Xunit;
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
또는 전혀 사용하지 않는 경우 :
[assembly: CollectionBehavior(DisableTestParallelization = true)]
후자는 아마도 당신이 원하는 것입니다. 병렬화 및 구성에 대한 자세한 정보는 xUnit 문서 에서 찾을 수 있습니다 .
각 테스트 클래스는 고유 한 테스트 컬렉션이며 그 아래의 테스트는 순서대로 실행되므로 모든 테스트를 동일한 컬렉션에 넣으면 순차적으로 실행됩니다.
xUnit에서는이를 위해 다음과 같이 변경할 수 있습니다.
다음은 병렬로 실행됩니다.
namespace IntegrationTests
{
public class Class1
{
[Fact]
public void Test1()
{
Console.WriteLine("Test1 called");
}
[Fact]
public void Test2()
{
Console.WriteLine("Test2 called");
}
}
public class Class2
{
[Fact]
public void Test3()
{
Console.WriteLine("Test3 called");
}
[Fact]
public void Test4()
{
Console.WriteLine("Test4 called");
}
}
}
순차적으로 만들려면 두 테스트 클래스를 동일한 컬렉션에 넣어야합니다.
namespace IntegrationTests
{
[Collection("Sequential")]
public class Class1
{
[Fact]
public void Test1()
{
Console.WriteLine("Test1 called");
}
[Fact]
public void Test2()
{
Console.WriteLine("Test2 called");
}
}
[Collection("Sequential")]
public class Class2
{
[Fact]
public void Test3()
{
Console.WriteLine("Test3 called");
}
[Fact]
public void Test4()
{
Console.WriteLine("Test4 called");
}
}
}
자세한 정보는 이 링크를 참조하십시오.
.NET Core 프로젝트의 경우 다음을 사용 xunit.runner.json
하여 만듭니다 .
{
"parallelizeAssembly": false,
"parallelizeTestCollections": false
}
또한, 당신은 csproj
포함해야
<ItemGroup>
<None Update="xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
이전 .Net Core 프로젝트의 경우 다음 project.json
을 포함해야합니다.
"buildOptions": {
"copyToOutput": {
"include": [ "xunit.runner.json" ]
}
}
.NET Core 프로젝트의 경우 https://xunit.github.io/docs/configuring-with-json.html에xunit.runner.json
설명 된대로 파일로 xUnit을 구성 할 수 있습니다 .
병렬 테스트 실행을 중지하기 위해 변경해야하는 설정은 parallelizeTestCollections
입니다. 기본값은 true
다음과 같습니다.
true
어셈블리가이 어셈블리 내부에서 서로에 대해 병렬로 테스트를 실행하려는 경우이 값을 설정합니다 . ...false
이 테스트 어셈블리 내의 모든 병렬화를 비활성화 하려면 이것을로 설정합니다 .JSON 스키마 유형 : 부울
기본값 :true
따라서이 xunit.runner.json
목적을위한 최소값 은 다음과 같습니다.
{
"parallelizeTestCollections": false
}
문서에서 언급했듯이 다음 방법 중 하나로 빌드에이 파일을 포함해야합니다.
- Visual Studio 의 파일 속성이 더 최신 인 경우 출력 디렉터리 에 복사를 복사로 설정 하거나
첨가
<Content Include=".\xunit.runner.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content>
당신에
.csproj
파일 또는첨가
"buildOptions": { "copyToOutput": { "include": [ "xunit.runner.json" ] } }
당신의
project.json
파일에
프로젝트 유형에 따라.
Finally, in addition to the above, if you're using Visual Studio then make sure that you haven't accidentally clicked the Run Tests In Parallel button, which will cause tests to run in parallel even if you've turned off parallelisation in xunit.runner.json
. Microsoft's UI designers have cunningly made this button unlabelled, hard to notice, and about a centimetre away from the "Run All" button in Test Explorer, just to maximise the chance that you'll hit it by mistake and have no idea why your tests are suddenly failing:
you can Use Playlist
right click on the test method -> Add to playlist -> New playlist
then you can specify the execution order, the default is, as you add them to the play list but you can change the playlist file as you want
I don't know the details, but it sounds like you might be trying to do integration testing rather than unit testing. If you could isolate the dependency on ServiceHost
, that would likely make your testing easier (and faster). So (for instance) you might test the following independently:
- Configuration reading class
- ServiceHost factory (possibly as an integration test)
- Engine class that takes an
IServiceHostFactory
and anIConfiguration
Tools that would help include isolation (mocking) frameworks and (optionally) IoC container frameworks. See:
- http://www.mockobjects.com/
- http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
Advanced Unit Testing을 사용할 수 있습니다 . 테스트를 실행하는 순서를 정의 할 수 있습니다 . 따라서 이러한 테스트를 호스팅하려면 새 cs 파일을 만들어야 할 수 있습니다.
원하는 순서로 작동하도록 테스트 방법을 구부리는 방법은 다음과 같습니다.
[Test]
[Sequence(16)]
[Requires("POConstructor")]
[Requires("WorkOrderConstructor")]
public void ClosePO()
{
po.Close();
// one charge slip should be added to both work orders
Assertion.Assert(wo1.ChargeSlipCount==1,
"First work order: ChargeSlipCount not 1.");
Assertion.Assert(wo2.ChargeSlipCount==1,
"Second work order: ChargeSlipCount not 1.");
...
}
작동하는지 알려주세요.
기본 클래스에 [Collection ( "Sequential")] 속성을 추가했습니다 .
namespace IntegrationTests
{
[Collection("Sequential")]
public class SequentialTest : IDisposable
...
public class TestClass1 : SequentialTest
{
...
}
public class TestClass2 : SequentialTest
{
...
}
}
참고 URL : https://stackoverflow.com/questions/1408175/execute-unit-tests-serially-rather-than-in-parallel
'programing tip' 카테고리의 다른 글
Laravel : 속성 별 컬렉션에서 객체 가져 오기 (0) | 2020.10.28 |
---|---|
Gradle 다운로드시 Ionic 빌드 Android 오류 (0) | 2020.10.28 |
jQuery를 사용하여 선택한 확인란의 값을 가져옵니다. (0) | 2020.10.28 |
CoreData에 어레이를 저장하는 방법은 무엇입니까? (0) | 2020.10.28 |
클래스에 속성이 있는지 확인 (0) | 2020.10.27 |