ควรเขียนการทดสอบหน่วยสำหรับผู้ทะเยอทะยานและผู้ตั้งค่า?


141

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


ฉันไม่คิดอย่างนั้น คุณไม่ควรเขียนกรณีทดสอบสำหรับ getter / setter
Harry Joy

1
ฉันคิดว่าคุณหมายถึง Java? นี่เป็นคำถามที่ฉับพลันเป็นพิเศษสำหรับ Java ซึ่งน้อยกว่ามากสำหรับภาษาที่ทันสมัยกว่านี้
skaffman

@skaffman ภาษาสมัยใหม่อะไรไม่มีคุณสมบัติ? แน่นอนว่าภาษาอย่าง Java ต้องการให้มันเป็นส่วนของเมธอดเต็ม แต่นั่นก็ไม่ได้ทำให้มันแตกต่างจากการพูดแบบ C #
ซานตาคลอสJørgensen

2
@Claus: เขาไม่ได้พูดคุณสมบัติเขาพูด getters และ setters ในจาวาคุณเขียนด้วยตนเองในภาษาอื่นคุณจะได้รับการสนับสนุนที่ดีขึ้น
skaffman

2
หนึ่งอาจถามว่าทำไมมี getters และ settersเลย
Raedwald

คำตอบ:


180

ฉันจะบอกว่าไม่มี

@ Will บอกว่าคุณควรตั้งเป้าให้ครอบคลุมรหัส 100% แต่ในความคิดของฉันมันเป็นสิ่งที่ทำให้ไขว้เขวอันตราย คุณสามารถเขียนการทดสอบหน่วยที่มีความครอบคลุม 100% และยังไม่ได้ทดสอบอะไรเลย

การทดสอบหน่วยมีไว้เพื่อทดสอบพฤติกรรมของรหัสของคุณในลักษณะที่แสดงออกและมีความหมายและ getters / setters เป็นวิธีการสิ้นสุดเท่านั้น หากการทดสอบของคุณใช้ getters / setters เพื่อให้บรรลุเป้าหมายในการทดสอบฟังก์ชัน "ของจริง" นั่นก็ถือว่าดีพอ

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


7
การตั้งเป้าหมายให้ครอบคลุมรหัส 100% นั้นโง่มาก คุณจะต้องใช้ความครอบคลุมของรหัสที่ไม่เปิดเผยต่อสาธารณะและ / หรือรหัสโดยไม่มีความซับซ้อน สิ่งต่าง ๆ เหล่านี้ดีที่สุดสำหรับการสร้างระบบอัตโนมัติ แต่แม้กระทั่งการทดสอบที่สร้างอัตโนมัติก็ไม่มีจุดหมาย เป็นการดีกว่าที่จะเปลี่ยนการโฟกัสเป็นการทดสอบที่สำคัญเช่นการทดสอบการรวม
ซานตาคลอสJørgensen

7
@Claus: ฉันเห็นด้วยยกเว้นเพียงเล็กน้อยเกี่ยวกับการเพ่งความสนใจไปที่การทดสอบการรวมระบบ การทดสอบหน่วยมีความสำคัญต่อการออกแบบที่ดีและการทดสอบการรวมเข้าด้วยกัน
skaffman

5
ฉันคิดว่ารหัสครอบคลุม 100% เมื่อเรียกใช้ชุดทดสอบทั้งหมดเป็นเป้าหมายที่ดี setters คุณสมบัติและรหัสอื่น ๆ จะถูกเรียกใช้เป็นส่วนหนึ่งของการทดสอบขนาดใหญ่ ชิ้นส่วนสุดท้ายที่จะครอบคลุมอาจเป็นข้อผิดพลาดในการจัดการ และหากการจัดการข้อผิดพลาดไม่ครอบคลุมโดยการทดสอบหน่วยมันจะไม่ถูกครอบคลุม คุณต้องการจัดส่งผลิตภัณฑ์ที่มีรหัสที่ไม่เคยเรียกใช้หรือไม่?
Anders Abel

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

คุณอาจกำลังทดสอบเครื่องมือติดตั้งที่ไม่จำเป็นซึ่งคุณ (หรือเครื่องมือ) สร้างขึ้นเพื่อให้มี POJO 'แบบกลม' คุณอาจใช้อินสแตนซ์โดยใช้ Gson.fromJson เพื่อ "ขยาย" POJOS (ไม่จำเป็นต้องตั้งค่า) ในกรณีนี้ตัวเลือกของฉันคือการลบ setters ที่ไม่ได้ใช้
Alberto Gaona

36

Roy Osherove ในหนังสือชื่อ 'The Art Of Unit Testing' กล่าวว่า:

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


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

1
หนังสือเล่มแรกที่สำคัญมักมีคำแนะนำที่ไม่ดี ฉันเคยเห็นหลาย ๆ กรณีที่ผู้คนขว้างเข้าไปในผู้ได้รับและผู้ตั้งอย่างรวดเร็วและทำผิดพลาดเพราะพวกเขากำลังตัดและวางหรือลืมสิ่งนี้ หรือนี่ -> หรืออะไรทำนองนั้น ง่ายต่อการทดสอบและควรทดสอบอย่างแน่นอน
ชาร์ลส์

35

YES ที่ดังก้องด้วย TDD


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


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

สำหรับฉันคำตอบคือดังก้องใช่ถ้าคุณทำตาม TDD หากคุณไม่ได้ไม่ใช่คำตอบที่เป็นไปได้

DDD ใน TDD

TDD มักอ้างว่าให้ประโยชน์หลักแก่เจ้า

  • ป้องกัน
    • มั่นใจได้ว่ารหัสอาจมีการเปลี่ยนแปลงแต่ไม่ได้พฤติกรรมของมัน
    • สิ่งนี้ช่วยให้มีการปฏิบัติที่สำคัญอย่างยิ่งต่อการปรับโครงสร้างใหม่
    • คุณได้รับ TDD นี้หรือไม่
  • ออกแบบ
    • คุณระบุสิ่งที่สิ่งที่ควรจะทำอย่างไร, วิธีการที่ควรจะทำงานก่อนที่จะใช้มัน
    • สิ่งนี้มักจะหมายถึงการตัดสินใจดำเนินการอย่างมีข้อมูลมากขึ้น
  • เอกสาร
    • ชุดทดสอบควรทำหน้าที่เป็นเอกสารข้อกำหนด (ข้อกำหนด)
    • การใช้การทดสอบเพื่อวัตถุประสงค์ดังกล่าวหมายความว่าเอกสารและการนำไปใช้งานอยู่ในสภาพที่สอดคล้องกันเสมอ - การเปลี่ยนแปลงหนึ่งหมายถึงการเปลี่ยนแปลงอื่น ๆ เปรียบเทียบกับข้อกำหนดการออกแบบและการเก็บรักษาในเอกสารคำแยกต่างหาก

แยกความรับผิดชอบออกจากการปฏิบัติ

ในฐานะโปรแกรมเมอร์มันเป็นเรื่องน่าดึงดูดอย่างมากที่คิดว่าคุณลักษณะเป็นสิ่งที่มีความสำคัญและเป็นผู้ได้รับและผู้ตั้งตัวเป็นค่าใช้จ่าย

แต่คุณลักษณะเป็นรายละเอียดการใช้งานในขณะที่ setters และ getters เป็นส่วนต่อประสานสัญญาที่ทำให้โปรแกรมใช้งานได้จริง

มันสำคัญกว่าการสะกดว่าวัตถุควร:

อนุญาตให้ลูกค้าเปลี่ยนสถานะ

และ

อนุญาตให้ไคลเอนต์เพื่อสอบถามสถานะ

ดังนั้นวิธีการจัดเก็บสถานะนี้จริง ๆ (ซึ่งเป็นแอตทริบิวต์ที่พบมากที่สุด แต่ไม่ใช่วิธีเดียว)

การทดสอบเช่น

(The Painter class) should store the provided colour

เป็นสิ่งสำคัญสำหรับส่วนเอกสารของ TDD

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

ขาดวิศวกรรมไปกลับ ...

หนึ่งในปัญหาสำคัญในโลกของการพัฒนาระบบคือการขาด วิศวกรรมไปกลับ1 - กระบวนการพัฒนาของระบบถูกแยกส่วนเป็นกระบวนการย่อยที่แยกจากกันซึ่งเป็นสิ่งประดิษฐ์ที่ (เอกสาร, รหัส) มักไม่สอดคล้องกัน

1 Brodie, Michael L. "John Mylopoulos: การเย็บเมล็ดแห่งการสร้างแบบจำลองแนวคิด" การสร้างแบบจำลองแนวคิด: รากฐานและการประยุกต์ Springer Berlin Heidelberg, 2009. 1-9.

... และ TDD แก้ปัญหาอย่างไร

เป็นส่วนเอกสารของ TDD ที่ทำให้มั่นใจได้ว่าข้อกำหนดของระบบและรหัสของมันสอดคล้องกันเสมอ

ออกแบบก่อนใช้ในภายหลัง

ภายใน TDD เราเขียนการทดสอบการยอมรับที่ล้มเหลวก่อนจากนั้นเขียนโค้ดที่ให้พวกเขาผ่าน

ภายใน BDD ระดับสูงกว่าเราจะเขียนสถานการณ์ก่อนจากนั้นให้ผ่าน

เหตุใดคุณจึงควรยกเว้นผู้ตั้งค่าและผู้ทะเยอทะยาน?

ในทางทฤษฎีมันเป็นไปได้อย่างสมบูรณ์แบบใน TDD สำหรับคนคนหนึ่งที่จะเขียนการทดสอบและอีกคนหนึ่งที่จะใช้รหัสที่ทำให้มันผ่าน

ดังนั้นถามตัวเอง:

บุคคลที่เขียนแบบทดสอบสำหรับชั้นเรียนควรพูดถึงผู้ได้รับและผู้ตั้งตัว

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

เห็นได้ชัดว่าถ้าคุณเขียนรหัสก่อนคำตอบอาจไม่ชัดเจน


2
นั่นเป็นเพียงด้านหนึ่งของเหรียญ ลองคิดถึงสิ่งที่คุณทำได้แทนที่จะทดสอบเพื่อประโยชน์ในการทดสอบ อย่างที่ Beck Beck กล่าวคุณจะได้รับเงินสำหรับรหัสการทำงานไม่ใช่เพื่อการทดสอบการทำงาน
Georgii Oleinikov

@GeorgiiOleinikov คุณได้อ่านคำตอบอื่น ๆ ของฉันด้านล่าง? มันค่อนข้างสอดคล้องกับมุมมองของคุณ
Izhaki

21

tl; dr: ใช่คุณควรและด้วยOpenPojoมันเป็นเรื่องเล็กน้อย

  1. คุณควรตรวจสอบความถูกต้องบางอย่างในตัวรับและตัวตั้งค่าของคุณดังนั้นคุณควรทำการทดสอบ ตัวอย่างเช่นsetMom(Person p)ไม่อนุญาตให้ตั้งค่าให้ทุกคนที่อายุน้อยกว่าตัวเองเป็นแม่ของพวกเขา

  2. แม้ว่าคุณจะไม่ได้ทำอะไรตอนนี้โอกาสที่คุณจะได้ในอนาคตก็จะเป็นผลดีต่อการวิเคราะห์การถดถอย หากคุณต้องการอนุญาตให้คุณแม่ตั้งค่าให้nullคุณควรมีการทดสอบว่าควรมีคนเปลี่ยนแปลงสิ่งใดในภายหลังสิ่งนี้จะเป็นการเสริมสมมติฐานของคุณ

  3. ข้อผิดพลาดที่พบบ่อยคือที่มันควรจะเป็นvoid setFoo( Object foo ){ foo = foo; } void setFoo( Object foo ){ this.foo = foo; }(ในกรณีแรกfooที่จะถูกเขียนขึ้นเพื่อเป็นพารามิเตอร์ ไม่fooข้อมูลเกี่ยวกับวัตถุ )

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

  5. มิฉะนั้นถ้าคุณมี setters / getters พื้นฐานที่สุดแล้วการทดสอบหน่วยพวกเขาจะเพิ่มประมาณ 10 นาทีต่อวัตถุมากที่สุดดังนั้นการสูญเสียคืออะไร หากคุณเพิ่มพฤติกรรมคุณมีการทดสอบโครงกระดูกอยู่แล้วและคุณจะได้รับการทดสอบการถดถอยนี้ฟรี หากคุณกำลังใช้ Java คุณมีข้อแก้ตัวไม่ได้เนื่องจากมีOpenPojo มีชุดของกฎที่มีอยู่ที่คุณสามารถเปิดใช้งานแล้วสแกนโครงการทั้งหมดของคุณกับพวกเขาเพื่อให้แน่ใจว่าพวกเขาจะใช้อย่างสม่ำเสมอภายในรหัสของคุณ

จากตัวอย่างของพวกเขา:

final PojoValidator pojoValidator = new PojoValidator();

//create rules
pojoValidator.addRule( new NoPublicFieldsRule  () );
pojoValidator.addRule( new NoPrimitivesRule    () );
pojoValidator.addRule( new GetterMustExistRule () );
pojoValidator.addRule( new SetterMustExistRule () );

//create testers
pojoValidator.addTester( new DefaultValuesNullTester () );
pojoValidator.addTester( new SetterTester            () );
pojoValidator.addTester( new GetterTester            () );

//test all the classes
for(  PojoClass  pojoClass :  PojoClassFactory.getPojoClasses( "net.initech.app", new FilterPackageInfo() )  )
    pojoValidator.runValidation( pojoClass );

11
ฉันรู้ว่านี่คือรุ่นเก่าตอนนี้ แต่: คุณควรจะตรวจสอบใน getters และ setters ของคุณหรือไม่ ฉันรู้สึกว่า setMom ควรทำในสิ่งที่พูด ถ้ามันตรวจสอบแล้วมันไม่ควรจะตรวจสอบและ EndSetMom? หรือดีกว่ารหัสยืนยันไม่ควรมี ELSEWHERE ไม่ใช่วัตถุธรรมดาใช่หรือไม่ ฉันหายไปนี่อะไร
ndtreviv

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

1
นั่นอาจเป็นไฮไลต์ประจำสัปดาห์ของฉัน ขอบคุณ.
เลื่อน

19

ใช่ แต่ไม่เสมอไป

ให้ฉันทำอย่างละเอียด:

การทดสอบหน่วยคืออะไร?

จากการทำงานอย่างมีประสิทธิภาพด้วยรหัสดั้งเดิม1 :

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

โปรดทราบว่าด้วย OOP ที่คุณพบว่า getters และ setters หน่วยเป็นคลาสไม่ใช่วิธีการที่แยกกัน

การทดสอบที่ดีคืออะไร?

ข้อกำหนดและการทดสอบทั้งหมดเป็นไปตามรูปแบบของตรรกะ Hoare :

{P} C {Q}

ที่ไหน:

  • {P}คือเงื่อนไข (ที่กำหนด )
  • Cเป็นเงื่อนไขทริกเกอร์ ( เมื่อ )
  • {Q}คือ postcondition ( จากนั้น )

แล้วคติพจน์:

ทดสอบพฤติกรรมไม่ใช่การนำไปใช้

ซึ่งหมายความว่าคุณไม่ควรทดสอบว่าCประสบความสำเร็จในการโพสต์สภาพคุณควรตรวจสอบว่าเป็นผลมาจาก{Q}C

เมื่อพูดถึง OOP Cเป็นคลาส ดังนั้นคุณไม่ควรทดสอบผลกระทบภายในเพียงผลภายนอกเท่านั้น

ทำไมไม่ทดสอบ bean getters และ setters แยกกัน

ตัวรับและเซ็ตเตอร์อาจเกี่ยวข้องกับตรรกะบางอย่าง แต่ตราบใดที่ตรรกะนี้ไม่มีผลกระทบภายนอก - ทำให้พวกเขาเป็นถั่ว accessors 2 ) การทดสอบจะต้องดูภายในวัตถุและไม่เพียง แต่เป็นการละเมิด encapsulation แต่ยังทดสอบการใช้งาน

ดังนั้นคุณไม่ควรทดสอบตัวรับถั่วและตัวแยก นี้ไม่ดี:

Describe 'LineItem class'

    Describe 'setVAT()'

        it 'should store the VAT rate'

            lineItem = new LineItem()
            lineItem.setVAT( 0.5 )
            expect( lineItem.vat ).toBe( 0.5 )

แม้ว่าถ้าsetVATจะมีข้อยกเว้นการทดสอบที่เกี่ยวข้องจะมีความเหมาะสมตั้งแต่ตอนนี้มีผลกระทบภายนอก

คุณควรทดสอบตัวตั้งและตัวตั้งอย่างไร

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

ดังนั้นการทดสอบ setters และ getters ควรเกี่ยวข้องกับผลกระทบภายนอกของวิธีการเหล่านี้ไม่ใช่ตัวทดสอบภายใน

ตัวอย่างเช่น:

Describe 'LineItem class'

    Describe 'getGross()'

        it 'should return the net time the VAT'

            lineItem = new LineItem()
            lineItem.setNet( 100 )
            lineItem.setVAT( 0.5 )
            expect( lineItem.getGross() ).toBe( 150 )

คุณอาจคิดกับตัวเอง:

โปรดรอสักครู่เรากำลังทดสอบgetGross()ที่นี่ไม่ได้ setVAT()

แต่ถ้าsetVAT()การทดสอบที่ผิดปกตินั้นน่าจะล้มเหลวเหมือนกันหมด

1 Feathers, M. , 2004 ทำงานอย่างมีประสิทธิภาพด้วยรหัสดั้งเดิม Prentice Hall Professional

2 Martin, RC, 2009. รหัสสะอาด: คู่มือของงานฝีมือซอฟต์แวร์เปรียว การศึกษาของเพียร์สัน


13

ในขณะที่มีเหตุผลที่สมเหตุสมผลสำหรับคุณสมบัติมีความเชื่อการออกแบบเชิงวัตถุทั่วไปว่าการเปิดเผยสถานะของสมาชิกผ่านคุณสมบัติคือการออกแบบที่ไม่ดี บทความของ Robert Martin ใน Open Open Principle นั้นขยายออกโดยระบุว่าคุณสมบัติส่งเสริมการมีเพศสัมพันธ์และจำกัดความสามารถในการปิดชั้นเรียนจากการดัดแปลง - หากคุณแก้ไขคุณสมบัติผู้บริโภคในชั้นเรียนทุกคนจะต้องเปลี่ยนเช่นกัน เขามีคุณสมบัติที่การเปิดเผยตัวแปรสมาชิกไม่จำเป็นต้องเป็นการออกแบบที่ไม่ดี แต่อาจมีสไตล์ที่ไม่ดี อย่างไรก็ตามหากคุณสมบัติเป็นแบบอ่านอย่างเดียวมีโอกาสน้อยที่การละเมิดและผลข้างเคียง

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

มีเหตุผลที่ชัดเจนว่าควรใช้คุณสมบัติการอ่าน / เขียนเช่นคุณสมบัติ ViewModel ที่เชื่อมโยงกับฟิลด์อินพุตเป็นต้น

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

  1. คุณกำลังขาดการทดสอบที่ใช้คุณสมบัติทางอ้อม
  2. คุณสมบัติไม่ได้ใช้

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


12

หากความสลับซับซ้อนของผู้ทะเยอทะยานและ / หรือผู้ตั้งค่าเป็น 1 (ซึ่งโดยปกติแล้ว) คำตอบคือไม่คุณไม่ควรทำ

ดังนั้นหากคุณมี SLA ที่ต้องการการครอบคลุมโค้ด 100% อย่ากังวลและให้ความสำคัญกับการทดสอบในส่วนที่สำคัญของซอฟต์แวร์ของคุณ

ป.ล. อย่าลืมสร้างความแตกต่างให้กับผู้ที่ได้รับและผู้เซทเทอร์แม้กระทั่งในภาษาอย่าง C # ซึ่งคุณสมบัติอาจมีลักษณะเหมือนกัน ความซับซ้อนของตัวตั้งค่าอาจสูงกว่าทะลุดังนั้นจึงตรวจสอบการทดสอบหน่วย


4
แม้ว่าหนึ่งควรทดสอบเพื่อป้องกันการคัดลอกบน getters
เลื่อน

8

อารมณ์ขัน, Take ยังฉลาด: วิถีแห่ง Testivus

"เขียนการทดสอบที่คุณทำได้วันนี้"

การทดสอบ getters / setters อาจ overkill ถ้าคุณเป็นผู้ทดสอบที่มีประสบการณ์และนี่เป็นโครงการขนาดเล็ก อย่างไรก็ตามหากคุณเพิ่งเริ่มเรียนรู้วิธีการทดสอบหน่วยหรือผู้ได้รับ / setters เหล่านี้อาจมีตรรกะ (เช่นsetMom()ตัวอย่างของ @ ArtB ) ดังนั้นคุณควรเขียนแบบทดสอบ


1
ลิงก์ของคุณควรชี้ไปที่: The Way of Testivus
JJS

2

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

นอกจากนี้หากคุณกำลังใช้รายงานการครอบคลุมรหัสเช่นเราสิ่งหนึ่งที่คุณสามารถทำได้คือเพิ่มแอตทริบิวต์ [ExcludeFromCodeCoverage] วิธีการแก้ปัญหาของเราคือการใช้สิ่งนี้กับรุ่นที่มีคุณสมบัติโดยใช้ getters และ setters หรือบนคุณสมบัติ ด้วยวิธีนี้มันจะไม่ส่งผลกระทบต่อ% การครอบคลุมโค้ดทั้งหมดเมื่อรันรายงานการครอบคลุมโค้ดโดยสมมติว่าเป็นสิ่งที่คุณใช้ในการคำนวณเปอร์เซ็นต์การครอบคลุมโค้ดของคุณ การทดสอบมีความสุข!


2

ในความคิดเห็นของฉันครอบคลุมรหัสเป็นวิธีที่ดีเพื่อดูว่าคุณพลาดฟังก์ชั่นใด ๆ ที่คุณควรจะครอบคลุม

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

เมื่อคุณตรวจสอบเปอร์เซ็นต์ความครอบคลุมโค้ดในโครงการของคุณเท่านั้นเปอร์เซ็นต์การครอบคลุมการทดสอบเช่น 80% นั้นไม่มีความหมาย คุณสามารถทดสอบส่วนที่ไม่มีตรรกะทั้งหมดและลืมบางส่วนที่สำคัญ ในกรณีนี้มีเพียง 100% เท่านั้นที่หมายความว่าคุณได้ทดสอบรหัสที่สำคัญทั้งหมด (และรหัสที่ไม่ใช่แบบลอจิคัลทั้งหมดด้วย) ทันทีที่ 99.9% คุณรู้ว่าได้ลืมบางสิ่งบางอย่าง

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

อีกอย่างหนึ่ง: ขณะที่ทำงานกับธนาคารขนาดใหญ่ในเนเธอร์แลนด์ฉันสังเกตเห็นว่า Sonar ระบุรหัสครอบคลุม 100% อย่างไรก็ตามฉันรู้ว่ามีบางอย่างขาดหายไป การตรวจสอบเปอร์เซ็นต์ความครอบคลุมโค้ดต่อไฟล์จะระบุไฟล์ที่เปอร์เซ็นต์ต่ำกว่า เปอร์เซ็นต์ฐานรหัสทั้งหมดมีขนาดใหญ่ที่ไฟล์เดียวไม่ได้ทำให้เปอร์เซ็นต์นั้นแสดงเป็น 99.9% ดังนั้นคุณอาจต้องระวังสิ่งนี้ ...


1

ฉันไม่ได้เล็ก ๆ น้อย ๆการวิเคราะห์ของความคุ้มครองที่ประสบความสำเร็จในรหัส JUnit ตัวเอง

หมวดหนึ่งรหัสเปิดคือ"ง่ายเกินไปที่จะทดสอบ" ซึ่งรวมถึง getters และ setters อย่างง่ายซึ่งผู้พัฒนา JUnit ไม่ได้ทดสอบ

ในทางกลับกัน JUnit ไม่มีวิธีใด ๆ (ไม่เลิกใช้) นานกว่า 3 บรรทัดที่ไม่ครอบคลุมโดยการทดสอบใด ๆ


1

ฉันจะบอกว่า: ใช่ข้อผิดพลาดในวิธีการทะเยอทะยาน / setter สามารถแอบเงียบและก่อให้เกิดข้อบกพร่องที่น่าเกลียดบางอย่าง

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

        assertTrue(executor.execute(Example.class, Arrays.asList( new DefensiveCopyingCheck(),
            new EmptyCollectionCheck(), new GetterIsSetterCheck(),
            new HashcodeAndEqualsCheck(), new PublicVariableCheck())));

-> https://github.com/Mixermachine/base-test


0

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

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

แม้ว่ามันจะยังคงไม่เลวร้ายเท่าการค้นพบปัญหาในการผลิต

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

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.