การทดสอบหน่วยถือว่ามีความเปราะหรือไม่ถ้ามันล้มเหลวเมื่อตรรกะทางธุรกิจเปลี่ยนไป?


27

โปรดดูรหัสด้านล่าง; มันทดสอบเพื่อดูว่าบุคคลที่มีเพศหญิงมีสิทธิ์ได้รับข้อเสนอ 1:

[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
    var personId = Guid.NewGuid();
    var gender = "F";
    var person = new Person(personId, gender);

    var id = Guid.NewGuid();
    var offer1 = new Offer1(id,"Offer1");
    Assert.False(offer1.IsEligible(person));
}

การทดสอบหน่วยนี้สำเร็จ อย่างไรก็ตามจะล้มเหลวหากมีการเสนอ 'Offer1' ให้กับสตรีในอนาคต

เป็นที่ยอมรับหรือไม่ - ถ้าตรรกะทางธุรกิจโดยรอบเสนอ 1 การเปลี่ยนแปลงการทดสอบหน่วยจะต้องเปลี่ยน โปรดทราบว่าในบางกรณี (สำหรับข้อเสนอบางอย่าง) ตรรกะทางธุรกิจจะเปลี่ยนไปในฐานข้อมูลเช่นนี้:

update Offers set Gender='M' where offer=1;

และในบางกรณีในรูปแบบโดเมนเช่นนี้:

if (Gender=Gender.Male)
{
  //do something
}

โปรดทราบว่าในบางกรณีตรรกะโดเมนที่อยู่เบื้องหลังมีการเปลี่ยนแปลงเป็นประจำและในบางกรณีก็ไม่ได้เป็นเช่นนั้น


2
คิดจากอีกมุมมองหนึ่ง: คุณต้องการให้มีการทดสอบที่ไม่ล้มเหลวเมื่อคุณเปลี่ยนตรรกะในระบบภายใต้การทดสอบหรือไม่?
Fabio

คำตอบ:


77

นี่ไม่เปราะตามความหมายปกติ การทดสอบหน่วยจะถือว่าเปราะถ้ามันแตกเนื่องจากการเปลี่ยนแปลงการใช้งานที่ไม่ส่งผลกระทบต่อพฤติกรรมภายใต้การทดสอบ แต่ถ้าตรรกะทางธุรกิจของตัวเองเปลี่ยนแปลงแล้วการทดสอบตรรกะนี้ควรจะทำลาย

ที่กล่าวว่าหากตรรกะทางธุรกิจมีการเปลี่ยนแปลงบ่อยครั้งบางทีอาจเป็นการไม่เหมาะสมที่จะเข้ารหัสความคาดหวังในการทดสอบหน่วย แต่คุณสามารถทดสอบว่าการกำหนดค่าในฐานข้อมูลมีผลต่อข้อเสนอตามที่คาดไว้หรือไม่

ชื่อของการทดสอบReturns False When Given A Person With A Gender Of Femaleไม่ได้อธิบายถึงกฎธุรกิจ กฎทางธุรกิจจะเป็นอะไรที่คล้ายOffers Applicable to M should not be applied to persons of gender Fกัน

ดังนั้นคุณสามารถเขียนการทดสอบที่ยืนยันว่าหากมีการกำหนดข้อเสนอพิเศษสำหรับผู้พิมพ์ M เท่านั้นบุคคลประเภท F จะไม่ถูกระบุว่ามีคุณสมบัติเหมาะสม การทดสอบนี้จะตรวจสอบให้แน่ใจว่าตรรกะทำงานแม้ว่าการกำหนดค่าของข้อเสนอเฉพาะจะเปลี่ยนแปลง


@ JaquesB ถ้าเช่นนั้นมันจะไม่เป็นการทดสอบหน่วย หรือมันจะ? ฉันเชื่อว่ามันจะเป็นการทดสอบการรวมระบบหากฐานข้อมูลมีส่วนเกี่ยวข้อง นั่นถูกต้องใช่ไหม? คุณกำลังบอกว่าอย่าใช้การทดสอบหน่วยหากตรรกะทางธุรกิจเปลี่ยนแปลงไปมาก
w0051977

@ w0051977: ขึ้นอยู่กับว่าคุณเขียนแบบทดสอบอย่างไร หากการทดสอบรวมถึงการเปลี่ยนแปลงสิ่งที่เปลี่ยนแปลงในฐานข้อมูลจริง ๆ แล้วก็เป็นการทดสอบการรวม
JacquesB

3
@ w0051977 แนวความคิดที่ดีกว่า - ไม่มีที่เก็บให้เป็นการพึ่งพาของส่วนประกอบที่รับผิดชอบในการใช้กฎเกณฑ์ทางธุรกิจ มี orchestration ระดับสูงกว่าที่เรียกที่เก็บจากนั้นเรียกใช้กฎธุรกิจ ตอนนี้คุณสามารถทดสอบกฎธุรกิจแบบแยกได้
Ant P

5
@ w0051977 แน่นอนว่าเป็น - การทดสอบระบุพฤติกรรม หากกฎที่ควบคุมพฤติกรรมของการเปลี่ยนแปลงองค์ประกอบแล้วการทดสอบจะต้องเปลี่ยนเพื่อสะท้อนให้เห็นถึงการเปลี่ยนแปลงในพฤติกรรม สิ่งที่ไม่จำเป็นต้องเปลี่ยนคือการทดสอบที่ระบุพฤติกรรมนอกเหนือจากสิ่งที่เปลี่ยนแปลง หากพฤติกรรมถูกกำหนดโดยฐานข้อมูลการทดสอบที่ครอบคลุมรหัสอื่น ๆ นั้นจะไม่เกี่ยวข้องโดยเนื้อแท้และไม่จำเป็นต้องเปลี่ยนแปลงเว้นแต่ว่าตรรกะฐานข้อมูลนั้นอยู่ในขอบเขตของการทดสอบ ขอบเขตนั้นมีไว้สำหรับคุณในการกำหนดและความหมายของการทดสอบหน่วยหรือการทดสอบการรวมนั้นไม่สำคัญ
Ant P

3
@ w0051977 การขยายความคิดนี้ถ้าการเปลี่ยนแปลงตรรกะทางธุรกิจหรือข้อผิดพลาดได้รับการแก้ไขและการทดสอบไม่จำเป็นต้องปรับมันเป็นสัญญาณว่าการทดสอบไม่ครอบคลุมกรณีที่เพียงพอและโดยทั่วไปควรจะขยาย
Morgen

14

เมื่อทรัพย์สินที่ถูกกำหนดไว้ในฐานข้อมูลการผลิต (หรือโคลนสำหรับการทดสอบ) นี้ไม่ได้เป็นหน่วยทดสอบ การทดสอบหน่วยตรวจสอบหน่วยงานและไม่ต้องใช้สถานะภายนอกโดยเฉพาะในการทำงาน สมมติว่าOffer1มีการกำหนดไว้ในฐานข้อมูลว่าเป็นข้อเสนอสำหรับผู้ชายเท่านั้น นั่นคือสถานะภายนอก ดังนั้นนี่คือการทดสอบการรวมมากขึ้นโดยเฉพาะระบบหรือการทดสอบการยอมรับ โปรดทราบว่าการทดสอบการยอมรับมักไม่ได้ถูกเขียนสคริปต์ (ไม่ได้ทำงานในกรอบการทดสอบ แต่ดำเนินการโดยมนุษย์ด้วยตนเอง)

เมื่อคุณสมบัติถูกกำหนดในรูปแบบโดเมนที่มีifคำสั่งการทดสอบเดียวกันเป็นการทดสอบหน่วย และมันอาจจะเปราะ แต่ปัญหาที่แท้จริงคือรหัสนั้นเปราะ ตามกฎทั่วไปรหัสของคุณจะมีความยืดหยุ่นมากขึ้นถ้าพฤติกรรมทางธุรกิจสามารถกำหนดค่าได้แทนที่จะเป็นรหัสฮาร์ด เนื่องจากการปรับใช้แบบเร่งด่วนเพื่อแก้ไขข้อผิดพลาดการเข้ารหัสขนาดเล็กควรเป็นของหายาก แต่ความต้องการทางธุรกิจที่เปลี่ยนแปลงโดยไม่ต้องแจ้งให้ทราบล่วงหน้าเป็นเพียงวันอังคาร (สิ่งที่เกิดขึ้นทุกสัปดาห์)

คุณอาจใช้กรอบการทดสอบหน่วยเพื่อรันการทดสอบ แต่กรอบการทดสอบหน่วยไม่ จำกัด เฉพาะการรันการทดสอบหน่วย พวกเขาสามารถและรันการทดสอบการรวมได้เช่นกัน

หากคุณกำลังเขียนการทดสอบหน่วยคุณจะสร้างทั้งสองpersonและoffer1จากพื้นดินขึ้นโดยไม่ต้องพึ่งพาสถานะฐานข้อมูล สิ่งที่ต้องการ

[Fact]
public void ReturnsFalseWhenGivenAPersonWithAGenderOfFemale()
{
    var personId = Guid.NewGuid();
    var gender = "F";
    var person = new Person(personId, gender);

    var id = Guid.NewGuid();
    var offer1 = new Offer1(id, "ReturnsFalseWhenGivenAPersonWithAGenderOfFemale");
    offer1.markLimitedToGender("M");

    Assert.False(offer1.IsEligible(person));
}

โปรดทราบว่าสิ่งนี้จะไม่เปลี่ยนแปลงตามตรรกะทางธุรกิจ มันไม่ยืนยันว่าจะoffer1ปฏิเสธผู้หญิง มันกำลังทำoffer1ข้อเสนอประเภทที่ปฏิเสธผู้หญิง

คุณอาจสร้างและกำหนดค่าฐานข้อมูลเป็นส่วนหนึ่งของการทดสอบ ใน C # โดยใช้ NUnit หรือใน JUnit ของ Java คุณต้องตั้งค่าฐานข้อมูลในSetupเมธอด สมมุติว่ากรอบการทดสอบของคุณมีความคิดคล้ายกัน ในวิธีการนั้นคุณสามารถแทรกบันทึกลงในฐานข้อมูลด้วย SQL

ถ้ามันยากสำหรับคุณที่จะเขียนโค้ดที่ใช้แทนฐานข้อมูลทดสอบสำหรับฐานข้อมูลการผลิตนั่นฟังดูเหมือนจุดอ่อนในการทดสอบในแอปพลิเคชันของคุณ สำหรับการทดสอบมันจะดีกว่าถ้าใช้บางอย่างเช่นการฉีดแบบพึ่งพาที่ยอมให้มีการทดแทน จากนั้นคุณสามารถเขียนการทดสอบที่เป็นอิสระจากกฎเกณฑ์ทางธุรกิจในปัจจุบัน

ข้อดีข้างเคียงของสิ่งนี้ก็คือมันมักจะง่ายกว่าสำหรับเจ้าของธุรกิจ (ไม่จำเป็นต้องเป็นเจ้าขององค์กรเช่นเดียวกับผู้รับผิดชอบผลิตภัณฑ์นี้ในลำดับชั้นขององค์กร) เพื่อกำหนดค่ากฎทางธุรกิจโดยตรง เพราะถ้าคุณมีกรอบทางเทคนิคประเภทนี้มันเป็นเรื่องง่ายที่จะอนุญาตให้เจ้าของธุรกิจใช้ส่วนต่อประสานผู้ใช้ (UI) เพื่อกำหนดค่าข้อเสนอ เจ้าของธุรกิจจะเลือกข้อ จำกัด ใน UI และมันจะออกmarkLimitedToGender("M")สาย จากนั้นเมื่อข้อเสนอยังคงอยู่กับฐานข้อมูลก็จะเก็บสิ่งนี้ แต่คุณไม่จำเป็นต้องจัดเก็บข้อเสนอพิเศษเพื่อใช้งาน ดังนั้นการทดสอบของคุณสามารถสร้างและกำหนดค่าข้อเสนอที่ไม่มีอยู่ในฐานข้อมูล

ในระบบของคุณตามที่อธิบายไว้เจ้าของธุรกิจจะต้องส่งคำขอไปยังกลุ่มทางเทคนิคซึ่งจะออก SQL ที่เหมาะสมและอัปเดตการทดสอบ หรือกลุ่มเทคนิคต้องแก้ไขรหัสและการทดสอบของคุณ (หรือการทดสอบแล้วรหัส) นั่นเป็นวิธีที่ค่อนข้างหนา คุณสามารถทำมันได้. แต่ซอฟต์แวร์ของคุณ (ไม่ใช่แค่การทดสอบของคุณ) จะเปราะน้อยกว่าถ้าคุณไม่ต้องทำเช่นนั้น

TL; DR : คุณสามารถเขียนแบบทดสอบนี้ได้ แต่คุณอาจจะดีกว่าที่จะเขียนซอฟต์แวร์ของคุณเพื่อที่คุณจะได้ไม่ต้องทำเช่นนั้น


ฉันเป็นเครื่องมืออิสระในการปรับปรุงรายละเอียดเล็กน้อยในคำตอบของคุณ โปรดตรวจสอบว่าฉันมีความตั้งใจของคุณถูกต้องหรือไม่
Doc Brown

ไม่มีข้อบ่งชี้ในโพสต์ต้นฉบับที่เกี่ยวข้องกับฐานข้อมูล ดังนั้นการอ้างว่ามันเสนอว่า Offer1 มีอยู่แล้วในฐานข้อมูลนั้นแปลกประหลาด
Winston Ewert

2
@ WinstonEwert: มีข้อบ่งชี้ชัดเจนคุณต้องอ่านคำถามให้ละเอียดยิ่งขึ้น ฉันไม่ได้ตระหนักถึงมันในการอ่านครั้งแรกเช่นกัน แต่มันก็เป็นสิ่งที่ OP กำลังพูดถึง
Doc Brown

@ mdfst13 ฉันขอโทษที่ฉันพลาดไป อย่างไรก็ตามสิ่งที่ OP กล่าวคือเงื่อนไขบางครั้งในฐานข้อมูลและบางครั้งในโมเดลโดเมน คำตอบของคุณดีมากสำหรับคดีแรกและไม่เคารพในกรณีที่สอง หากคุณจะแก้ไขคำตอบของคุณเพื่อชี้แจงจุดนั้นฉันจะลบ downvote ที่รีบร้อนของฉัน
Winston Ewert
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.