TDD ที่มีรูปแบบพื้นที่เก็บข้อมูล


10

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

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

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

คำตอบ:


11

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

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

public void Save(Car car)
{
    session.Save(car);
}

แต่ลองดูอีกตัวอย่างหนึ่งเช่นดึงรถด้วย ID มันอาจดูเหมือน

public function GetCarWithId(String id)
{
    return Session.QueryOver<Car>()
                    .Where(x => x.Id == id)
                    .SingleOrDefault();
}

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

ตัวเลือกที่ 1: จำลองการโทรที่เกิดขึ้นกับเฟรมเวิร์ก ORM

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

ตัวเลือกที่ 2: (อีกครั้ง) สร้างฐานข้อมูลจากการทดสอบ

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

ตัวเลือก 3: ทดสอบกับฐานข้อมูลจริง

อีกวิธีหนึ่งคือการทดสอบฐานข้อมูลจริงและแยก unittest คุณสามารถทำสิ่งนี้ได้หลายวิธี: ล้อมรอบการทดสอบของคุณด้วยธุรกรรมทำความสะอาดด้วยตนเอง (ไม่แนะนำให้ดูแลยากมาก) สร้างฐานข้อมูลใหม่อย่างสมบูรณ์หลังจากแต่ละขั้นตอน ... ขึ้นอยู่กับแอปพลิเคชันที่คุณกำลังสร้าง ไม่เป็นไปได้ ในแอปพลิเคชันของฉันฉันสามารถสร้างฐานข้อมูลการพัฒนาท้องถิ่นจากแหล่งควบคุมและ unittests ของฉันบน repositories ใช้ธุรกรรมเพื่อแยกการทดสอบจากกันอย่างสมบูรณ์ (เปิดธุรกรรมแทรกข้อมูลพื้นที่เก็บข้อมูลทดสอบธุรกรรมย้อนกลับ) ทุกครั้งแรกสร้างการตั้งค่าฐานข้อมูลการพัฒนาท้องถิ่นแล้วทำการ unittests ที่แยกธุรกรรมสำหรับที่เก็บบนฐานข้อมูลการพัฒนาท้องถิ่นนั้น มัน'

อย่าทดสอบ DAL

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

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

'การทดสอบหน่วย' เป็นเพียงชื่อ

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


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

9
  1. อย่าทดสอบวิธีการเก็บข้อมูลเล็กน้อยหรือชัดเจน

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

    นี่เป็นหลักการเดียวกับที่ใช้กับคุณสมบัติเล็ก ๆ น้อย ๆ เช่นนี้

    public property SomeProperty
    {
        get { return _someProperty; }
        set { _someProperty = value; }
    }
    

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

  2. หากคุณยังต้องการทดสอบวิธีการเหล่านั้น ...

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

ข้อมูลเพิ่มเติม
The Full Stack, Part 3: การสร้าง Repository โดยใช้ TDD (เริ่มดูที่ประมาณ 16 นาที)


3
แน่นอนฉันเข้าใจสิ่งนี้ ถึงกระนั้นหากเป็นวิธีการของ TDD ฉันไม่ควรเขียนรหัสใด ๆ หากฉันไม่มีการทดสอบสำหรับรหัสนี้ก่อนใช่ไหม?
Thaven

1
@Thaven - มีวิดีโอหลายรายการใน youtube ชื่อ "is tdd dead?" ดูพวกเขา พวกเขาพูดถึงประเด็นที่น่าสนใจมากมายซึ่งหนึ่งในนั้นก็คือความคิดที่ว่าการใช้ TDD ในทุกระดับของการสมัครไม่จำเป็นต้องเป็นความคิดที่ดีที่สุด "ไม่มีรหัสโดยไม่มีการทดสอบที่ล้มเหลว" เป็นตำแหน่งที่มากเกินไปเป็นหนึ่งในข้อสรุป
จูลส์

2
@Jules: อะไรคือtl; dw?
Robert Harvey

1
@RobertHarvey มันยากที่จะสรุป แต่ประเด็นที่สำคัญที่สุดคือการปฏิบัติ TDD ในฐานะศาสนาที่ต้องปฏิบัติตามเสมอคือความผิดพลาด ทางเลือกในการใช้งานเป็นส่วนหนึ่งของการแลกเปลี่ยนและคุณต้องพิจารณาว่า (1) คุณสามารถทำงานได้เร็วขึ้นโดยไม่มีปัญหาและและ (2) อาจผลักดันคุณไปสู่โซลูชันที่ซับซ้อนกว่าที่คุณต้องการ โดยเฉพาะอย่างยิ่งถ้าคุณพบว่าตัวเองใช้ mocks มาก
จูลส์

1
+1 สำหรับแต้ม # 1 การทดสอบอาจผิดปกติเพียง แต่พวกเขามักไม่สำคัญ ไม่มีประโยชน์ที่จะทดสอบฟังก์ชั่นที่มีความถูกต้องชัดเจนกว่าการทดสอบ ไม่เหมือนกับการได้รับความครอบคลุมของรหัส 100% จะทำให้คุณใกล้เคียงกับการทดสอบทุกการประมวลผลของโปรแกรมที่เป็นไปได้ดังนั้นคุณอาจจะฉลาดพอที่จะใช้ความพยายามในการทดสอบ
Doval
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.