Snapshooter هي أداة اختبار لقطة لـ .NET Core و .NET Framework
Snapshooter هي أداة اختبار لقطة مرنة لتبسيط التحقق من صحة النتيجة في اختبارات وحدتك في .NET. يعتمد على فكرة اختبار اللقطة الدائرية.
للحصول على مزيد من المعلومات التفصيلية حول Snapshooter ، انتقل إلى مستندات Snapshooter
للبدء ، قم بتثبيت حزمة Snapshooter Xunit أو Nunit Nuget:
dotnet add package Snapshooter.Xunitdotnet add package Snapshooter.NUnitdotnet add package Snapshooter.MSTestابدأ
لتأكيد نتائج الاختبار الخاصة بك باستخدام لقطات في اختبارات وحدتك ، اتبع الخطوات التالية:
أدخل لقطة Affrice 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__ دائمًا بجوار ملف اختبار الوحدة الذي تم تنفيذه.
إذا تغير كائنك الناتج ولم تعد اللقطة الموجودة متطابقة بعد الآن ، فسوف يفشل اختبار الوحدة. ستشير رسالة خطأ اختبار الوحدة إلى وضع عدم التوافق الدقيق داخل اللقطة.
بالإضافة إلى ذلك ، في مجلد Snapshot __snapshots__ سيتم إنشاء مقلوب فرعي يحمل اسم __mismatch__ . في هذا المجلد ، يمكنك العثور على اللقطة الفعلية التي لا تتناسب مع اللقطة الموجودة في مجلد __snapshots__ . لذلك من الممكن مقارنة اللقطتين باستخدام أداة مقارنة النص.
إذا كانت اللقطة في المجلد غير المتطابق __mismatch__ صحيحة ، فما عليك سوى نقلها إلى المجلد الأصل __snapshots__ (تجاوز المجلد الموجود).
اقرأ المزيد
بناء جملة المطابقة الافتراضي للقطات هو:
Snapshot . Match ( person ) ;ومع ذلك ، يمكننا أيضًا استخدام بناء الجملة بطلاقة:
person . MatchSnapshot ( ) ;أو يمكننا استخدام بناء الجملة Fluentassertion ():
person . Should ( ) . MatchSnapshot ( ) ;بالنسبة إلى NUNIT ، سندعم التأكيد. بناء الجملة (قريبًا):
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: استخدم خيار تجاهل MANTER 'MAGNOREALFIELDS ()' وأضف الاسم.
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreAllFields ( "Id" ) ) ;الخيار 2: استخدم خيار التجاهل الافتراضي "تجاهل Fields (**.)" مع بناء جملة JsonPath التالي **.
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreFields ( "**.Id" ) ) ;إذا كانت بعض الحقول من اللقطات لدينا كبيرة جدًا ، على سبيل المثال حقل ثنائي يحتوي على الكثير من البيانات ، فيمكننا استخدام خيار HashField. يخلق خيار HashField تجزئة من قيمة الحقل ، وبالتالي في كل مرة تتم مقارنة التجزئة فقط. إذا كان هناك تغيير في قيمة الحقل ، فسوف تفشل مطابقة اللقطة.
[ 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" ) ) ;في بعض الأحيان ، توجد حقول في لقطة ، والتي تريد تأكيدها بشكل منفصل مقابل قيمة أخرى.
على سبيل المثال ، يتم إنشاء حقل المعرف الخاص بـ "الشخص" حديثًا في الخدمة ، وبالتالي تتلقى في الاختبار دائمًا شخصًا يعاني من معرف جديد (GUID). الآن إذا كنت تريد التحقق من أن المعرف ليس بمثابة GUID فارغ ، فيمكن استخدام خيار 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 على تأكيدات Xunit أو Nunit ، كما يمكن استخدامها تأكيدات بطلاقة أو أداة تأكيد أخرى.
يمكن تسلسل جميع عمليات التجاهل أو Istype أو Assert Field.
[ 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" ) ) ) ) ;
} عند إجراء اختبارات Snapshooter في بناء CI ، قد ترغب في التأكد من فحص لقطات بشكل صحيح نظرًا لأن الاختبارات التي لا يمكن اختباراتها بدون لقطة ستنشئ فقط اللقطة الأولية وتصبح خضراء.
من أجل فشل الاختبارات التي لا توجد فيها لقطة على CI-Build ، يمكنك تعيين سلوك SnapShooter على وضع صارم عن طريق تعيين البيئة المتغير SNAPSHOOTER_STRICT_MODE إلى on أو true .
اعتمد هذا المشروع مدونة السلوك التي حددها العهد المساهم لتوضيح السلوك المتوقع في مجتمعنا. لمزيد من المعلومات ، راجع قواعد سلوك Swiss Life OSS.