จะเขียนแบบทดสอบหน่วยได้อย่างไร?


136

ฉันมีคลาส Java ฉันจะ ทดสอบหน่วยได้อย่างไร


ในกรณีของฉันฉันมีผลรวมเลขฐานสอง ต้องใช้byte[]อาร์เรย์สองอาร์เรย์รวมและส่งคืนอาร์เรย์ไบนารีใหม่


7
คุณสามารถใช้เครื่องมือเช่นjUnitและเขียนกรณีทดสอบ (วิธีการทดสอบ) สำหรับคลาส java ของคุณ จากนั้นเรียกใช้การทดสอบ jUnit เป็นส่วนหนึ่งของกระบวนการสร้าง (ant / maven) การใช้ jUnit นั้นไม่ใช่เรื่องยากเลยส่วนที่ยากจะมาพร้อมกับสถานการณ์การทดสอบต่างๆที่คุณสามารถคิดได้เพื่อให้คุณสามารถจับข้อบกพร่องได้ แต่เนิ่นๆและบ่อยครั้ง
CoolBeans

คำตอบ:


133
  1. กำหนดเอาต์พุตที่คาดหวังและต้องการสำหรับเคสปกติด้วยอินพุตที่ถูกต้อง

  2. ตอนนี้ใช้การทดสอบโดยการประกาศคลาสตั้งชื่ออะไรก็ได้ (โดยปกติจะเป็น TestAddingModule) และเพิ่มเมธอด testAdd เข้าไป (เช่นแบบด้านล่าง):

    • เขียนวิธีการและด้านบนเพิ่มคำอธิบายประกอบ @Test
    • ในวิธีนี้ให้เรียกใช้ผลรวมไบนารีของคุณและassertEquals(expectedVal,calculatedVal).
    • ทดสอบวิธีการของคุณโดยเรียกใช้ (ใน Eclipse คลิกขวาเลือก Run as → JUnit test)

      //for normal addition 
      @Test
      public void testAdd1Plus1() 
      {
          int x  = 1 ; int y = 1;
          assertEquals(2, myClass.add(x,y));
      }
      
  3. ใส่เคสอื่น ๆ ตามต้องการ

    • ทดสอบว่าผลรวมไบนารีของคุณไม่เกิดข้อยกเว้นที่ไม่คาดคิดหากมีจำนวนเต็มล้น
    • ทดสอบว่าวิธีของคุณจัดการอินพุต Null ได้อย่างดี (ตัวอย่างด้านล่าง)

      //if you are using 0 as default for null, make sure your class works in that case.
      @Test
      public void testAdd1Plus1() 
      {
          int y = 1;
          assertEquals(0, myClass.add(null,y));
      }
      

1. จำเป็นต้องมีสัญกรณ์ @Test หรือไม่? 2. ทำไมไม่ทดสอบค่า null ด้วย assertNotNull? 3. ผลการทดสอบหน่วยอยู่ที่ไหน? ผลลัพธ์จะแสดงให้ผู้ใช้ทราบอย่างไร?
user137717

10
ใช่@Testจำเป็นต้องมีสัญกรณ์ สิ่งนี้ทำเพื่อส่งสัญญาณให้นักวิ่งทดสอบหน่วยทราบว่าวิธีนี้แสดงถึงการทดสอบหน่วยและควรดำเนินการ วิธีการที่ไม่มีคำอธิบายประกอบ@Testจะไม่ถูกดำเนินการโดยนักวิ่งทดสอบ
Ali Shah Ahmed

สำหรับการทดสอบครั้งที่สอง - ไม่ควรเพิ่ม a nullเพื่อyให้คุณy?
Adjit

ขอบคุณ! ฉันอยากรู้ว่าทำไมจึงไม่จำเป็นต้องเพิ่มstaticตัวปรับแต่งของวิธีทดสอบ
Liang Zhang

111

ผมให้โพสต์นี้สำหรับทั้งIntelliJและEclipse

คราส:

สำหรับการทดสอบหน่วยสำหรับโครงการของคุณโปรดทำตามขั้นตอนเหล่านี้ (ฉันใช้ Eclipse เพื่อเขียนการทดสอบนี้):

1- คลิกที่ New -> Java Project

สร้างโครงการ

2- เขียนชื่อโครงการของคุณและคลิกที่เสร็จสิ้น

สร้างโครงการ

3- คลิกขวาที่โครงการของคุณ จากนั้นคลิกที่ใหม่ -> คลาส

สร้างชั้นเรียน

4- เขียนชื่อชั้นเรียนของคุณและคลิกที่เสร็จสิ้น

สร้างชั้นเรียน

จากนั้นกรอกชั้นเรียนดังนี้:

public class Math {
    int a, b;
    Math(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int add() {
        return a + b;
    }
}

5- คลิกที่ File -> New -> JUnit Test Case

สร้างการทดสอบ JUnite

6- ตรวจสอบ setUp () และคลิกที่เสร็จสิ้น SetUp () จะเป็นสถานที่ที่คุณเริ่มต้นการทดสอบของคุณ

ตรวจสอบการตั้งค่า ()

7- คลิกที่ตกลง

เพิ่ม JUnit

8- ที่นี่ฉันเพิ่ม 7 และ 10 ดังนั้นฉันคาดว่าคำตอบจะเป็น 17 กรอกชั้นทดสอบของคุณดังนี้:

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MathTest {
    Math math;
    @Before
    public void setUp() throws Exception {
        math = new Math(7, 10);
    }
    @Test
    public void testAdd() {
        Assert.assertEquals(17, math.add());
    }
}

9- เขียนคลิกที่คลาสทดสอบของคุณใน package explorer และคลิกที่ Run as -> JUnit Test

เรียกใช้ JUnit Test

10- นี่คือผลการทดสอบ

ผลการทดสอบ

IntelliJ: โปรดทราบว่าฉันใช้ชุมชน IntelliJ IDEA 2020.1 สำหรับภาพหน้าจอ นอกจากนี้คุณต้องตั้งค่า jre ก่อนขั้นตอนเหล่านี้ ฉันใช้ JDK 11.0.4

1- คลิกขวาที่โฟลเดอร์หลักของโครงการของคุณ -> ใหม่ -> ไดเรกทอรี คุณควรเรียกสิ่งนี้ว่า 'การทดสอบ' ป้อนคำอธิบายภาพที่นี่ 2- คลิกขวาที่โฟลเดอร์ทดสอบและสร้างแพ็คเกจที่เหมาะสม ฉันขอแนะนำให้สร้างชื่อบรรจุภัณฑ์เดียวกันกับคลาสดั้งเดิม จากนั้นคุณคลิกขวาที่ไดเร็กทอรีทดสอบ -> ทำเครื่องหมายไดเร็กทอรีเป็น -> รูทแหล่งทดสอบ ป้อนคำอธิบายภาพที่นี่ 3- ในแพ็คเกจที่ถูกต้องในไดเร็กทอรีทดสอบคุณต้องสร้างคลาส Java (ฉันแนะนำให้ใช้ Test.java) ป้อนคำอธิบายภาพที่นี่ 4- ในคลาสที่สร้างขึ้นพิมพ์ '@Test' จากนั้นในตัวเลือกที่ IntelliJ ให้คุณเลือกเพิ่ม 'JUnitx' ลงใน classpath 5- เขียนวิธีการทดสอบของคุณในชั้นเรียนทดสอบของคุณ ลายเซ็นของวิธีการเป็นดังนี้:ป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่

@Test
public void test<name of original method>(){
...
}

คุณสามารถยืนยันได้ดังนี้:

Assertions.assertTrue(f.flipEquiv(node1_1, node2_1));

นี่คือการนำเข้าที่ฉันเพิ่ม:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

ป้อนคำอธิบายภาพที่นี่

นี่คือการทดสอบที่ฉันเขียน: ป้อนคำอธิบายภาพที่นี่

คุณสามารถตรวจสอบวิธีการของคุณได้ดังนี้:

Assertions.assertEquals(<Expected>,<actual>);
Assertions.assertTrue(<actual>);
...

สำหรับการเรียกใช้การทดสอบหน่วยของคุณให้คลิกขวาที่การทดสอบแล้วคลิกที่เรียกใช้ ป้อนคำอธิบายภาพที่นี่

หากการทดสอบของคุณผ่านผลลัพธ์จะเป็นดังนี้: ป้อนคำอธิบายภาพที่นี่

ฉันหวังว่ามันจะช่วยได้ คุณสามารถมองเห็นโครงสร้างของโครงการใน GitHub https://github.com/m-vahidalizadeh/problem_solving_project


13
รักคำตอบของคุณเป็น "วิธีการ" ที่ดีที่สุด!
alisa

4
ฉันดีใจที่คำตอบของฉันเป็นประโยชน์ ขอบคุณสำหรับความคิดเห็นของคุณ.
โมฮัมหมัด

2
นี่คือสิ่งที่บทเรียนควรมีลักษณะดังนี้ ตัวอย่างที่สะอาดรัดกุม ดีมาก.
Jack Of Blades

1
ขอบคุณมากครับคุณแจ็ค ฉันดีใจที่คุณพบว่ามีประโยชน์
Mohammad

18

นี่เป็นคำถามทั่วไปและมีหลายวิธีที่สามารถตอบได้

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

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

  1. การบวกง่ายๆระหว่างจำนวนบวกสองจำนวน เพิ่มจากนั้นตรวจสอบว่าผลลัพธ์คือสิ่งที่คุณคาดหวัง
  2. การบวกระหว่างจำนวนบวกและจำนวนลบ (ซึ่งส่งคืนผลลัพธ์พร้อมเครื่องหมายของอาร์กิวเมนต์แรก)
  3. การบวกระหว่างจำนวนบวกและจำนวนลบ (ซึ่งส่งคืนผลลัพธ์พร้อมเครื่องหมายของอาร์กิวเมนต์ที่สอง)
  4. การบวกระหว่างจำนวนลบสองจำนวน
  5. การเพิ่มที่ส่งผลให้เกิดการล้น

ในการตรวจสอบผลลัพธ์คุณสามารถใช้วิธีการ assertXXX ต่างๆจากคลาส org.junit.Assert (เพื่อความสะดวกคุณสามารถทำ 'import static org.junit.Assert. *') วิธีการเหล่านี้จะทดสอบเงื่อนไขเฉพาะและล้มเหลวในการทดสอบหากไม่ผ่านการตรวจสอบความถูกต้อง (พร้อมข้อความเฉพาะหรือไม่ก็ได้)

ตัวอย่างคลาส testcase ในกรณีของคุณ (โดยไม่มีการกำหนดเนื้อหาวิธีการ):

import static org.junit.Assert.*;

public class AdditionTests {
    @Test
    public void testSimpleAddition() { ... }


    @Test
    public void testPositiveNegativeAddition() { ... }


    @Test
    public void testNegativePositiveAddition() { ... }


    @Test
    public void testNegativeAddition() { ... }


    @Test
    public void testOverflow() { ... }
}

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


8

เช่นเดียวกับ @CoolBeans กล่าวจะดูที่jUnit นี่คือบทแนะนำสั้น ๆเพื่อช่วยให้คุณเริ่มต้นใช้งาน jUnit 4.x

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


6

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

  • การทดสอบ (ทุกชนิดทุกประเภท) เปรียบเทียบพฤติกรรมจริงของบางสิ่ง (ระบบภายใต้การทดสอบมทส.) กับพฤติกรรมที่คาดหวัง

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

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

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

  • แต่คุณต้องการข้อกำหนดนั้นเมื่อคุณตั้งค่าที่จะเขียนโค้ดนั้น ดังนั้นส่วนหนึ่งของการทดสอบที่แท้จริงจะเริ่มขึ้นก่อนที่คุณจะเขียนมทส. แม้แต่บรรทัดเดียว เทคนิคการทดสอบของ Test Driven Development (TDD) นำความคิดดังกล่าวไปสู่จุดสูงสุดและคุณได้สร้างรหัสทดสอบหน่วยก่อนที่คุณจะเขียนโค้ดที่จะทดสอบ

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

  • เทคนิคที่มีประโยชน์สำหรับการแสดงสเปคเป็นยืนยันคือการเขียนโปรแกรมโดยการทำสัญญา คุณสมบัติเหล่านี้ในแง่ของการpostconditions Postcondition คือการยืนยันเกี่ยวกับสถานะของ SUT ที่เปิดเผยต่อสาธารณะหลังจากส่งคืนจากวิธีการหรือตัวสร้าง บางวิธีมีเงื่อนไขภายหลังที่เป็นค่าคงที่ซึ่งเป็นเพรดิเคตที่เป็นจริงก่อนและหลังการดำเนินการของเมธอด ชั้นนอกจากนี้ยังสามารถบอกว่าจะมีค่าคงที่ซึ่งเป็น postconditions ของทุกคอนสตรัคและวิธีการของการเรียนและด้วยเหตุนี้ควรเสมอจะเป็นจริง เงื่อนไขภายหลัง (และค่าคงที่) จะแสดงเฉพาะในรูปของสถานะที่มองเห็นการประชาสัมพันธ์เท่านั้น: publicและprotectedฟิลด์ค่าที่ส่งคืนโดยส่งคืนโดยpublicและprotectedวิธีการ (เช่น getters) และสถานะของวัตถุที่เปิดเผยต่อสาธารณะ (โดยการอ้างอิง) ไปยังวิธีการ


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

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