Snapshooter
Snapshooter는 .NET의 장치 테스트에서 결과 유효성 검사를 단순화하는 유연한 스냅 샷 테스트 도구입니다. Jest Snapshot 테스트 아이디어를 기반으로합니다.
Snapshooter에 대한 자세한 정보를 얻으려면 Snapshooter Docs로 이동하십시오.
시작하려면 Snapshooter Xunit 또는 Nunit Nuget 패키지를 설치하십시오.
dotnet add package Snapshooter.Xunitdotnet add package Snapshooter.NUnitdotnet add package Snapshooter.MSTest시작하세요
장치 테스트에서 스냅 샷으로 테스트 결과를 주장하려면 다음 단계를 수행하십시오.
Snapshot Assert Statement Snapshot.Match(yourResultObject); 단위 테스트에.
예:
/// <summary>
/// Tests if the new created person is valid.
/// </summary>
[ Fact ]
public void CreatePersonSnapshotTest ( )
{
// arrange
var serviceClient = new ServiceClient ( ) ;
// act
TestPerson person = serviceClient . CreatePerson (
Guid . Parse ( "2292F21C-8501-4771-A070-C79C7C7EF451" ) , "David" , "Mustermann" ) ;
// assert
Snapshot . Match ( person ) ;
} Snapshot.Match(person) 문은 결과 객체의 새로운 스냅 샷을 생성하고 __snapshots__ 폴더에 저장합니다. __snapshots__ 폴더는 항상 실행 된 단위 테스트 파일 옆에 있습니다.
스냅 샷 이름 : <UnitTestClassName>.<TestMethodName>.snap
새 스냅 샷 파일 __snapshots__/<UnitTestClassName>.<TestMethodName>.snap
이제 Snapshot.Match(person) 문은 테스트 결과의 스냅 샷을 다시 생성하고 __snapshots__ 폴더에서 검토 된 스냅 샷과 비교합니다. __snapshots__ 폴더는 항상 실행 된 단위 테스트 파일 옆에 있습니다.
결과 객체가 변경되었고 기존 스냅 샷이 더 이상 일치하지 않으면 장치 테스트가 실패합니다. 단위 테스트 오류 메시지는 스냅 샷 내에서 정확한 불일치 위치를 가리 킵니다.
또한 스냅 샷 폴더 __snapshots__ 에서 이름 __mismatch__ 가있는 하위 폴더가 생성됩니다. 이 폴더에서 __snapshots__ 폴더의 기존 스냅 샷과 일치하지 않는 실제 스냅 샷을 찾을 수 있습니다. 따라서 두 개의 스냅 샷을 텍스트 비교 도구와 비교할 수 있습니다.
불일치 폴더 __mismatch__ 의 스냅 샷이 올바른 경우 부모 __snapshots__ 폴더 (기존의 것을 재정의)로 이동하십시오.
더 읽으십시오
스냅 샷의 기본 일치 구문은 다음과 같습니다.
Snapshot . Match ( person ) ;그러나 유창한 구문을 사용할 수도 있습니다.
person . MatchSnapshot ( ) ;또는 fluentAssertion 's where () 구문을 사용할 수 있습니다.
person . Should ( ) . MatchSnapshot ( ) ;Nunit의 경우 우리는 Assert를 지원할 것입니다.이 구문 (곧 출시) :
Assert . That ( person , Match . Snapshot ( ) ) ; 스냅 샷 어설 션 중에 스냅 샷의 일부 필드가 무시되면 다음과 같은 무시 옵션을 사용할 수 있습니다.
[ Fact ]
public void CreatePersonSnapshot_IgnoreId ( )
{
// arrange
var serviceClient = new ServiceClient ( ) ;
// act
TestPerson person = serviceClient . CreatePerson ( "Hans" , "Muster" ) ;
// assert
Snapshot . Match < Person > ( testPerson , matchOptions => matchOptions . IgnoreField ( "Size" ) ) ;
}무시할 필드는 JSONPATH를 통해 위치되므로 매우 유연하며 자식 물체 나 배열에서 필드를 무시할 수도 있습니다.
예제를 무시하십시오 :
// Ignores the field 'StreetNumber' of the child node 'Address' of the person
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreField ( "Address.StreetNumber" ) ) ;
// Ignores the field 'Name' of the child node 'Country' of the child node 'Address' of the person
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreField ( "Address.Country.Name" ) ) ;
// Ignores the field 'Id' of the first person in the 'Relatives' array of the person
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreField ( "Relatives[0].Id" ) ) ;
// Ignores the field 'Name' of all 'Children' nodes of the person
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreField ( "Children[*].Name" ) ) ;
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreField ( "**.Id" ) ) ; 특정 이름으로 모든 필드를 무시하려면 두 가지 옵션이 있습니다.
옵션 1 : 무시 매치 옵션 'egineallfields ()'를 사용하고 이름을 추가하십시오.
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreAllFields ( "Id" ) ) ;옵션 2 : 다음 JSONPATH 구문 **과 함께 기본 무시 무시 옵션 'itcorefields (**.)'를 사용하십시오.
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreFields ( "**.Id" ) ) ;스냅 샷의 일부 필드가 너무 큰 경우, 예를 들어 많은 데이터가있는 이진 필드와 같은 해시 필드 옵션을 사용할 수 있습니다. 해시 필드 옵션은 필드 값의 해시를 생성하므로 매번 해시 만 비교됩니다. 필드 값이 변경되면 스냅 샷 일치가 실패합니다.
[ Fact ]
public void ImageSnapshot_HashImageBinary ( )
{
// arrange
var serviceClient = new ServiceClient ( ) ;
// act
TestImage image = serviceClient . CreateMonaLisaImage ( ) ;
// assert
Snapshot . Match ( image , matchOptions => matchOptions . HashField ( "Data" ) ) ;
}해시가있는 스냅 샷 예제
{
"Id" : 3450987 ,
"OwnerId" : " 0680faef-6e89-4d52-bad8-291053c66696 " ,
"Name" : " Mona Lisa " ,
"CreationDate" : " 2020-11-10T21:23:09.036+01:00 " ,
"Price" : 951868484.345 ,
"Data" : " m+sQR9KG9WpgYoQiRASPkt9FLJOLsjK86UuiXKVRzas= "
}필드에서 해시의 필드는 JSONPATH 또는 필드 이름을 통해 위치 할 수 있습니다.
해시 필드 예제 :
// Hash the field 'Data' of the child node 'Thumbnail' of the person
Snapshot . Match < Person > ( person , matchOptions => matchOptions . HashField ( "Thumbnail.Data" ) ) ;
// Hash the field 'Data' of the first thumbnail in the 'Thumbnails' array of the image
Snapshot . Match < Person > ( person , matchOptions => matchOptions . HashField ( "Thumbnails[0].Data" ) ) ;
// Ignores the field 'Data' of all 'Thumbnails' nodes of the image
Snapshot . Match < Person > ( person , matchOptions => matchOptions . HashField ( "Thumbnails[*].Data" ) ) ;
// Ignores all fields with name 'Data'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . HashField ( "**.Data" ) ) ;때로는 스냅 샷에 필드가 있으며 다른 값에 대해 별도로 주장하고자합니다.
예를 들어, '사람'의 ID 필드는 항상 서비스에서 새로 생성되므로 테스트에서 항상 새로운 ID (Guid)를 가진 사람을받습니다. 이제 ID가 빈 안내서가 아닌지 확인하려면 Assert 옵션을 사용할 수 있습니다.
/// <summary>
/// Tests if the new created person is valid and the person id is not empty.
/// </summary>
[ Fact ]
public void CreatePersonSnapshot_AssertId ( )
{
// arrange
var serviceClient = new ServiceClient ( ) ;
// act
TestPerson person = serviceClient . CreatePerson ( "Hans" , "Muster" ) ; // --> id is created within the service
// assert
Snapshot . Match < Person > ( testPerson , matchOption => matchOption . Assert (
fieldOption => Assert . NotEqual ( Guid . Empty , fieldOption . Field < Guid > ( "Id" ) ) ) ) ;
}주장 할 분야는 JSONPATH를 통해 위치되므로 매우 유연하며 자식 물체 나 배열에서 필드를 무시할 수도 있습니다.
주장 예 :
// Assert the field 'Street' of the 'Address' of the person
Snapshot . Match < Person > ( person , matchOption => matchOption . Assert (
fieldOption => Assert . Equal ( 15 , fieldOption . Field < int > ( "Address.StreetNumber" ) ) ) ) ;
// Asserts the field 'Code' of the field 'Country' of the 'Address' of the person
Snapshot . Match < Person > ( person , matchOption => matchOption . Assert (
fieldOption => Assert . Equal ( "De" , fieldOption . Field < CountryCode > ( "Address.Country.Code" ) ) ) ) ;
// Asserts the fist 'Id' field of the 'Relatives' array of the person
Snapshot . Match < Person > ( person , > matchOption . Assert (
fieldOption => Assert . NotNull ( fieldOption . Field < string > ( "Relatives[0].Id" ) ) ) ) ;
// Asserts every 'Id' field of all the 'Relatives' of the person
Snapshot . Match < Person > ( person , > matchOption . Assert (
fieldOption => Assert . NotNull ( fieldOption . Fields < string > ( "Relatives[*].Id" ) ) ) ) ;
// Asserts 'Relatives' array is not empty
Snapshot . Match < Person > ( person , > matchOption . Assert (
fieldOption => Assert . NotNull ( fieldOption . Fields < TestPerson > ( "Relatives[*]" ) ) ) ) ;Snapshooter Assert 기능은 Xunit 또는 Nunit Asserts에 국한되지 않으며 유창한 주장이나 다른 주장 도구를 사용할 수도 있습니다.
모든 무시, ISTYPE 또는 ASSERT 필드 검사를 연결할 수 있습니다.
[ Fact ]
public void Match_ConcatenateFieldChecksTest_SuccessfulMatch ( )
{
// arrange
var serviceClient = new ServiceClient ( ) ;
// act
TestPerson person = serviceClient . CreatePerson ( "Hans" , "Muster" ) ;
// act & assert
Snapshot . Match < TestPerson > ( testPerson , matchOption => matchOption
. Assert ( option => Assert . NotEqual ( Guid . Empty , option . Field < Guid > ( "Id" ) ) )
. IgnoreField < DateTime > ( "CreationDate" )
. Assert ( option => Assert . Equal ( - 58 , option . Field < int > ( "Address.StreetNumber" ) ) )
. Assert ( option => testChild . Should ( ) . BeEquivalentTo ( option . Field < TestChild > ( "Children[3]" ) ) )
. IgnoreField < TestCountry > ( "Address.Country" )
. Assert ( option => Assert . Null ( option . Field < TestCountry > ( "Relatives[0].Address.Plz" ) ) ) ) ;
} Ci-Build에서 스냅 샷 테스트를 실행할 때 스냅 샷없이 테스트하면 초기 스냅 샷을 생성하고 녹색이되므로 스냅 샷이 올바르게 체크인되는지 확인할 수 있습니다.
CI 건물에 스냅 샷이없는 테스트에 실패하려면 환경 변수 SNAPSHOOTER_STRICT_MODE on 또는 true 로 설정하여 스냅 샷 동작을 엄격한 모드로 설정할 수 있습니다.
이 프로젝트는 기고자 언약이 정의한 행동 강령을 채택하여 지역 사회에서 예상되는 행동을 명확히했습니다. 자세한 내용은 스위스 생활 OSS 행동 강령을 참조하십시오.