เป็นการปฏิบัติที่ไม่ถูกต้องหรือไม่ในการบังคับใช้คำสั่งการเรียกใช้การทดสอบหน่วย?


84

ฉันกำลังเขียนการทดสอบสำหรับโครงการที่ประกอบด้วยหลาย submodules กรณีทดสอบแต่ละข้อที่ฉันเขียนขึ้นจะทำงานแยกกันและฉันจะล้างข้อมูลทั้งหมดระหว่างการทดสอบ

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

ฉันไม่สามารถทำงานกับข้อมูลจำลองได้เนื่องจากฟังก์ชั่นหลักที่ฉันกำลังทดสอบคือการเชื่อมต่อกับเซิร์ฟเวอร์ระยะไกลกล่องดำซึ่งรับเฉพาะข้อมูลจาก submodule แรกเท่านั้น

ในกรณีนี้มันตกลงเพื่อบังคับใช้คำสั่งการดำเนินการสำหรับการทดสอบหรือมันเป็นการปฏิบัติที่ไม่ดี? ฉันรู้สึกว่ามีกลิ่นในการตั้งค่านี้ แต่ฉันไม่สามารถหาวิธีที่ดีกว่า

แก้ไข: คำถามมาจากวิธีการจัดโครงสร้างการทดสอบที่การทดสอบหนึ่งเป็นการตั้งค่าการทดสอบอื่น? เนื่องจากการทดสอบ "ก่อนหน้า" ไม่ใช่การตั้งค่า แต่ทดสอบรหัสที่ดำเนินการตั้งค่า



123
หากคุณกำลังทดสอบการเชื่อมต่อกับเซิร์ฟเวอร์ระยะไกลแสดงว่าพวกเขากำลังทดสอบการกำหนดไม่ใช่การทดสอบหน่วย
Telastyn

9
คำตอบแรกทำให้ฉันสับสนที่นี่เพราะในชื่อของคุณคุณพูดว่า และในบทสรุปของคำถามของคุณคุณเขียนว่า "ไม่เป็นไร" ใครก็ตามที่ตอบว่าใช่หรือไม่ใช่จะทำให้ใครคนหนึ่งสับสน!
Liath

8
ดูเหมือนว่าคุณกำลังสร้างชุดการทดสอบการรวมระบบ แม้แต่การทดสอบครั้งเดียวก็ไม่ควรใช้การทดสอบอื่น
นกกระทุงบินต่ำ

17
หากคำสั่งซื้อนั้นสำคัญคุณอาจทำผิด
Mark Rogers

คำตอบ:


236

ฉันไม่สามารถทำงานกับข้อมูลจำลองได้เนื่องจากฟังก์ชั่นหลักที่ฉันกำลังทดสอบคือการเชื่อมต่อกับเซิร์ฟเวอร์ระยะไกลกล่องดำซึ่งรับเฉพาะข้อมูลจาก submodule แรกเท่านั้น

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

แต่มันก็คุ้มค่าที่จะพิจารณารูปลักษณ์ใหม่ของโครงสร้างแอปของคุณ ความสามารถในการเยาะเย้ย submodule แรกและเซิร์ฟเวอร์ภายนอกนั้นอาจช่วยให้คุณสามารถเขียนการทดสอบหน่วยที่แท้จริงสำหรับ submodules อื่น ๆ ทั้งหมด


14
ไม่ต้องพูดถึงว่าการทดสอบบางอย่างต้องตรวจสอบโดยเฉพาะว่าพฤติกรรมที่คาดหวังเกิดขึ้นเมื่อเซิร์ฟเวอร์ระยะไกลไม่พร้อมใช้งาน
Alexander

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

10
ปัญหาน่าจะเป็นที่ Junit มี "หน่วย" อยู่ในชื่อ
Thorbjørn Ravn Andersen

7
@ ThorbjørnRavnAndersenอย่างแน่นอน คนทั่วไปเขียนการทดสอบการรวมมากกว่าการทดสอบหน่วยเพราะการทดสอบการรวมนั้นมีประโยชน์มากกว่าและยากต่อการเขียนน้อยกว่าการทดสอบหน่วย "ของจริง" แต่เนื่องจากกรอบการทดสอบที่ได้รับความนิยมนั้นได้รับการตั้งชื่อตามแนวคิดของการทดสอบหน่วยคำศัพท์จึงถูกเลือกให้เข้าร่วมและหมายถึง "การทดสอบอัตโนมัติใด ๆ " ในสำนวนภาษาสมัยใหม่
Mason Wheeler

1
@MasonWheeler หรือแม้กระทั่งได้ร่วมกับผู้จัดการด้านเทคนิคเพื่อทำการทดสอบการยอมรับ
TKK

32

ใช่มันเป็นการปฏิบัติที่ไม่ดี

โดยทั่วไปการทดสอบหน่วยมีวัตถุประสงค์เพื่อทดสอบหน่วยของรหัสเดียว (เช่นฟังก์ชั่นเดียวตามสถานะที่รู้จัก)

เมื่อคุณต้องการทดสอบเหตุการณ์ที่อาจเกิดขึ้นในเครือคุณต้องการรูปแบบการทดสอบที่แตกต่างกันเช่นการทดสอบการรวม สิ่งนี้จะเป็นจริงยิ่งขึ้นหากคุณขึ้นอยู่กับบริการของบุคคลที่สาม

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


8
ตกลง ฉันคิดว่าความสับสนนี้เกิดขึ้นจากความจริงที่ว่าหลาย ๆ คนมีความคิดว่าการทดสอบการรวมเข้าด้วยกันต้องเป็นแบบ end-to-end และใช้ "การทดสอบหน่วย" เพื่ออ้างถึงการทดสอบใด ๆ ที่ทดสอบเพียงชั้นเดียว
autophage

8
@ autoophage: เห็นด้วยกับสิ่งนี้อย่างแน่นอน ในความเป็นจริงฉันเห็นด้วยกับมันมากจนฉันพบว่าตัวเองตกหลุมพรางอยู่เป็นประจำแม้จะยอมรับว่ามันเป็นกับดัก 😂
Lightness Races ใน Orbit

16

คำสั่งบังคับใช้ที่คุณเสนอนั้นสมเหตุสมผลถ้าคุณยกเลิกการทดสอบการทำงานหลังจากความล้มเหลวครั้งแรก

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

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

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


7

กลิ่นที่คุณอ้างถึงคือการประยุกต์ใช้ข้อ จำกัด และกฎที่ไม่ถูกต้องในการทดสอบของคุณ

การทดสอบหน่วยมักสับสนกับ "การทดสอบอัตโนมัติ" หรือ "การทดสอบอัตโนมัติโดยโปรแกรมเมอร์"

การทดสอบหน่วยต้องมีขนาดเล็กเป็นอิสระและรวดเร็ว

บางคนไม่ถูกต้องอ่านหนังสือเล่มนี้เป็น"การทดสอบแบบอัตโนมัติเขียนโดยโปรแกรมเมอร์ต้องมีขนาดเล็กเป็นอิสระและรวดเร็ว" แต่มันก็หมายความว่าถ้าการทดสอบของคุณไม่เล็กอิสระและรวดเร็วไม่ใช่การทดสอบหน่วยดังนั้นกฎบางอย่างสำหรับการทดสอบหน่วยไม่ควรไม่สามารถหรือไม่ต้องใช้สำหรับการทดสอบของคุณ ตัวอย่างเล็ก ๆ น้อย ๆ : คุณควรรันการทดสอบหน่วยหลังจากทุกบิลด์ซึ่งคุณต้องไม่ทำการทดสอบอัตโนมัติที่ไม่เร็ว

ในขณะที่การทดสอบที่ไม่ใช่การทดสอบหน่วยหมายความว่าคุณสามารถข้ามกฎหนึ่งและได้รับอนุญาตให้มีการพึ่งพาซึ่งกันและกันระหว่างการทดสอบคุณยังพบว่ามีกฎอื่น ๆ ที่คุณอาจพลาดและจะต้องรื้อฟื้น - บางสิ่งสำหรับขอบเขตของคำถามอื่น .


6

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

ตัวอย่างเช่น submodule กำลังสร้างข้อมูลและอีกอันหนึ่งกำลังเรียกใช้แบบสอบถามบนข้อมูล หาก submodule ที่สร้างข้อมูลมีข้อผิดพลาดการทดสอบสำหรับ submodule แบบสอบถามจะล้มเหลวเช่นกันแม้ว่า submodule นั้นจะทำงานได้ดี

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

เช่น

ถ้าคุณมี:

class Queries {

    int GetTheNumber() {
        var dataModule = new Submodule1();
        var data = dataModule.GetData();
        return ... run some query on data
    }
}

แทนที่จะชอบ:

interface DataModule {
    Data GetData();
}


class Queries {

    IDataModule _dataModule;

    ctor(IDataModule dataModule) {
       _dataModule = dataModule;
    }

    int GetTheNumber() {
        var data = _dataModule.GetData();
        return ... run some query on data
    }
}

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


6

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


2
ฉันมีแนวโน้มมากกว่าที่จะตรวจสอบสาเหตุที่การทดสอบหน่วยหนึ่งทำงานช้ากว่าการบังคับใช้คำสั่งซื้อ การทดสอบหน่วยจะต้องรวดเร็ว
Robbie Dee

OP บอกว่าเขาไม่สามารถทำงานกับข้อมูลจำลองสำหรับการทดสอบเหล่านี้บางส่วนได้ นั่นหมายถึงฐานข้อมูลได้รับผลกระทบบางประเภททำให้การทดสอบทั้งหมดช้าลง (แม้แต่การทดสอบจริงบางหน่วยที่ควรรันได้อย่างรวดเร็วตามธรรมชาติ) หากเขามีการทดสอบอื่น ๆ ที่ไม่ต้องการฐานข้อมูลฮิตพวกเขาจะเรียกใช้ลำดับความสำคัญเร็วกว่าสิ่งใด ๆ ที่ต้องใช้ดิสก์หรือเครือข่าย
Mike Holler

2
คุณคิดถูกแล้วฉันคิดว่า; Robbie ถูกต้องที่การทดสอบหน่วยควรมีขนาดเล็กและรวดเร็วและแยกได้จากการอ้างอิงดังนั้นคำสั่งไม่ควรสำคัญและการเรียงลำดับแบบสุ่มมักส่งเสริมการออกแบบที่ดีขึ้นโดยการบังคับใช้ความเป็นอิสระนั้น และไมค์เป็นสิทธิที่การทดสอบการทำงานได้เร็วขึ้นเป็นครั้งแรกเป็นอย่างมากที่ดีมากสำหรับการทดสอบการรวม ดังคำตอบข้างต้นปัญหาส่วนหนึ่งคือคำศัพท์ของการทดสอบหน่วยกับการรวมเข้าด้วยกัน
WillC

@MikeHoller จากนั้นพวกเขาไม่ได้ทดสอบหน่วย ไม่ควรมีความสับสนว่าหน่วยทดสอบคืออะไร
Robbie Dee

@ RobbieDee ฉันแค่ใช้ศัพท์ที่ OP ใช้อยู่ ฉันเข้าใจว่านี่ไม่ใช่การทดสอบหน่วยที่แท้จริง หากคุณต้องการต่อสู้เกี่ยวกับคำศัพท์ให้นำมันขึ้นมาด้วย OP (ดังนั้นทำไมฉันชี้แจงกับ "การทดสอบหน่วยที่แท้จริง" ในความคิดเห็นก่อนหน้าของฉัน ")
Mike Holler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.