it-swarm-vi.tech

Móc thực thi Before và After Suite trong jUnit 4.x

Tôi đang cố gắng thiết lập trước và thiết lập cho một loạt các thử nghiệm tích hợp, sử dụng jUnit 4.4 để thực hiện các thử nghiệm. Các giọt nước mắt cần phải được chạy đáng tin cậy. Tôi đang gặp vấn đề khác với TestNG, vì vậy tôi đang tìm cách chuyển trở lại jUnit. Những hook nào có sẵn để thực hiện trước khi bất kỳ thử nghiệm nào được chạy và sau khi tất cả các thử nghiệm đã hoàn thành?

Lưu ý: chúng tôi đang sử dụng maven 2 cho bản dựng của chúng tôi. Tôi đã thử sử dụng maven's pre- & post-integration-test các pha, nhưng, nếu thử nghiệm thất bại, maven dừng lại và không chạy post-integration-test, đó là không giúp đỡ.

81
sblundy

Có, có thể chạy các phương thức thiết lập và phá bỏ một cách đáng tin cậy trước và sau bất kỳ thử nghiệm nào trong bộ kiểm tra. Hãy để tôi chứng minh bằng mã:

package com.test;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({Test1.class, Test2.class})
public class TestSuite {

    @BeforeClass
    public static void setUp() {
        System.out.println("setting up");
    }

    @AfterClass
    public static void tearDown() {
        System.out.println("tearing down");
    }

}

Vì vậy, lớp Test1 của bạn sẽ trông giống như:

package com.test;

import org.junit.Test;


public class Test1 {
    @Test
    public void test1() {
        System.out.println("test1");
    }

}

... Và bạn có thể tưởng tượng rằng Test2 trông tương tự. Nếu bạn đã chạy TestSuite, bạn sẽ nhận được:

setting up
test1
test2
tearing down

Vì vậy, bạn có thể thấy rằng thiết lập/xé xuống chỉ chạy trước và sau tất cả các thử nghiệm, tương ứng.

Lưu ý: điều này chỉ hoạt động nếu bạn đang chạy bộ thử nghiệm và không chạy Test1 và Test2 dưới dạng các thử nghiệm JUnit riêng lẻ. Bạn đã đề cập đến việc bạn đang sử dụng maven và plugin maven Surefire thích chạy thử nghiệm riêng lẻ và không phải là một phần của bộ ứng dụng. Trong trường hợp này, tôi khuyên bạn nên tạo một siêu lớp mà mỗi lớp kiểm tra mở rộng. Siêu lớp sau đó chứa các phương thức @B BeforeClass và @AfterClass được chú thích. Mặc dù không hoàn toàn sạch như phương pháp trên, tôi nghĩ nó sẽ hiệu quả với bạn.

Đối với sự cố với các thử nghiệm thất bại, bạn có thể đặt maven.test.error.ignore để quá trình xây dựng tiếp tục trên các thử nghiệm thất bại. Điều này không được khuyến khích như là một thực hành liên tục, nhưng nó sẽ giúp bạn hoạt động cho đến khi tất cả các bài kiểm tra của bạn vượt qua. Để biết thêm chi tiết, xem tài liệu maven Surefire .

111
Julie

Một đồng nghiệp của tôi đã đề xuất như sau: bạn có thể sử dụng RunListener tùy chỉnh và triển khai phương thức testRunFinished (): http://junit.sourceforge.net/javadoc/org/junit/runner/notification/RunListener.html# testRunFinished (org.junit.runner.Result)

Để đăng ký RunListener, chỉ cần định cấu hình plugin Surefire như sau: http://maven.Apache.org/surefire/maven-surefire-plugin/examples/junit.html phần "Sử dụng trình nghe và phóng viên tùy chỉnh"

Cấu hình này cũng nên được chọn bởi plugin failafe. Giải pháp này rất tuyệt vì bạn không phải chỉ định Suites, các lớp kiểm tra tra cứu hoặc bất kỳ nội dung nào trong số này - nó cho phép Maven thực hiện phép thuật của mình, chờ cho tất cả các thử nghiệm kết thúc.

32
Martin Vysny
11
Tobogganski

Sử dụng các chú thích, bạn có thể làm một cái gì đó như thế này:

import org.junit.*;
import static org.junit.Assert.*;
import Java.util.*;

class SomethingUnitTest {
    @BeforeClass
    public static void runBeforeClass()
    {

    }

    @AfterClass
    public static void runAfterClass()
    {  

    }

    @Before  
    public void setUp()
    {

    }

    @After
    public void tearDown()
    {

    }

    @Test
    public void testSomethingOrOther()
    {

    }

}
7
Jroc

Đây, chúng tôi

  • nâng cấp lên JUnit 4.5,
  • đã viết các chú thích để gắn thẻ cho mỗi lớp kiểm tra hoặc phương thức cần một dịch vụ làm việc,
  • đã viết các trình xử lý cho mỗi chú thích có chứa các phương thức tĩnh để thực hiện cài đặt và phân tách dịch vụ,
  • đã mở rộng Trình chạy thông thường để định vị các chú thích trong các bài kiểm tra, thêm các phương thức xử lý tĩnh vào chuỗi thực hiện kiểm tra tại các điểm thích hợp.
3
carym

Với điều kiện là tất cả các bài kiểm tra của bạn có thể mở rộng một lớp "kỹ thuật" và nằm trong cùng một gói, bạn có thể thực hiện một mẹo nhỏ:

public class AbstractTest {
  private static int nbTests = listClassesIn(<package>).size();
  private static int curTest = 0;

  @BeforeClass
  public static void incCurTest() { curTest++; }

  @AfterClass
  public static void closeTestSuite() {
      if (curTest == nbTests) { /*cleaning*/ }             
  }
}

public class Test1 extends AbstractTest {
   @Test
   public void check() {}
}
public class Test2 extends AbstractTest {
   @Test
   public void check() {}
}

Xin lưu ý rằng giải pháp này có rất nhiều nhược điểm:

  • phải thực hiện tất cả các thử nghiệm của gói
  • phải phân lớp một lớp "techincal"
  • bạn không thể sử dụng @B BeforeClass và @AfterClass bên trong các lớp con
  • nếu bạn chỉ thực hiện một thử nghiệm trong gói, việc dọn dẹp sẽ không được thực hiện
  • ...

Để biết thông tin: listClassIn () => Làm thế nào để bạn tìm thấy tất cả các lớp con của một lớp nhất định trong Java?

2
christophe blin

Đối với "Lưu ý: chúng tôi đang sử dụng maven 2 cho bản dựng của mình. Tôi đã thử sử dụng các giai đoạn thử nghiệm trước & sau tích hợp của maven, nhưng, nếu thử nghiệm thất bại, maven dừng lại và không chạy thử nghiệm sau tích hợp , không có ích gì. "

thay vào đó, bạn có thể thử plugin failafe, tôi nghĩ rằng nó có tiện ích để đảm bảo dọn dẹp xảy ra bất kể trạng thái thiết lập hay giai đoạn trung gian

2
Binod Pant

Nếu bạn không muốn tạo một bộ và phải liệt kê tất cả các lớp kiểm tra của mình, bạn có thể sử dụng phản xạ để tìm số lượng các lớp kiểm tra một cách linh hoạt và đếm ngược trong một lớp cơ sở @AfterClass để thực hiện việc ripDown chỉ một lần:

public class BaseTestClass
{
    private static int testClassToRun = 0;

    // Counting the classes to run so that we can do the tear down only once
    static {
        try {
            Field field = ClassLoader.class.getDeclaredField("classes");
            field.setAccessible(true);

            @SuppressWarnings({ "unchecked", "rawtypes" })
            Vector<Class> classes = (Vector<Class>) field.get(BlockJUnit4ClassRunner.class.getClassLoader());
            for (Class<?> clazz : classes) {
                if (clazz.getName().endsWith("Test")) {
                    testClassToRun++;
                }
            }
        } catch (Exception ignore) {
        }
    }

    // Setup that needs to be done only once
    static {
        // one time set up
    }

    @AfterClass
    public static void baseTearDown() throws Exception
    {
        if (--testClassToRun == 0) {
            // one time clean up
        }
    }
}

Nếu bạn thích sử dụng @B BeforeClass thay vì các khối tĩnh, bạn cũng có thể sử dụng cờ boolean để thực hiện đếm phản xạ và chỉ thiết lập thử nghiệm một lần trong lần gọi đầu tiên. Hy vọng điều này sẽ giúp được ai đó, tôi đã mất một buổi chiều để tìm ra cách tốt hơn là liệt kê tất cả các lớp trong một bộ.

Bây giờ tất cả những gì bạn cần làm là mở rộng lớp này cho tất cả các lớp kiểm tra của bạn. Chúng tôi đã có một lớp cơ sở để cung cấp một số nội dung phổ biến cho tất cả các bài kiểm tra của chúng tôi vì vậy đây là giải pháp tốt nhất cho chúng tôi.

Cảm hứng đến từ đây SO câu trả lời https://stackoverflow.com/a/37488620/5930242

Nếu bạn không muốn mở rộng lớp này ở mọi nơi, câu trả lời cuối cùng SO có thể làm những gì bạn muốn.

0
FredBoutin

Vì maven-Surefire-plugin không chạy lớp Suite trước nhưng xử lý các lớp bộ và kiểm tra giống nhau, vì vậy chúng tôi có thể định cấu hình plugin như dưới đây để chỉ bật các lớp bộ và vô hiệu hóa tất cả các bài kiểm tra. Suite sẽ chạy tất cả các bài kiểm tra.

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.5</version>
            <configuration>
                <includes>
                    <include>**/*Suite.Java</include>
                </includes>
                <excludes>
                    <exclude>**/*Test.Java</exclude>
                    <exclude>**/*Tests.Java</exclude>
                </excludes>
            </configuration>
        </plugin>
0
Anurag Sharma

Cách duy nhất tôi nghĩ sau đó để có được chức năng bạn muốn là làm một cái gì đó như

import junit.framework.Test;  
import junit.framework.TestResult;  
import junit.framework.TestSuite;  

public class AllTests {  
    public static Test suite() {  
        TestSuite suite = new TestSuite("TestEverything");  
        //$JUnit-BEGIN$  
        suite.addTestSuite(TestOne.class);  
        suite.addTestSuite(TestTwo.class);  
        suite.addTestSuite(TestThree.class);  
        //$JUnit-END$  
     }  

     public static void main(String[] args)  
     {  
        AllTests test = new AllTests();  
        Test testCase = test.suite();  
        TestResult result = new TestResult();  
        setUp();  
        testCase.run(result);  
        tearDown();  
     }  
     public void setUp() {}  
     public void tearDown() {}  
} 

Tôi sử dụng một cái gì đó như thế này trong Eclipse, vì vậy tôi không chắc nó di động như thế nào ngoài môi trường đó

0
Jroc

Theo như tôi biết thì không có cơ chế nào để thực hiện điều này trong JUnit, tuy nhiên bạn có thể thử phân lớp Suite và ghi đè phương thức run () bằng một phiên bản cung cấp các hook.

0
user15299