Sapthooter es una herramienta de prueba de instantáneas para .NET Core y .NET Framework
SnapShooter es una herramienta de prueba de instantánea flexible para simplificar la validación de resultados en sus pruebas unitarias en .NET. Se basa en la idea de las pruebas de instantáneas de Jest.
Para obtener información más detallada sobre Sapthooter, vaya a los documentos de Sapthooter
Para comenzar, instale el paquete Snapshooter XUnit o Nunit Nuget:
dotnet add package Snapshooter.Xunitdotnet add package Snapshooter.NUnitdotnet add package Snapshooter.MSTestEmpezar
Para afirmar los resultados de su prueba con instantáneas en sus pruebas unitarias, siga los siguientes pasos:
Insertar una instantánea afirmar la instrucción Snapshot.Match(yourResultObject); en su prueba unitaria.
Ejemplo:
/// <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 ) ;
} La instrucción Snapshot.Match(person) crea una nueva instantánea de su objeto de resultados y lo almacena en la carpeta __snapshots__ . La carpeta __snapshots__ siempre está al lado de su archivo de prueba unitario ejecutado.
Nombre de la instantánea: <UnitTestClassName>.<TestMethodName>.snap
Revise su nuevo archivo de instantánea __snapshots__/<UnitTestClassName>.<TestMethodName>.snap .
Ahora, la declaración Snapshot.Match(person) volverá a crear una instantánea del resultado de su prueba y lo comparará con su instantánea revisada en la carpeta __snapshots__ . La carpeta __snapshots__ siempre está al lado de su archivo de prueba unitario ejecutado.
Si su objeto de resultado ha cambiado y la instantánea existente ya no coincide, entonces la prueba unitaria fallará. El mensaje de error de prueba unitario apuntará a la posición de desajuste exacta dentro de la instantánea.
Además, en la carpeta de instantánea __snapshots__ se creará una subcarpeta con nombre __mismatch__ . En esta carpeta, puede encontrar la instantánea real que no coincide con la instantánea existente en la carpeta __snapshots__ . Por lo tanto, es posible comparar las dos instantáneas con una herramienta de comparación de texto.
Si la instantánea en la carpeta de falta de coincidencia __mismatch__ es correcta, solo muévala a la carpeta __snapshots__ parental (anule la existente).
Leer más
La sintaxis de coincidencia predeterminada para las instantáneas es:
Snapshot . Match ( person ) ;Sin embargo, también podríamos usar la sintaxis fluida:
person . MatchSnapshot ( ) ;O podemos usar la sintaxis de FluentAspertion debería ():
person . Should ( ) . MatchSnapshot ( ) ;Para Nunit apoyaremos la afirmación. Esa sintaxis (próximamente):
Assert . That ( person , Match . Snapshot ( ) ) ; Si algunos campos en su instantánea se ignoran durante la afirmación de la instantánea, entonces se pueden usar las siguientes opciones de ignorar:
[ 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" ) ) ;
}Los campos para ignorar se ubicarán a través de JSONPATH, por lo tanto, usted es muy flexible y también puede ignorar los campos de objetos o matrices de niños.
Ignorar ejemplos:
// 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" ) ) ; Si queremos ignorar todos los campos por un nombre específico, entonces tenemos dos opciones:
Opción 1: Use la opción Ignore Match 'IgnoreAllFields ()' y agregue el nombre.
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreAllFields ( "Id" ) ) ;Opción 2: use la opción de coincidencia de ignoración predeterminada 'IgnoreFields (**.)' Con la siguiente sintaxis jsonpath **.
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreFields ( "**.Id" ) ) ;Si algunos campos de nuestra instantánea son demasiado grandes, por ejemplo, un campo binario con muchos datos, entonces podemos usar la opción Hashfield. La opción Hashfield crea un hash del valor del campo y, por lo tanto, cada vez que solo se compara el hash. Si hay un cambio en el valor de campo, la coincidencia de instantáneas fallará.
[ Fact ]
public void ImageSnapshot_HashImageBinary ( )
{
// arrange
var serviceClient = new ServiceClient ( ) ;
// act
TestImage image = serviceClient . CreateMonaLisaImage ( ) ;
// assert
Snapshot . Match ( image , matchOptions => matchOptions . HashField ( "Data" ) ) ;
}Ejemplo de instantánea con hash
{
"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= "
}Los campos (s) al hash se pueden ubicar a través de JSONPATH o por nombre de campo.
Ejemplos de campo hash:
// 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" ) ) ;A veces hay campos en una instantánea, que debes afirmar por separado contra otro valor.
Por ejemplo, el campo de identificación de una 'persona' siempre se genera recientemente en un servicio, por lo tanto, usted recibe en la prueba siempre una persona con una nueva identificación (GUID). Ahora, si desea verificar que la ID no sea un GUID vacío, se puede usar la opción 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" ) ) ) ) ;
}Los campos para afirmar se ubicarán a través de JSONPATH, por lo tanto, usted es muy flexible y también puede ignorar los campos de objetos o matrices de niños.
Afirmar ejemplos:
// 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[*]" ) ) ) ) ;La funcionalidad de afirmación de Snapshooter no se limita a XUNIT o Nunit Afirma, también podría usarse afirmaciones fluidas u otra herramienta de afirmación.
Todas las verificaciones de campo Ignore, IsType o Afirman se pueden concatenar.
[ 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" ) ) ) ) ;
} Al ejecutar las pruebas de SaptShooter en una construcción de CI, es posible que desee asegurarse de que las instantáneas se registren correctamente, ya que de lo contrario las pruebas sin una instantánea simplemente crean la instantánea inicial y se volverá verde.
Para fallar las pruebas que no tienen una instantánea en su CI-Build, puede establecer el comportamiento de SnapShooter en modo estricto estableciendo la variable de entorno SNAPSHOOTER_STRICT_MODE en on o true .
Este proyecto ha adoptado el Código de Conducta definido por el Pacto de contribuyente para aclarar el comportamiento esperado en nuestra comunidad. Para obtener más información, consulte el Código de Conducta Swiss Life Oss.