เบื่อกับการพิมพ์ข้อมูลทดสอบลงในคอนโซลหลายสิบครั้งเพื่อตรวจสอบงานของคุณหรือไม่? ยินดีต้อนรับสู่แมว ฉันจะบอกคุณว่าคุณสามารถทำอะไรกับมันได้บ้าง
เป้าหมายสูงสุดของเนื้อหานี้คือทำให้การเปิดตัวงานที่ได้รับการแก้ไขโดยอัตโนมัติด้วยพารามิเตอร์ต่างๆ และตรวจสอบผลลัพธ์โดยไม่ต้องทำการเปลี่ยนแปลงซอร์สโค้ด ตามที่คุณอาจเข้าใจแล้วจากชื่อเรื่อง ผู้ช่วยหลักของเราในเรื่องที่ค่อนข้างง่ายนี้คือ
JUnit หากคุณยังไม่เคยได้ยินเกี่ยวกับ
Unit Testing และ
Unit Tests ฉันขอแนะนำให้คุณพักสักหน่อยและทำความคุ้นเคยกับแนวคิดเหล่านี้ โชคดีที่มีข้อมูลบนอินเทอร์เน็ตเพียงพอ ไม่ คุณไม่ต้องการเหรอ? โอเค ฉันคิดว่านี่จะไม่กลายเป็นปัญหาใหญ่สำหรับการทำความเข้าใจกับสิ่งที่เกิดขึ้น ท้ายที่สุดคุณรู้ไหมว่าการทดสอบและการทดสอบโดยทั่วไปคืออะไร? คุณทำเช่นนี้ทุกครั้งที่เริ่มงาน ป้อนข้อมูลเริ่มต้นและเปรียบเทียบผลลัพธ์ที่ได้กับสิ่งที่คุณคาดหวังที่จะเห็น
สวัสดีชาวโลก JUnit! JUnit คืออะไร? บน
เว็บไซต์อย่างเป็นทางการ ของโครงการ เราสามารถอ่านคำอธิบายต่อไปนี้:
JUnit เป็นเฟรมเวิร์กง่ายๆ ในการเขียนการทดสอบซ้ำ เป็นตัวอย่างของสถาปัตยกรรม xUnit สำหรับเฟรมเวิร์กการทดสอบหน่วย
สำหรับเรา นี่หมายถึงความสามารถในการเขียนคลาสที่ออกแบบมาเป็นพิเศษซึ่งวิธีการจะโต้ตอบกับโปรแกรมของเรา เปรียบเทียบผลลัพธ์ที่ได้กับคลาสอ้างอิง และแจ้งให้เราทราบหากไม่ตรงกัน เพื่อให้เข้าใจหลักการนี้ ให้พิจารณาตัวอย่างง่ายๆ สมมติว่าเรามีคลาสเสริม ซึ่งหนึ่งในวิธีการนั้นใช้ตัวแปรประเภท
int สองตัว แล้วส่งคืนผลรวม
นี่คือฟังก์ชันที่เราจะพยายามทดสอบ โชคดีที่ IDEA ที่เราชื่นชอบมีทุกสิ่งที่คุณต้องการเพื่อสร้างการทดสอบอย่างรวดเร็ว สิ่งที่เราต้องทำก็แค่วางเคอร์เซอร์ในบรรทัดประกาศคลาส กด "Alt + Enter" และเลือก "สร้างการทดสอบ" ในเมนูบริบท:
หลังจากที่คุณระบุตำแหน่งแล้ว คุณควรสร้างการทดสอบ IDEA แนะนำให้เลือกไลบรารีการทดสอบ (ในเอกสารนี้ฉันใช้ JUnit4 เพื่อให้คลาสไลบรารีเชื่อมต่อกับโปรเจ็กต์คุณต้องคลิกปุ่ม "แก้ไข") วิธีทดสอบและอื่น ๆ ตัวเลือก.
IDE จะสร้างเทมเพลตคลาสการทดสอบ: ClassName = TestClassName + "Test" MethodName = "test" + TestMethodName
เราเพียงแค่ต้องกรอกเนื้อหาของวิธีการ
วิธีการที่เรียกว่า “การยืนยัน” ซึ่งจัดทำโดย JUnit จะช่วยในเรื่องนี้ ด้วยวิธีที่เรียบง่าย งานของพวกเขาจะเป็นดังนี้: ผลลัพธ์ที่คาดหวังและผลลัพธ์ของการเรียกใช้เมธอดภายใต้การทดสอบจะถูกส่งผ่านไปยังเมธอด .assert* เพื่อความสะดวก คุณสามารถเพิ่มข้อความอธิบายเป็นพารามิเตอร์แรกได้ หากพารามิเตอร์ไม่ตรงกันในระหว่างการทดสอบ คุณจะได้รับแจ้งเกี่ยวกับเรื่องนี้ คุณสามารถเปิดคลาสทดสอบเพื่อดำเนินการได้เหมือนกับคลาสทั่วไป ฉันชอบใช้คีย์ผสม Ctrl+Shift+F10
มาระบุงานกันดีกว่า ตามทฤษฎี ทุกอย่างเรียบง่ายและสวยงาม แต่ในบริบทของตัวอย่างที่เสนอ ไม่จำเป็นจริงๆ เราสามารถเชื่อถือคอมพิวเตอร์ให้บวกเลขสองตัวได้ เราสนใจมากขึ้นว่าสิ่งต่างๆ จะดำเนินไปอย่างไรกับปัญหาจริงที่นักเรียน JavaRush ได้รับการแก้ไข เช่น ฉันขอแนะนำให้ใช้ระดับอันเป็นที่รัก05.lesson12.bonus03
/* ปัญหาเกี่ยวกับอัลกอริธึม เขียนโปรแกรมที่: 1. ป้อนตัวเลข N > 0 จากคอนโซล 2. จากนั้นป้อนตัวเลข N จากคอนโซล 3. แสดงค่าสูงสุดของตัวเลข N ที่ป้อน */
เราจำเป็นต้องเขียนการทดสอบ 3 แบบ คือ จำนวนบวก ลบ และเซตคละ
ยิ่งเข้าป่า... นี่คือสิ่งที่น่าประหลาดใจรอเราอยู่:
public class UtilApp { public static void main(String[] args) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); //напишите здесь ваш code int n; int maximum; /* Конечно же я не буду размещать решение задачи ;) Код приведенный тут переработан для наглядности, и не в коем случае не означает что он должен присутствовать в "правильном решении" */ System.out.println(maximum); } }
ตรรกะของโปรแกรมอยู่ในเมธอด main()
ข้อมูลต้นฉบับจะไม่ถูกส่งไปยังวิธีการ แต่ถูกป้อนจากแป้นพิมพ์
เมธอด main() จะไม่ส่งคืนผลลัพธ์ แต่จะส่งออกไปยังคอนโซล
หากประเด็นแรกไม่เป็นปัญหาเป็นพิเศษ (เราสามารถเรียกเมธอด main() ได้ตามปกติ) สองประเด็นถัดไปจะบังคับให้เราเจาะลึกหัวข้อนั้นและทำให้สมองของเราตึงเครียด ฉันพบวิธีแก้ไขปัญหาหลายประการ:
การย้ายตรรกะในการหาค่าสูงสุดไปเป็นวิธีแยกกัน
ข้อดี: วิธีการที่ถูกต้องในแง่ของการปรับโครงสร้างใหม่
จุดด้อย: โปรแกรมมีโค้ดมากเกินไป มีโครงสร้างที่ไม่จำเป็น อย่างน้อยก็มีการเพิ่มอาร์เรย์หรือ ArrayList (ขึ้นอยู่กับรสนิยมและสี...) มีการทดสอบเฉพาะกลไกในการค้นหาค่าสูงสุดเท่านั้น ไม่ได้ตรวจสอบข้อมูลเข้าและออก
การเขียน wrapper สำหรับ System.in/System.out
ข้อดี: เราไม่ใช้ห้องสมุดบุคคลที่สาม
จุดด้อย: เส้นทางไม่เหมาะสำหรับผู้เริ่มต้น ความซับซ้อนสัมพัทธ์ของการดำเนินการทดสอบ จำนวนโค้ดในการทดสอบอาจมากกว่าในงานที่กำลังทดสอบ
การใช้ไลบรารีเพิ่มเติมสำหรับการทดสอบ
ข้อดี: รหัสสะอาดในการทดสอบ ค่อนข้างง่ายในการเขียนการทดสอบ ซอร์สโค้ดของคลาสที่ทดสอบไม่มีการเปลี่ยนแปลง
จุดด้อย: จำเป็นต้องเชื่อมต่อไลบรารีบุคคลที่สามเข้ากับโปรเจ็กต์
พูดตามตรง ฉันชอบตัวเลือกที่สามมากที่สุด ดังนั้นเรามาลองใช้มันกันดีกว่า
กฎของระบบ การค้นหาสั้น ๆ นำฉันไปที่หน้า
http://stefanbirkner.github.io/system-rules/ และเห็นได้ชัดว่านี่คือสิ่งที่ฉันต้องการ
ชุดกฎ JUnit สำหรับการทดสอบโค้ดที่ใช้ java.lang.System
ดังนั้น
เรามาดาวน์โหลดไลบรารี่กันดี กว่า ดาวน์โหลด ไลบรารี
Commons IO ที่จำเป็นสำหรับกฎของระบบ ใน การทำงาน เราเชื่อมต่อไลบรารีทั้งสองเข้ากับโปรเจ็กต์ของเรา (ไฟล์ -> โครงสร้างโปรเจ็กต์ -> ไลบรารี -> + -> Java) และเริ่มแกะสลัก: หลังจากเปิดตัว งานของเราขอให้คุณป้อนหมายเลข N+1 จากคอนโซล โดยที่ตัวเลขแรกจะบอกคุณ กี่เลขจะตามเขาไป ใน System Rules คลาส TextFromStandardInputStream ใช้เพื่อวัตถุประสงค์เหล่านี้ ขั้นแรก เราจำเป็นต้องเพิ่มฟิลด์ประเภทนี้ให้กับคลาสการทดสอบของเราและทำเครื่องหมายด้วยคำอธิบายประกอบ @Rule:
@Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream();
จากนั้น ในวิธีการทดสอบโดยตรงเราจะระบุข้อมูลที่จำเป็น:
systemInMock.provideText("4\n2\n6\n1\n3\n");
อย่างที่คุณเห็น ตัวเลขจะถูกส่งในรูปแบบข้อความและคั่นด้วยสตริงยัติภังค์ "\n" จากนี้ปรากฎว่า N จะเท่ากับ 4 และเราจะหาค่าสูงสุดจากตัวเลข {2, 6, 1, 3} ต่อไป เราต้องสร้างอินสแตนซ์ของคลาสที่กำลังทดสอบและเรียกใช้เมธอด main() โปรแกรมของเราจะอ่านข้อมูลจาก systemInMock ประมวลผลและพิมพ์ผลลัพธ์ สิ่งที่เราต้องทำคืออ่านและเปรียบเทียบกับมาตรฐาน เมื่อต้องการทำเช่นนี้ กฎของระบบจะจัดเตรียมคลาส StandardOutputStreamLog ให้กับเรา เราเพิ่มฟิลด์ประเภทที่ระบุ:
@Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog();
คุณสามารถอ่านข้อมูลที่พิมพ์โดยใช้เมธอด .getLog() ในขณะที่คุณต้องคำนึงถึงการมีอยู่ของอักขระขึ้นบรรทัดใหม่ ตัวเลือกสุดท้ายอาจเป็นดังนี้:
assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); // or assertEquals("{2, 6, 1, 3}, max = 6", "6\r\n", log.getLog());
ระหว่างการทดสอบ เพื่อที่จะ หลีกเลี่ยงการแบ่งชั้นข้อมูล คุณต้องล้างบันทึก
log.clear();
ข้อความทั้งหมดของชั้นเรียนทดสอบของฉัน:
import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.StandardOutputStreamLog; import org.junit.contrib.java.lang.system.TextFromStandardInputStream; import static org.junit.Assert.*; import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.emptyStandardInputStream; public class UtilAppTest { @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Test public void testAddition() throws Exception { systemInMock.provideText("4\n2\n6\n1\n3\n"); UtilApp utilApp = new UtilApp(); utilApp.main(new String[]{}); assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); systemInMock.provideText("5\n-100\n-6\n-15\n-183\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{-100, -6, -15, -183, -1}, max = -1", "-1", log.getLog().trim()); systemInMock.provideText("3\n2\n0\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{2, 0, -1}, max = 2", "2", log.getLog().trim()); } }
เราเปิดตัวและสนุกไปกับมัน
-=!!! สำคัญ!!!=- เนื้อหานี้จัดทำขึ้นเพื่อวัตถุประสงค์ในการให้ข้อมูลเท่านั้น ฉันไม่รับประกันว่าการทดสอบงานบนเซิร์ฟเวอร์จะประสบความสำเร็จหากมีคลาสที่ไม่เกี่ยวข้องในแพ็คเกจพร้อมกับงาน ก่อนที่จะส่งงานสำหรับการตรวจสอบไปยังเซิร์ฟเวอร์ ให้ลบทุกสิ่งที่ไม่เกี่ยวข้องออก: ไฟล์ที่ไม่จำเป็น คลาสที่ไม่จำเป็น โค้ดที่ใส่ความคิดเห็น การสำเร็จการทดสอบที่คุณสร้างไว้ไม่ได้รับประกันว่าการทดสอบบนเซิร์ฟเวอร์จะสำเร็จ ฉันไม่ได้ตั้งใจเคี้ยวเนื้อหาทางทฤษฎี: ทฤษฎีการทดสอบหน่วย คำอธิบายประกอบ JUnit การยืนยัน ฯลฯ เนื้อหาทั้งหมดอยู่ในลิงก์ที่ให้ไว้ในข้อความ บางทีคุณอาจมีวิธีทดสอบงานของคุณเอง ฉันยินดีที่จะพูดคุยกับคุณในความคิดเห็น
GO TO FULL VERSION