รหัสทดสอบคัดลอกและวาง: วิธีนี้แย่แค่ไหน?


12

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

แต่ฉันมักจะคัดลอกโค้ดทดสอบขนาดใหญ่จำนวนหนึ่งจากส่วนหนึ่งแล้ววางลงในอีกส่วนหนึ่งและทำการเปลี่ยนแปลงเล็กน้อยตามที่ฉันต้องการ ฉันไม่ได้ใช้วิธีการเข้ารหัสที่มีโครงสร้างมากขึ้นเช่นการใช้หลักการหรือฟังก์ชั่น OO มากขึ้น

ผู้เขียนโค้ดคนอื่นรู้สึกเช่นนี้เมื่อเขียนรหัสทดสอบหรือไม่? เห็นได้ชัดว่าฉันต้องการที่จะปฏิบัติตามหลักการ DRY และ YAGNI แต่ฉันพบว่ารหัสทดสอบ (รหัสทดสอบอัตโนมัติสำหรับการทดสอบ GUI ต่อไป) สามารถทำให้หลักการเหล่านี้ยากที่จะปฏิบัติตาม หรือฉันต้องการเพียงแค่ฝึกฝนการเข้ารหัสและระบบโดยรวมที่ดีขึ้นในการทำสิ่งต่าง ๆ ?

แก้ไข: เครื่องมือที่ฉันใช้คือ SilkTest ซึ่งเป็นภาษาที่เป็นกรรมสิทธิ์ที่ชื่อว่า 4Test เช่นกันการทดสอบเหล่านี้ส่วนใหญ่ใช้สำหรับเดสก์ท็อปของ Windows แต่ฉันได้ทำการทดสอบเว็บแอปโดยใช้การตั้งค่านี้เช่นกัน


คุณใช้เครื่องมือทดสอบอะไร อาจเป็นได้ว่ากรอบการทดสอบของคุณไม่สนับสนุนประเภทการทดสอบที่คุณเขียน Cut-n-paste มากกว่า 3 บรรทัดโดยทั่วไปนั้นแย่มาก แต่ถ้าคุณสามารถเพิ่มมูลค่าระยะยาวได้อย่างชัดเจนมากขึ้นโดยการทดสอบ GUI โดยอัตโนมัติมากกว่าการดำเนินการด้วยตนเองทุกครั้ง ดี.
GlenPeterson

นอกจากนี้ภาษานี้คืออะไร? คุณอาจมีบางสิ่งบางอย่างที่ไม่ได้นึกขึ้นมาได้ซึ่งจะอนุญาตให้ใช้ซ้ำได้ (เช่นฟังก์ชั่นชั้นหนึ่ง) ในทางตรงกันข้ามกรณีทดสอบจะควรจะถูกเก็บไว้ที่เรียบง่ายที่จะให้มันมีโอกาสน้อยที่พวกเขามีข้อบกพร่องของตัวเอง ...
Izkata

3
ในสิ่งที่ฉันได้เขียนโค้ดการทดสอบไม่ได้ถูกแยกออกจากการรีแฟคเตอร์ ..
Simon Whitehead

คำตอบ:


23

คัดลอกวางแล้วกรณีทดสอบที่แก้ไขแล้วมักจะใช้ได้

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

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


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

12

การทำซ้ำเป็นรากของความชั่วร้ายทั้งหมด

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

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

ทุกครั้งที่ฉันแนะนำการทำซ้ำบางประเภทและต้องแก้ไขข้อบกพร่องในนั้นฉันลืมที่จะแก้ไขแบบจำลอง ... (Donald Knuth) ดังนั้นเมื่อใดก็ตามที่มีการซ้ำซ้อนเพียงแค่เอามันออกมาให้ดีที่สุดเท่าที่จะทำได้อย่าแฮ็ค !

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

นี่คือการอ่านที่ดีจากสยองขวัญรหัสที่เป็นแรงบันดาลใจฉัน - ข้อเสนอเจียมเนื้อเจียมตัวสำหรับคัดลอกและวางโรงเรียนรหัสซ้ำ


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

ใช่ฉันเอาสถานีจาก Knuth :)
Yusubov

9
คุณพูดซ้ำตัวเอง: คุณพูดซ้ำ ๆ โดยพูดว่า "การทำซ้ำเป็นรากเหง้าของความชั่วทั้งหมด" ในชื่อเรื่องและประโยคอินโทรของคุณ
Thomas Eding

Yeap ฉันไม่ว่าเจตนาที่จะเน้นความสำคัญและคุณจะยินดีที่จะแก้ไข thats ส่วนหนึ่ง :)
Yusubov

1
โทมัสเอดิงคุณพูดซ้ำตัวเองเช่นกัน คุณพูดซ้ำตัวเองเช่นกัน =)
marktani

7

มันยังค่อนข้างแย่ที่จะตัดและวาง มีปัญหาเล็กน้อย

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

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

มันอาจทำให้การทดสอบอ่านได้น้อยลง บล็อกขนาดใหญ่ของรหัสที่คัดลอกอาจอ่านได้ยากกว่าวิธีการเรียกใช้ตัวช่วยซึ่งมีชื่อที่สื่อความหมาย

ทุกสิ่งที่ฉันระบุไว้เป็นสิ่งที่อาจเป็นปัญหา หากคุณพบว่าไม่มีของพวกเขาจริงมีปัญหาแล้วแน่นอนก็ปรับ


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

4

ฉันเคยเห็นด้วยกับคุณ แต่เมื่อเวลาผ่านไปฉันพบว่าการเปลี่ยนแปลงทุกอย่างที่ฉันทำ (โดยเฉพาะการเปลี่ยนแปลง DI ในการทดสอบหน่วย) จำเป็นต้องใช้การทดสอบจำนวนมากในการเปลี่ยนแปลงและยุ่งยาก ตอนนี้ฉันสมัครเข้าเรียนที่โรงเรียน DRY แม้ว่าจะเขียนข้อสอบ

สำหรับการทดสอบ GUI คุณอาจต้องการดูรูปแบบ PageObjectเพื่อลดรหัสซ้ำ


2

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

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


+1 สำหรับObject Mother patternรหัสการเริ่มต้นทั่วไป
k3b

2

ผู้คนควรพยายาม จำกัด การทำซ้ำเมื่อทำได้ - ใช่ แต่ผลตอบแทนขึ้นอยู่กับสถานการณ์ สิ่งนี้สามารถย้อนกลับไปยังการอภิปราย 'แนวทางปฏิบัติที่ดีที่สุด' แต่คำถามคือสิ่งที่ดีที่สุดสำหรับคุณในสถานการณ์นี้ มีข้อยกเว้นสำหรับทุกกฎ

สองสามสิ่งที่ฉันจะถามคือ 1) มีโอกาสมากน้อยแค่ไหนที่ฟังก์ชันนี้ที่ทดสอบใน UAT จะมีการเปลี่ยนแปลง หากไม่น่าจะเปลี่ยนแปลงได้มีโอกาสน้อยที่คุณจะต้องอัปเดตชุดรหัสแต่ละชุด 2) หากมีการเปลี่ยนแปลงใน UAT มันจะส่งผลกระทบต่อแต่ละชุดของรหัสที่คัดลอกหรืออาจส่งผลกระทบเพียงหนึ่งหรือสองชุด? หากอาจแยกได้และต้องการการเปลี่ยนแปลงเพียงชุดเดียวอาจช่วยให้แยกสิ่งต่าง ๆ ได้ 3) วิธีการเริ่มต้นจะซับซ้อนเพียงใดหากคุณลองใช้และจัดการกับสถานการณ์ทั้งหมดหรือไม่ คุณกำลังเพิ่มจำนวนซ้อนกันถ้า / else / loops หรือไม่? หากคุณเริ่มต้นทำกิ่งทั้งหมดคุณอาจจบลงด้วยรหัสที่ยากต่อการเข้าใจ มันจะง่ายกว่าที่จะทำให้การปรับปรุงในแต่ละข้อความที่คัดลอกกว่ามันจะต้องกลับไปที่ตรรกะกิ่งทั้งหมด?

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


0

หนึ่งขั้นตอนใหญ่

One thought: ดูเหมือนว่าคุณกำลังพยายามหลีกเลี่ยงรหัส cut-n-paste โดยทำวิธีดังนี้:

testScreen(title, fieldList, linkList, param1, param2, param3,...) {
    test that the layout at the top of the screen is correct
    test if PageTitle == title?
    for each field in fieldList:
        check that it appears in order on the screen
    for each field in linkList:
        check that it appears in order on the screen
    test if param1 is whatever...
    test if param2 is whatever...
    etc.
    test that the bottom of the screen is correct
}

ขั้นตอนเล็ก ๆ น้อย ๆ มากมาย (ชุดเครื่องมือ)

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

testScreenTop()
verifyLinks(list)
testScreenBottom()

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

ตัดและวาง

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

การทดสอบ UI อัตโนมัติ

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


0

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


0

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

ลองนึกภาพสถานการณ์ข้อผิดพลาดต่อไปนี้:

  • ใครบางคนทำการเปลี่ยนแปลงกับฐานข้อมูลซึ่งการทดสอบของคุณขึ้นอยู่กับ
  • ผลที่ตามมา: การทดสอบอัตโนมัติ 2933 ครั้งใน 117 ข้อล้มเหลว

คุณจะทำอะไร?

  • (1) แก้ไขการทดสอบ 117 ครั้ง?
  • (2) ลบการทดสอบ 117 ครั้งและนำไปใช้ใหม่ผ่านการคัดลอกและวางใหม่ สิ่งนี้อาจจะง่ายกว่า (1)
  • (3) refactor การทดสอบเพื่อแยกรหัสทั่วไปเพื่อให้ในอนาคตคุณต้องปรับใช้เพียงวิธีเดียว (หรือไม่กี่) เพื่อแก้ไขการทดสอบ (ดูคำตอบของ @pdr หรือ @Michael Brown)
  • (4) ลบการทดสอบ 117 ครั้งโดยไม่ทำการทดสอบซ้ำอีกครั้ง

จากประสบการณ์ของฉัน:

เมื่อแนะนำการจัดการทดสอบแบบอัตโนมัติอย่าง "คัดลอกและวางการทดสอบ": คุณจะได้รับการทดสอบจำนวนมากในเวลาอันสั้น

หลังจากการจัดการ "สถานการณ์ข้อผิดพลาด" บางคนชอบ (4) เนื่องจากการแก้ไข "การคัดลอกและทดสอบวาง" มีราคาแพงมาก

ทำถูกต้องตั้งแต่แรก (3) จะไม่เร็วนัก แต่เพิ่มโอกาสที่การทดสอบจะอยู่รอด

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