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เริ่มต้นใช้งาน
หากต้องการยืนยันผลการทดสอบของคุณด้วยสแน็ปช็อตในการทดสอบหน่วยของคุณให้ทำตามขั้นตอนต่อไปนี้:
แทรกคำสั่ง snapshot assert 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
ตรวจสอบไฟล์ snapshot ใหม่ของคุณ __snapshots__/<UnitTestClassName>.<TestMethodName>.snap
ตอนนี้คำสั่ง Snapshot.Match(person) จะสร้างสแน็ปช็อตของผลการทดสอบของคุณอีกครั้งและเปรียบเทียบกับสแนปชอตที่ตรวจสอบของคุณในโฟลเดอร์ __snapshots__ โฟลเดอร์ __snapshots__ อยู่ติดกับไฟล์ทดสอบหน่วยที่ดำเนินการของคุณเสมอ
หากวัตถุผลลัพธ์ของคุณมีการเปลี่ยนแปลงและสแน็ปช็อตที่มีอยู่ไม่ตรงกันอีกต่อไปการทดสอบหน่วยจะล้มเหลว ข้อความแสดงข้อผิดพลาดในการทดสอบหน่วยจะชี้ไปที่ตำแหน่งที่ไม่ตรงกันที่แน่นอนภายในสแน็ปช็อต
นอกจากนี้ในโฟลเดอร์ Snapshot __snapshots__ โฟลเดอร์ย่อยที่มีชื่อ __mismatch__ จะถูกสร้างขึ้น ในโฟลเดอร์นี้คุณสามารถค้นหาสแน็ปช็อตจริงซึ่งไม่ตรงกันกับสแน็ปช็อตที่มีอยู่ในโฟลเดอร์ __snapshots__ ดังนั้นจึงเป็นไปได้ที่จะเปรียบเทียบสแน็ปช็อตทั้งสองกับเครื่องมือเปรียบเทียบข้อความ
หากสแน็ปช็อตในโฟลเดอร์ที่ไม่ตรงกัน __mismatch__ ถูกต้องเพียงแค่ย้ายไปที่โฟลเดอร์ parent __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: ใช้ตัวเลือกการจับคู่ที่ไม่สนใจ 'ไม่รู้ ()' และเพิ่มชื่อ
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreAllFields ( "Id" ) ) ;ตัวเลือกที่ 2: ใช้ตัวเลือกการจับคู่เริ่มต้น 'เพิกเฉยฟิลด์ (**.)' กับไวยากรณ์ JSONPath ต่อไปนี้ **
// Ignores all fields with name 'Id'
Snapshot . Match < Person > ( person , matchOptions => matchOptions . IgnoreFields ( "**.Id" ) ) ;หากบางฟิลด์ของภาพรวมของเรามีขนาดใหญ่เกินไปตัวอย่างเช่นฟิลด์ไบนารีที่มีข้อมูลจำนวนมากเราสามารถใช้ตัวเลือก 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" ) ) ;บางครั้งมีฟิลด์ในภาพรวมซึ่งคุณต้องการยืนยันแยกต่างหากจากค่าอื่น
ตัวอย่างเช่นฟิลด์ ID ของ 'บุคคล' ถูกสร้างขึ้นใหม่เสมอในบริการดังนั้นคุณจะได้รับในการทดสอบเสมอบุคคลที่มี ID ใหม่ (GUID) ตอนนี้หากคุณต้องการตรวจสอบว่า ID ไม่ใช่ 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 Assert ไม่ได้ จำกัด อยู่ที่ XUNIT หรือ NUNIT ยืนยัน แต่ก็สามารถใช้การยืนยันที่คล่องแคล่วหรือเครื่องมือยืนยันอื่น
การตรวจสอบการตรวจสอบฟิลด์ Istype หรือการยืนยันทั้งหมดทั้งหมดสามารถต่อกันได้
[ 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-Build คุณอาจต้องการให้แน่ใจว่าสแน็ปช็อตได้รับการตรวจสอบอย่างถูกต้องเนื่องจากการทดสอบมิฉะนั้นโดยไม่มีสแน็ปช็อตจะสร้างสแน็ปช็อตเริ่มต้นและกลายเป็นสีเขียว
เพื่อที่จะล้มเหลวในการทดสอบที่ไม่มีภาพรวมบน CI-Build ของคุณคุณสามารถตั้งค่าพฤติกรรม snapshooter เป็นโหมดที่เข้มงวดโดยการตั้งค่าตัวแปรสภาพแวดล้อม SNAPSHOOTER_STRICT_MODE เป็น on หรือ true
โครงการนี้ได้นำจรรยาบรรณที่กำหนดโดยพันธสัญญาผู้สนับสนุนเพื่อชี้แจงพฤติกรรมที่คาดหวังในชุมชนของเรา สำหรับข้อมูลเพิ่มเติมดูจรรยาบรรณ OSS Life OSS