Junit: แยกการทดสอบการรวมและการทดสอบหน่วย


126

ฉันได้รับการทดสอบ Junit มาเป็นจำนวนมาก แต่การทดสอบเหล่านี้ (นอกเหนือจากการทดสอบส่วนใหญ่ไม่ได้ผล) เป็นส่วนผสมของการทดสอบหน่วยจริงและการทดสอบการรวม (ต้องใช้ระบบภายนอกฐานข้อมูล ฯลฯ )

ดังนั้นฉันจึงพยายามคิดหาวิธีแยกพวกมันออกจากกันเพื่อที่ฉันจะได้รันการทดสอบหน่วยได้อย่างรวดเร็วและการทดสอบการรวมหลังจากนั้น

ตัวเลือกคือ ..

  1. แยกเป็นไดเรกทอรีแยกต่างหาก

  2. ย้ายไปที่ Junit4 (จาก v3) และใส่คำอธิบายประกอบคลาสเพื่อแยกคลาส

  3. ใช้หลักการตั้งชื่อไฟล์เพื่อบอกว่าคลาสคืออะไรเช่น AdapterATest และ AdapterAIntergrationTest

3 มีปัญหาว่า Eclipse มีตัวเลือก "เรียกใช้การทดสอบทั้งหมดในโครงการ / แพ็คเกจหรือโฟลเดอร์ที่เลือก" ดังนั้นจึงยากมากที่จะเรียกใช้การทดสอบการรวมระบบ

2: เสี่ยงที่นักพัฒนาอาจเริ่มเขียนการทดสอบการรวมในชั้นเรียนทดสอบหน่วยและมันก็ยุ่งเหยิง

1: ดูเหมือนจะเป็นทางออกที่ดีที่สุด แต่ลำไส้ของฉันบอกว่าต้องมีทางออกที่ดีกว่านี้

นั่นคือคำถามของฉันคุณจะแยกการทดสอบการรวมและการทดสอบหน่วยที่เหมาะสมได้อย่างไร


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

คำตอบ:


10

ปัจจุบันฉันใช้ไดเรกทอรีแยกจากกันเนื่องจากนโยบายขององค์กร (และ Junit 3 ดั้งเดิม) แต่ฉันต้องการเปลี่ยนไปใช้คำอธิบายประกอบตอนนี้ฉันใช้ Junit 4

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

ฉันสนใจที่จะทราบว่าโซลูชันอื่น ๆ มีอะไรบ้างนอกเหนือจากคำอธิบายประกอบหรือการแยกชั้นเรียนทางกายภาพ ..


145

คุณสามารถแยกได้อย่างง่ายดายโดยใช้หมวดหมู่ JUnit และ Maven

สิ่งนี้แสดงให้เห็นอย่างสั้น ๆ ด้านล่างโดยการแยกหน่วยและการทดสอบการรวม

กำหนดอินเทอร์เฟซ Marker

ขั้นตอนแรกในการจัดกลุ่มการทดสอบโดยใช้หมวดหมู่คือการสร้างอินเทอร์เฟซเครื่องหมาย

อินเทอร์เฟซนี้จะใช้เพื่อทำเครื่องหมายการทดสอบทั้งหมดที่คุณต้องการเรียกใช้เป็นการทดสอบการรวม

public interface IntegrationTest {}

ทำเครื่องหมายชั้นเรียนทดสอบของคุณ

เพิ่มคำอธิบายประกอบหมวดหมู่ที่ด้านบนสุดของชั้นเรียนทดสอบของคุณ ใช้ชื่ออินเทอร์เฟซใหม่ของคุณ

import org.junit.experimental.categories.Category;
@Category(IntegrationTest.class)
public class ExampleIntegrationTest{
  @Test
  public void longRunningServiceTest() throws Exception {
  }
}

กำหนดค่าการทดสอบหน่วย Maven

ความสวยงามของโซลูชันนี้คือไม่มีอะไรเปลี่ยนแปลงไปจากด้านการทดสอบหน่วยของสิ่งต่างๆ

เราเพียงแค่เพิ่มการกำหนดค่าบางอย่างให้กับปลั๊กอิน maven surefire เพื่อให้ละเว้นการทดสอบการรวมใด ๆ

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.11</version>
  <dependencies>
   <dependency>
     <groupId>org.apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <includes>
      <include>**/*.class</include>
    </includes>
    <excludedGroups>com.test.annotation.type.IntegrationTest</excludedGroups>
  </configuration>
</plugin>

เมื่อคุณทำการทดสอบ mvn clean การทดสอบหน่วยที่ไม่มีเครื่องหมายของคุณเท่านั้นที่จะทำงาน

กำหนดค่าการทดสอบการรวม Maven

อีกครั้งการกำหนดค่าสำหรับสิ่งนี้ง่ายมาก

หากต้องการเรียกใช้เฉพาะการทดสอบการรวมให้ใช้สิ่งนี้:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.11</version>
  <dependencies>
   <dependency>
     <groupId>org.apache.maven.surefire</groupId>
     <artifactId>surefire-junit47</artifactId>
     <version>2.12</version>
   </dependency>
  </dependencies>
  <configuration>
    <groups>com.test.annotation.type.IntegrationTest</groups>
  </configuration>
</plugin>

หากคุณรวมสิ่งนี้ไว้ในโปรไฟล์ด้วย id ITคุณสามารถเรียกใช้เฉพาะการทดสอบอย่างรวดเร็วโดยใช้mvn clean installไฟล์. เพื่อให้ทำงานได้เพียงบูรณาการ / mvn clean install -P ITการทดสอบช้าใช้

แต่ส่วนใหญ่มักจะคุณจะต้องการที่จะเรียกใช้การทดสอบได้อย่างรวดเร็วโดยการเริ่มต้นและทุก-P ITการทดสอบด้วย หากเป็นเช่นนั้นคุณต้องใช้เคล็ดลับ:

<profiles>
    <profile>
        <id>IT</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <excludedGroups>java.io.Serializable</excludedGroups> <!-- An empty element doesn't overwrite, so I'm using an interface here which no one will ever use -->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

java.io.Serializableที่คุณสามารถดูฉันไม่รวมการทดสอบที่มีการกำกับด้วย สิ่งนี้จำเป็นเนื่องจากโปรไฟล์จะสืบทอดการกำหนดค่าเริ่มต้นของปลั๊กอิน Surefire ดังนั้นแม้ว่าคุณจะพูด<excludedGroups/>หรือ<excludedGroups></excludedGroups>ค่าก็ตามcom.test.annotation.type.IntegrationTestนี้ก็ตาม

คุณยังไม่สามารถใช้ noneเนื่องจากต้องเป็นอินเทอร์เฟซบน classpath (Maven จะตรวจสอบสิ่งนี้)

หมายเหตุ:

  • การพึ่งพาsurefire-junit47มีความจำเป็นก็ต่อเมื่อ Maven ไม่เปลี่ยนไปใช้ตัววิ่ง JUnit 4 โดยอัตโนมัติ การใช้groupsหรือexcludedGroupsองค์ประกอบควรเรียกสวิตช์ ดูที่นี่ .
  • โค้ดด้านบนส่วนใหญ่นำมาจากเอกสารสำหรับปลั๊กอิน Maven Failsafe ดูส่วน "การใช้หมวดหมู่ JUnit" ในหน้านี้
  • ในระหว่างการทดสอบของฉันฉันพบว่าสิ่งนี้ใช้ได้แม้กระทั่งเมื่อคุณใช้@RunWith()คำอธิบายประกอบเพื่อเรียกใช้ห้องชุดหรือการทดสอบตามฤดูใบไม้ผลิ

18
ฉันคิดว่ามีข้อผิดพลาดในส่วน pom.xml สุดท้ายของคุณ คุณวางข้อมูลโค้ดเดียวกันกับเฟส "ทดสอบ" มันยังคงไม่รวมการทดสอบการรวมและไม่ผูกมัดกับเฟส maven ใด ๆ
อเล็กซ์

1
อันที่จริงส่วน pom สุดท้ายเป็นข้อผิดพลาดในการคัดลอกและวาง ควรแสดงปลั๊กอิน maven-failafe-plugin
Paulo Merson

2
แล้ว xml ตัวที่สองควรเป็นอย่างไร? : O
Liv

คุณไม่ต้องใช้เคล็ดลับ (เวทมนตร์สุดท้ายที่มี Serializable) หากคุณใช้โปรไฟล์ Maven เริ่มต้น
user831217

นี่ควรเป็นคำตอบที่ได้รับการยอมรับจริง ๆ เพราะนี่เป็นวิธีแก้ปัญหาแทนการถกเถียงทางปรัชญาเกี่ยวกับตำแหน่งที่จะทำการทดสอบต่างๆ
Bwvolleyball

40

เราใช้ปลั๊กอิน Maven Surefire เพื่อเรียกใช้การทดสอบหน่วยและปลั๊กอิน Maven Failsafe เพื่อเรียกใช้การทดสอบการรวมระบบ การทดสอบหน่วยเป็นไปตามหลักการ**/Test*.java **/*Test.java **/*TestCase.javaตั้งชื่อการทดสอบการรวม -**/IT*.java **/*IT.java **/*ITCase.java- ดังนั้นจึงเป็นตัวเลือกของคุณที่สาม

ในสองโครงการเราใช้ TestNG และกำหนดกลุ่มทดสอบที่แตกต่างกันสำหรับการทดสอบการรวม / หน่วย แต่อาจไม่เหมาะสำหรับคุณ


1
+1 สำหรับ maven + surefire + failafe + junit combo ฉันไม่ทราบว่าระบบป้องกันความผิดพลาดจะเรียกใช้ "IT *" โดยอัตโนมัติ หวาน.
PapaFreud

13

ฉันจะย้ายไปที่ Junit4 เพียงเพื่อมี :)

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

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


9

การใช้คำอธิบายประกอบ Spring IfProfileValueทำให้สามารถทำได้โดยไม่ต้องใช้ปลั๊กอิน maven หรือการกำหนดค่าที่จำเป็น

ใส่คำอธิบายประกอบคลาสหรือวิธีการทดสอบการรวมโดยใช้ IfProfileValue

import org.springframework.test.annotation.IfProfileValue;

@IfProfileValue(name="test-groups", value="integration")
public class ExampleIntegrationTest{
    @Test
    public void longRunningServiceTest() throws Exception {
    }
} 

ในการรันโดยใช้การทดสอบหน่วยเท่านั้น:

mvn clean test

ในการรันโดยใช้การทดสอบการรวมและการทดสอบหน่วย:

mvn clean test -Dtest-groups=integration

นอกจากนี้ "เรียกใช้การทดสอบทั้งหมด" ใน IDE จะเรียกใช้เฉพาะการทดสอบหน่วย เพิ่ม-Dtest-groups=integrationอาร์กิวเมนต์ VM เพื่อรันทั้งการรวมและการทดสอบหน่วย


วิธีนี้ดีและเรียบง่าย แต่ปัญหาที่ฉันพบคือโดยค่าเริ่มต้นฉันต้องการเรียกใช้การทดสอบทั้งหมด (รวมถึงการทดสอบการรวม) วิธีนี้เป็นไปไม่ได้ใช่หรือไม่?
csalazar

6

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

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

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

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