ฉันจะใช้การทดสอบหน่วยและ TDD เพื่อทดสอบแอพที่ขึ้นอยู่กับการดำเนินการ CRUD ของฐานข้อมูลเป็นส่วนใหญ่ได้อย่างไร


22

ที่ทำงานหนึ่งในโครงการของฉันส่วนใหญ่เกี่ยวกับการรับส่งข้อมูลจากไคลเอนต์ภายนอกและเก็บไว้ในฐานข้อมูล มันเป็นแอพพลิเคชั่นขององค์กร Java ที่ใช้ JPA และตรรกะส่วนใหญ่ของเราหมุนรอบการดำเนินการ CRUD

ข้อบกพร่องส่วนใหญ่ของเราเกี่ยวข้องกับ JPA ไม่ทางใดก็ทางหนึ่ง

  • ตัวอย่างที่ 1: ถ้าคุณคลิกปุ่มบันทึกสองครั้ง JPA อาจลองแทรกเอนทิตีเดียวกันในฐานข้อมูลเป็นครั้งที่สองทำให้เกิดการละเมิดคีย์หลัก
  • ตัวอย่างที่ 2: คุณดึงเอนทิตีจากฐานข้อมูลแก้ไขและลองอัปเดตข้อมูล JPA อาจพยายามสร้างอินสแตนซ์ใหม่แทนการอัปเดตเก่า

บ่อยครั้งที่โซลูชันต้องการเพิ่ม / ลบ / เปลี่ยนคำอธิบายประกอบ JPA บางครั้งก็เกี่ยวข้องกับการปรับเปลี่ยนตรรกะ DAO

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

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

TDD ดูเหมือนว่าไม่เหมาะสมเพราะการปรับใช้ + ข้อเสนอแนะการทดสอบช้ามากทำให้ฉันไม่ได้ผลมาก การปรับใช้ + ข้อเสนอแนะการทดสอบวนใช้เวลา 3 นาทีและนั่นก็ต่อเมื่อฉันรันการทดสอบเฉพาะเกี่ยวกับรหัสที่ฉันเขียน ในการรันการทดสอบการรวมระบบทั้งหมดจะใช้เวลา 30+ นาที

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


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


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

@randomA ถูกต้องฉันแก้ไขคำถามของฉันเพื่อพูดอย่างชัดเจน ฉันไม่เข้าใจว่าทำไมคุณแนะนำให้ฉันเปลี่ยนคำถาม คุณสามารถทำอย่างละเอียด? ฉันต้องการให้เป็นส่วนหนึ่งในการทดสอบหน่วยที่นั่นเพราะฉันค่อนข้างจะเขียนทดสอบหน่วยกว่าการทดสอบการรวม (แม้ว่าฉันรู้ว่าunit testing != TDD)
แดเนียลแคปแลน

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


คำตอบ:


7

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

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

แต่ถ้าคุณสามารถทำได้ 10 ครั้งด้วย H2 สำหรับทุก ๆ ระบบที่สมบูรณ์


เป็นความคิดที่ดี แต่ฉันยังคงต้องปรับใช้กับเซิร์ฟเวอร์แอป AFAIK นั่นเป็นจำนวนมากในเวลา 3+ นาที ที่กล่าวว่ามันคุ้มค่าที่จะทำ แต่มันก็ยังยากที่จะจินตนาการถึงการรันการทดสอบบ่อยเท่าที่ฉันจะทำการทดสอบหน่วยและดังนั้นจึงดูเหมือนว่าไม่มีประสิทธิภาพในการพัฒนาโดยใช้ TDD
แดเนียลแคปแลน

1
ฉันคิดว่ามักจะมีวิธีแก้ไขความต้องการนั้น (เช่นdocs.oracle.com/middleware/1212/toplink/TLADG/testingjpa.htm ) โอกาสสูงที่จะทำงานมากกว่าที่เป็นธรรม อีกตัวเลือกหนึ่งคือรับเซิร์ฟเวอร์ทดสอบที่หนักกว่าและใช้งานแบบขนาน
soru

1
@tietyT การพิสูจน์แนวคิดของฉันเองด้วยหน่วย hsqldb ทดสอบแอปพลิเคชันเว็บบน crud ใน github: TestingWithHsqldb - การทดสอบหน่วยไม่จำเป็นต้องใช้แอป

3

ฐานข้อมูลสามารถทดสอบหน่วยได้ง่าย - คุณต้องมีขั้นตอนและธุรกรรมที่เก็บไว้

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

หวังว่าสิ่งนี้จะให้ข้อมูลเชิงลึกเกี่ยวกับวิธีดำเนินการภายในกรอบของคุณ


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

เราเคยเรียกใช้การทดสอบหน่วยฐานข้อมูลสำหรับ SQL ของเรา แต่จากนั้นจะเป็นการ sprocs ขณะที่คุณสามารถไดเรกทอรีหน่วยทดสอบ SQL จาก SQL ขั้นตอนอื่น ๆ กรอบทดสอบหน่วยของเราเป็น MSTest จึงทำให้ความรู้สึกที่จะเรียกพวกเขาจากที่นั่น (เดี๋ยวก่อนเราได้เห็บสีเขียวในการสร้างเซิร์ฟเวอร์ซึ่งเป็นปัจจัยที่สำคัญที่สุด) หากคุณมีฐานข้อมูลอยู่เสมอ (และเราได้ทำการทดสอบแบบ int อยู่แล้ว) ดังนั้นจึงง่ายต่อการอัปโหลดรหัส sql ทั้งหมดและเรียกใช้การทดสอบหน่วยทั้งหมดบนเซิร์ฟเวอร์การสร้าง บางครั้งคุณก็ต้องจริงจังกับสิ่งเหล่านี้
gbjbaanb

ฉันไม่คิดว่าคุณจะตอบประโยคแรกของฉัน
Daniel Kaplan

ดีเพียงใช้หน่วย jpa แล้ว ฉันไม่สามารถตอบได้ว่ารหัส JPA ของคุณทำงานอย่างไร (หรือไม่) เพียงลองเสนอแนวคิดในการทดสอบ sql นั้นใน db
gbjbaanb

3

คนอื่น ๆ ตอบด้วย "จำลองฐานข้อมูลของคุณ!" - แต่อะไรคือจุดในการเยาะเย้ยเลเยอร์ DB ของคุณถ้าคุณต้องการทดสอบว่ามันโต้ตอบกับโค้ดของคุณอย่างไร

สิ่งที่คุณกำลังมองหาคือการทดสอบการรวมและ / หรือการทดสอบ UI อัตโนมัติ คุณพูดถึงว่าปัญหาเกิดขึ้นเมื่อ:

*If you click the save button twice*

วิธีเดียวที่จะทดสอบสิ่งนี้คือการเขียนการทดสอบ UI อัตโนมัติเพื่อคลิกที่ปุ่มสองครั้ง อาจตรวจสอบซีลีเนียม

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


สิ่งนี้อ่านได้มากกว่าคำพูดที่เยินยอกว่าคำตอบ
ริ้น

ฉันตอบคำถามสามครั้ง - การทดสอบการรวม, การทดสอบ GUI และ / หรือการทดสอบหน่วย DB ใช่มันพูดจาโผงผางนิดหน่อยฉันจะแก้ไขมันให้เป็นรูปร่างที่เพรียวบางตอนนี้
Rocklan

1
"วิธีเดียวที่จะทดสอบสิ่งนี้คือการเขียนการทดสอบ UI อัตโนมัติเพื่อคลิกที่ปุ่มสองครั้งอาจลองดูซีลีเนียม" ในสถานการณ์เช่นนี้แบ็กเอนด์จะป้องกันสิ่งนั้นได้ดีกว่ามิฉะนั้น UI จะเข้าถึงฐานข้อมูลโดยตรง
Daniel Kaplan

0

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

คุณถูกต้องที่ TDD สามารถเริ่มต้นพังทลายได้เมื่อคุณต้องการทำการทดสอบที่ไม่เหมาะสำหรับการทดสอบหน่วย (เช่นการทดสอบการรวม / ระบบ) - สิ่งนี้ก่อให้เกิดการถกเถียงกันมากมายในการ "TDD ตาย?" การถกเถียงระหว่าง Kent Beck, Martin Fowler และ David Heinemeier Hansson: http://martinfowler.com/articles/is-tdd-dead/

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