วิธีหลีกเลี่ยงข้อผิดพลาดเชิงตรรกะในรหัสเมื่อ TDD ไม่ได้ช่วย?


67

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

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

นี่คือโค้ดที่เกี่ยวข้อง:

now = datetime.datetime.utcnow()
today = now.date()
if event_date.date() == today:
    return "Today"

yesterday = today - datetime.timedelta(1)
if event_date.date() == yesterday:
    return "Yesterday"

delta = (now - event_date).days

if delta < 7:
    return _number_to_text(delta) + " days ago"

if delta < 30:
    weeks = math.floor(delta / 7)
    if weeks == 1:
        return "A week ago"

    return _number_to_text(weeks) + " weeks ago"

if delta < 365:
    ... # Handle months and years in similar manner.

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

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

if delta == 1:
    return "A day ago"

deltaหลังจากการคำนวณ

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

  • มันง่ายมากที่จะยอมรับความผิดพลาดเชิงตรรกะแม้ในซอร์สโค้ดที่ง่ายเช่นนั้น
  • การพัฒนาที่ขับเคลื่อนด้วยการทดสอบไม่ได้ช่วยอะไร

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

ฉันจะหลีกเลี่ยงการสร้างข้อผิดพลาดนี้ตั้งแต่แรกได้อย่างไร


38
โดยมีกรณีทดสอบหรือไม่ ดูเหมือนว่าคุณจะค้นพบมันในภายหลังและเชื่อมโยงกับ TDD
Julurous

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

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

43
ขอแสดงความยินดีคุณค้นพบภูมิปัญญาเก่าที่ไม่มีการทดสอบใด ๆ ที่สามารถพิสูจน์ว่าไม่มีข้อบกพร่อง แต่หากคุณกำลังมองหาเทคนิคในการสร้างความครอบคลุมที่ดีขึ้นของโดเมนอินพุตที่เป็นไปได้คุณจะต้องทำการวิเคราะห์โดเมนโดเมนเคสและขอบที่เทียบเท่าของโดเมนนั้นอย่างละเอียด เทคนิคเก่าและเป็นที่รู้จักทั้งหมดรู้จักกันมานานก่อนเทอม TDD ถูกประดิษฐ์ขึ้น
Doc Brown

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

คำตอบ:


57

เหล่านี้เป็นชนิดของข้อผิดพลาดที่คุณมักจะพบในrefactorขั้นตอนของสีแดง / เขียว / refactor อย่าลืมขั้นตอนนั้น! พิจารณา refactor เช่นนี้ (ยังไม่ทดลอง):

def pluralize(num, unit):
    if num == 1:
        return unit
    else:
        return unit + "s"

def convert_to_unit(delta, unit):
    factor = 1
    if unit == "week":
        factor = 7 
    elif unit == "month":
        factor = 30
    elif unit == "year":
        factor = 365
    return delta // factor

def best_unit(delta):
    if delta < 7:
        return "day"
    elif delta < 30:
        return "week"
    elif delta < 365:
        return "month"
    else:
        return "year"

def human_friendly(event_date):
    date = event_date.date()
    today = now.date()
    yesterday = today - datetime.timedelta(1)
    if date == today:
        return "Today"
    elif date == yesterday:
        return "Yesterday"
    else:
        delta = (now - event_date).days
        unit = best_unit(delta)
        converted = convert_to_unit(delta, unit)
        pluralized = pluralize(converted, unit)
        return "{} {} ago".format(converted, pluralized)

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

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

กล่าวอีกนัยหนึ่งการปรับโครงสร้างไม่ได้เป็นเพียงการทำให้สวย มันช่วยให้มนุษย์สังเกตเห็นข้อผิดพลาดที่คอมไพเลอร์ไม่สามารถทำได้ง่ายขึ้น


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

@Dupuplicator แน่นอน แต่จากนั้นขึ้นอยู่กับภาษา / วัฒนธรรมที่คุณตั้งเป้าหมายคุณอาจหนีไปด้วยการปรับเปลี่ยนการpluralizeใช้numและunitการสร้างคีย์บางชนิดเพื่อดึงสตริงรูปแบบจากไฟล์ตาราง / ทรัพยากรบางไฟล์ หรือคุณอาจต้องเขียนตรรกะใหม่อย่างสมบูรณ์เพราะคุณต้องการหน่วยที่แตกต่างกัน ;-)
Hulk

4
ปัญหายังคงอยู่แม้จะมีการปรับโครงสร้างซ้ำอีกครั้งซึ่งก็คือ "เมื่อวาน" ไม่ได้ทำให้เข้าใจได้อย่างชัดเจนในช่วงเวลาเช้าตรู่ของวันรุ่งขึ้น (ไม่นานหลังจาก 12:01 น.) ในแง่ที่เป็นมิตรกับมนุษย์สิ่งที่เกิดขึ้นในเวลา 23.59 น. ก็ไม่ได้เปลี่ยนจาก "วันนี้" เป็น "เมื่อวาน" ทันทีเมื่อนาฬิกาหลุดผ่านเที่ยงคืน มันเปลี่ยนจาก "1 นาทีก่อน" เป็น "2 นาทีก่อน" "วันนี้" หยาบเกินไปในแง่ของบางสิ่งที่เกิดขึ้น แต่ไม่กี่นาทีที่ผ่านมาและ "เมื่อวาน" เต็มไปด้วยปัญหานกฮูกกลางคืน
David Hammen

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

149

การพัฒนาที่ขับเคลื่อนด้วยการทดสอบไม่ได้ช่วยอะไร

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

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


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

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

15
TDD นั้นดีพอ ๆ กับแบบทดสอบที่เขียน
Mindwin

การสังเกตอื่น: การเพิ่มการทดสอบสำหรับกรณีนี้จะปรับปรุงการออกแบบโดยบังคับให้เรานำสิ่งนั้นdatetime.utcnow()ออกจากฟังก์ชันและแทนที่จะส่งผ่านnowเป็นอาร์กิวเมนต์ (ทำซ้ำ) แทน
Toby Speight

114

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

การทดสอบจะไม่ช่วยได้มากหากปัญหามีการกำหนดอย่างไม่ดี คุณเห็นได้ชัดว่าการผสมวันปฏิทินกับวันที่นับเป็นชั่วโมง หากคุณยึดติดกับวันตามปฏิทินในเวลา 1:00 น. 26 ชั่วโมงที่ผ่านมาไม่ใช่เมื่อวาน และถ้าคุณยึดติดกับชั่วโมงชั่วโมงที่ผ่านมา 26 ชั่วโมงผ่านไป 1 วันก่อนโดยไม่คำนึงถึงเวลา


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

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

1
ฉันชอบคำตอบนี้เพราะชี้ให้เห็นปัญหาที่แท้จริง: จุดในเวลาและวันที่เป็นปริมาณที่แตกต่างกันสองแบบ สิ่งเหล่านี้เกี่ยวข้องกัน แต่เมื่อคุณเริ่มเปรียบเทียบสิ่งต่าง ๆ ไปทางทิศใต้อย่างรวดเร็ว ในการเขียนโปรแกรมตรรกะวันที่และเวลาเป็นสิ่งที่ยากที่สุดที่จะทำให้ถูกต้อง ฉันไม่ชอบที่การใช้งานวันที่จำนวนมากโดยทั่วไปจะเก็บวันที่เป็นเวลา 0:00 มันทำให้เกิดความสับสนมาก
Pieter B

38

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

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


2
การมีการทดสอบที่เขียนโดยบุคคลอื่นที่ไม่ใช่นักพัฒนานั้นเป็นความคิดที่ดีเสมอหมายความว่าทั้งสองฝ่ายต้องมองข้ามเงื่อนไขอินพุตเดียวกันสำหรับข้อผิดพลาดเพื่อให้สามารถใช้งานได้
Michael Kay

35

มีสองวิธีที่ปกติฉันพบว่าสามารถช่วยได้

ก่อนอื่นฉันมองหาเคสแบบขอบ นี่คือสถานที่ที่พฤติกรรมเปลี่ยนไป ในกรณีของคุณพฤติกรรมจะเปลี่ยนไปตามลำดับของจำนวนเต็มบวก มีกรณีขอบที่ศูนย์หนึ่งที่เจ็ด ฯลฯ ฉันจะเขียนกรณีทดสอบที่และรอบกรณีขอบ ฉันมีกรณีทดสอบที่ -1 วัน 0 วัน 1 ชั่วโมง 23 ชั่วโมง 24 ชั่วโมง 25 ชั่วโมง 6 วัน 7 วัน 8 วัน ฯลฯ

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


9
นี่คือส่วนหนึ่งที่สำคัญจริงๆของ TDD ที่มักจะถูกมองข้ามและผมเคยเห็นไม่ค่อยได้พูดคุยเกี่ยวกับในบทความและคำแนะนำ - มันจริงๆที่สำคัญในการทดสอบกรณีที่ทันสมัยและเงื่อนไขขอบเขตเท่าที่ผมพบว่าเป็นแหล่งที่มาของ 90% ของบัก - ของโดย ข้อผิดพลาด -one, over and underflows, วันสุดท้ายของเดือน, เดือนสุดท้ายของปี, leap-years และอื่น ๆ
GoatInTheMachine

2
@ GoatInTheMachine - และ 90% ของข้อผิดพลาด 90% เหล่านี้อยู่ในช่วงเปลี่ยนผ่านการปรับเวลาตามฤดูกาล ... Hahaha
Caleb

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

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

14

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

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

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

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

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

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

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

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


12

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

ทำไมจะไม่ล่ะ? ฟังดูเหมือนความคิดที่ดีทีเดียว!

การเพิ่มสัญญา (การยืนยัน) ลงในโค้ดเป็นวิธีที่ดีในการปรับปรุงความถูกต้อง โดยทั่วไปเราเพิ่มพวกเขาเป็นเงื่อนไขเบื้องต้นในรายการฟังก์ชั่นและpostconditionsเมื่อกลับมาฟังก์ชั่น ตัวอย่างเช่นเราสามารถเพิ่ม postcondition ที่ค่ากลับมาทุกคนมีทั้งในรูปแบบ "เป็น [หน่วย] ที่ผ่านมา" หรือ "[หมายเลข] [หน่วย] s ที่ผ่านมา" เมื่อทำในลักษณะที่มีระเบียบวินัยสิ่งนี้นำไปสู่การออกแบบตามสัญญาและเป็นหนึ่งในวิธีการทั่วไปในการเขียนรหัสความเชื่อมั่นสูง

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

ใน PBT แทนการทดสอบผลลัพธ์ของรหัสเฉพาะคุณทดสอบว่าผลลัพธ์เป็นไปตามคุณสมบัติบางอย่าง ตัวอย่างเช่นหนึ่งในทรัพย์สินของreverse()ฟังก์ชั่นเป็นที่สำหรับรายการใด ๆ,l reverse(reverse(l)) = lส่วนต่าง ๆ ของการทดสอบการเขียนเช่นนี้คือคุณสามารถให้เครื่องยนต์ PBT สร้างรายการโดยพลการสองสามร้อยรายการ หากไม่มีให้ทำเช่นนั้นเอ็นจิ้น "ย่อ" กรณีที่ล้มเหลวเพื่อค้นหารายการขั้นต่ำที่ทำให้โค้ดของคุณเสียหาย ดูเหมือนว่าคุณกำลังเขียน Python ซึ่งมีสมมติฐานเป็นกรอบ PBT หลัก

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


2
นี่คือทางออกที่ถูกต้องสำหรับปัญหาประเภทนี้ ชุดของผลลัพธ์ที่ถูกต้องนั้นง่ายต่อการกำหนด (คุณสามารถให้นิพจน์ปกติอย่างง่าย ๆ ได้/(today)|(yesterday)|([2-6] days ago)|...) จากนั้นคุณสามารถเรียกใช้กระบวนการด้วยอินพุตที่เลือกแบบสุ่มจนกว่าคุณจะพบสิ่งที่ไม่ได้อยู่ในชุดของผลลัพธ์ที่คาดหวัง การใช้วิธีการนี้จะทำให้ดักจับข้อผิดพลาดนี้และไม่ต้องการให้ตระหนักว่าข้อผิดพลาดอาจมีอยู่ก่อน
จูลส์

@Jules ดูเพิ่มเติมการตรวจสอบสถานที่ให้บริการทดสอบ / ฉันมักจะเขียนการทดสอบอสังหาริมทรัพย์ในระหว่างการพัฒนาเพื่อให้ครอบคลุมกรณีที่ไม่คาดฝันมากที่สุดเท่าที่จะเป็นไปได้และบังคับให้ฉันคิดถึงคุณสมบัติทั่วไป / ค่าคงที่ ฉันบันทึกการทดสอบแบบถอยหลังครั้งเดียวเพื่อการถดถอยและ (ซึ่งปัญหาของผู้เขียนเป็นตัวอย่างของ)
Warbo

1
ถ้าคุณทำการวนซ้ำมากในการทดสอบถ้าจะใช้เวลานานมากซึ่งเอาชนะหนึ่งในเป้าหมายหลักของการทดสอบหน่วย: ทำการทดสอบอย่างรวดเร็ว !
CJ Dennis

5

นี่คือตัวอย่างที่การเพิ่มมอดูลาร์เล็กน้อยจะมีประโยชน์ หากมีการใช้เซ็กเมนต์รหัสที่ผิดพลาดได้หลายครั้งก็เป็นวิธีที่ดีที่จะห่อหุ้มด้วยฟังก์ชันถ้าเป็นไปได้

def time_ago(delta, unit):
    delta_str = _number_to_text(delta) + " " + unit;
    if delta == 1:
        return delta_str + " ago"
    else:
        return delta_str = "s ago"

now = datetime.datetime.utcnow()
today = now.date()
if event_date.date() == today:
    return "Today"

yesterday = today - datetime.timedelta(1)
if event_date.date() == yesterday:
    return "Yesterday"

delta = (now - event_date).days

if delta < 7:
    return time_ago(delta, "day")

if delta < 30:
    weeks = math.floor(delta / 7)
    return time_ago(weeks, "week")

if delta < 365:
    months = math.floor(delta / 31)
    return time_ago(months, "month")

5

การพัฒนาที่ขับเคลื่อนด้วยการทดสอบไม่ได้ช่วยอะไร

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

  • อย่าเขียนการทดสอบเพื่อยืนยันการทำงานภายใต้การทดสอบตามที่คุณทำ เขียนข้อสอบที่ตั้งใจทำ

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

เทคนิคหลักในการเขียนซอฟต์แวร์ที่แข็งแกร่งยังเป็นเทคนิคหลักในการทำความเข้าใจวิธีการเขียนการทดสอบที่มีประสิทธิภาพ:

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

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


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


1

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

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

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

แต่การเขียนมันทำให้เราต้องยอมรับความจริงที่ว่าเราจะผลิตซอฟต์แวร์รถบั๊กกี้ เกือบทุกแบบฝึกหัดการพัฒนาซอฟต์แวร์ที่ทันสมัยอยู่ในระดับหนึ่งที่สร้างขึ้นรอบ ๆ ทั้งการป้องกันข้อบกพร่องจากการปรากฏตัวในสถานที่แรกหรือการปกป้องตัวเราเองจากผลของข้อบกพร่องที่เราผลิตอย่างหลีกเลี่ยงไม่ได้:

  • การรวบรวมข้อกำหนดอย่างละเอียดทำให้เราทราบว่าพฤติกรรมที่ไม่ถูกต้องมีลักษณะอย่างไรในรหัสของเรา
  • การเขียนโค้ดที่สะอาดและมีการออกแบบอย่างระมัดระวังทำให้ง่ายขึ้นในการหลีกเลี่ยงการแนะนำบั๊กในตอนแรกและง่ายต่อการแก้ไขเมื่อเราระบุมัน
  • การทดสอบการเขียนช่วยให้เราสามารถจัดทำบันทึกสิ่งที่เราเชื่อว่าข้อบกพร่องที่เลวร้ายที่สุดที่เป็นไปได้ในซอฟต์แวร์ของเราคือการพิสูจน์ว่าเราหลีกเลี่ยงข้อบกพร่องเหล่านั้น TDD สร้างการทดสอบเหล่านั้นก่อนรหัส BDD ได้มาจากการทดสอบเหล่านั้นจากข้อกำหนดและการทดสอบหน่วยแบบเก่าจะสร้างการทดสอบหลังจากที่โค้ดถูกเขียน แต่พวกเขาก็ป้องกันการถดถอยที่เลวร้ายที่สุดในอนาคต
  • การตรวจสอบจากเพื่อนหมายความว่าทุกครั้งที่มีการเปลี่ยนแปลงรหัสดวงตาอย่างน้อยสองคู่ได้เห็นรหัสทำให้ลดข้อผิดพลาดที่เกิดขึ้นบ่อยครั้งในต้นแบบ
  • การใช้ตัวติดตามบั๊กหรือตัวติดตามเรื่องราวของผู้ใช้ที่ปฏิบัติต่อข้อผิดพลาดเนื่องจากเรื่องราวของผู้ใช้หมายความว่าเมื่อบั๊กปรากฏขึ้นพวกเขาจะถูกติดตามและจัดการในที่สุดโดยไม่ลืมและปล่อยให้หลงทางอยู่เสมอ
  • การใช้เซิร์ฟเวอร์ staging หมายความว่าก่อนที่จะมีการปล่อยรุ่นใหญ่บั๊ก show-stopper ใด ๆ มีโอกาสปรากฏขึ้นและได้รับการจัดการ
  • การใช้การควบคุมเวอร์ชันหมายความว่าในสถานการณ์ที่เลวร้ายที่สุดกรณีที่รหัสที่มีข้อบกพร่องสำคัญถูกส่งไปยังลูกค้าคุณสามารถดำเนินการย้อนกลับฉุกเฉินและรับผลิตภัณฑ์ที่เชื่อถือได้กลับสู่มือลูกค้าขณะที่คุณแยกแยะ

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


1

คุณไม่เคยนึกถึงกรณีนี้มาก่อนและดังนั้นจึงไม่มีกรณีทดสอบ

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

สำหรับนักบินอัตโนมัติคุณจะใช้เวลามากกว่าเครื่องมือง่ายๆ

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

นอกจากนี้หากผู้ทดสอบเป็นบุคคลที่แตกต่างจากผู้พัฒนามักจะพบกรณีที่สำคัญกว่า


1

(และเชื่อว่าเกี่ยวข้องกับเขตเวลาแม้จะมีการใช้ UTC ในรหัสอย่างสม่ำเสมอ)

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

ตัวอย่าง: ในออสเตรเลียมีเหตุการณ์เกิดขึ้นเวลา 9.00 น. ตามเวลาท้องถิ่น เวลา 11.00 น. จะมีการแสดงเป็น "เมื่อวาน" เพราะวันที่ UTC มีการเปลี่ยนแปลง


0
  • ให้คนอื่นเขียนแบบทดสอบ วิธีนี้มีคนที่ไม่คุ้นเคยกับการใช้งานของคุณอาจตรวจสอบสถานการณ์ที่ไม่ค่อยเกิดขึ้นซึ่งคุณไม่ได้คิด

  • ถ้าเป็นไปได้ฉีดกรณีทดสอบเป็นคอลเลกชัน สิ่งนี้ทำให้การเพิ่มการทดสอบอื่นง่ายขึ้นเหมือนกับการเพิ่มอีกบรรทัดyield return new TestCase(...)หนึ่ง สิ่งนี้สามารถไปในทิศทางของการทดสอบเชิงสำรวจโดยอัตโนมัติการสร้างกรณีทดสอบ: "เรามาดูกันว่าโค้ดจะส่งคืนในวินาทีใดของหนึ่งสัปดาห์ที่ผ่านมา"


0

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

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

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

การใช้ TDD อย่างถูกต้องไม่ได้หมายความว่าคุณจะเขียนรหัสปราศจากข้อผิดพลาดหมายความว่าคุณจะเขียนข้อบกพร่องน้อยลง คุณพูด:

ความต้องการค่อนข้างชัดเจน

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


0

มันง่ายมากที่จะยอมรับความผิดพลาดเชิงตรรกะแม้ในซอร์สโค้ดที่ง่ายเช่นนั้น

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

การพัฒนาที่ขับเคลื่อนด้วยการทดสอบไม่ได้ช่วยอะไร

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

ที่น่าเป็นห่วงก็คือฉันไม่สามารถดูได้ว่าข้อบกพร่องดังกล่าวสามารถหลีกเลี่ยงได้อย่างไร

คุณทำไม่ได้ ไม่ใช่แม้แต่นาซ่าที่ค้นพบวิธีการหลีกเลี่ยงข้อบกพร่อง เราไม่ได้เป็นมนุษย์เช่นกัน

นอกจากคิดก่อนเขียนรหัส

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

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

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

สำหรับรหัสภารกิจสำคัญคุณสามารถทำสิ่งที่คุณพูดได้ แต่ไม่ใช่สำหรับรหัสมาตรฐานในชีวิตประจำวันของคุณ

ฉันจะหลีกเลี่ยงการสร้างข้อผิดพลาดนี้ตั้งแต่แรกได้อย่างไร

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

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


-2

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

ดังนั้นสิ่งนี้หมายความว่าแม้พยายามดักจับบั๊กทั้งหมดก็เป็นการออกกำลังกายที่ไร้ประโยชน์และดังนั้นคุณควรใช้เทคนิคเช่น TDD เป็นวิธีการเขียนโค้ดที่ดีกว่ารหัสที่มีบั๊กน้อยกว่าไม่ใช่บั๊ก 0

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

ทางเลือกอื่นเช่นการทดสอบการรวมระบบหรือการทดสอบการทดสอบระบบและการบันทึกและการวิเคราะห์บันทึกเหล่านั้น

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

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


นี่คือความพ่ายแพ้อย่างมาก That in turn means you should spend less time using these techniques- แต่คุณเพิ่งบอกว่ามันจะช่วยให้มีข้อบกพร่องน้อยลง?!
JᴀʏMᴇᴇ

@ JᴀʏMᴇᴇเพิ่มเติมทัศนคติในทางปฏิบัติของเทคนิคที่ทำให้คุณได้รับปังที่สุดสำหรับ buck.I ของคุณรู้ว่าคนที่มีความภาคภูมิใจที่พวกเขาใช้จ่าย 10 ครั้งการเขียนการทดสอบกว่าที่พวกเขาทำในรหัสของพวกเขาและพวกเขายังคงมีข้อบกพร่องดังนั้นความเหมาะสมมากกว่าดันทุรัง เกี่ยวกับเทคนิคการทดสอบเป็นสิ่งจำเป็น และการทดสอบการรวมจะต้องใช้ต่อไปดังนั้นจึงต้องใช้ความพยายามมากกว่าในการทดสอบหน่วย
gbjbaanb
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.