JUnit4 fail () ở đây, nhưng pass () ở đâu?


82

Có một fail()phương thức trong thư viện JUnit4. Tôi thích nó, nhưng gặp phải tình trạng thiếu pass()phương pháp không có trong thư viện. Tại sao nó như vậy?

Tôi đã phát hiện ra rằng tôi có thể sử dụng assertTrue(true)thay thế nhưng vẫn có vẻ không hợp lý.

@Test
 public void testSetterForeignWord(){
  try {
   card.setForeignWord("");
   fail();
  } catch (IncorrectArgumentForSetter ex){
  }

 // assertTrue(true);
 }

7
Chỉ cần sử dụng câu lệnh return - trong hầu hết các trường hợp, câu lệnh đó sẽ được chuyển dưới dạng pass ().
topchef 29/10/10

@topchef rằng bình luận đơn lẻ đó đã giáng một nhát búa vào đầu, trong khi mọi người khác tranh luận về việc cái nào được chấp nhận và cái nào không.

Một số hệ thống kiểm tra (perl Test :: Simple) đếm số lần xác nhận vượt qua và không thành công. Tuy nhiên, Junit đếm số phương pháp thử nghiệm đạt và không đạt. Do đó, Junit không có cùng một cách sử dụng cho một passphương thức.
Randall Whitman

Câu trả lời:


63

Miễn là kiểm tra không ném ra một ngoại lệ, nó sẽ vượt qua, trừ khi @Testchú thích của bạn chỉ định một ngoại lệ dự kiến. Tôi cho rằng a pass()có thể ném ra một ngoại lệ đặc biệt mà JUnit luôn hiểu là vượt qua, để làm ngắn mạch thử nghiệm, nhưng điều đó sẽ đi ngược lại thiết kế thông thường của các thử nghiệm (tức là giả sử thành công và chỉ thất bại nếu một khẳng định không thành công) và, nếu mọi người đã ý tưởng rằng nó được ưu tiên sử dụng pass(), nó sẽ làm chậm đáng kể một loạt các bài kiểm tra vượt qua (do chi phí tạo ngoại lệ). Kiểm tra không đạt không phải là tiêu chuẩn, vì vậy sẽ không phải là vấn đề lớn nếu họ có chi phí đó.

Lưu ý rằng ví dụ của bạn có thể được viết lại như thế này:

@Test(expected=IncorrectArgumentForSetter.class)
public void testSetterForeignWord("") throws Exception {
  card.setForeignWord("");
}

Ngoài ra, bạn nên ưu tiên sử dụng các ngoại lệ Java tiêu chuẩn. Của bạn IncorrectArgumentForSettercó lẽ nên là một IllegalArgumentException.


4
Phương thức fail () và các phương thức OwnerX () thực sự chỉ ném ra một AssertionError, điều này khiến phương thức kiểm tra thoát ra không sạch. Đó là lý do tại sao một sự trở lại thành công chỉ ra thành công ...
Steven Schlansker

-1 - phương thức pass () không làm gì cả - nó thoát thử nghiệm ngay lập tức mà không có ngoại lệ. Điều đó có hiệu quả tương đương với câu lệnh trả về trong hầu hết các trường hợp (ngoại trừ trường hợp ngoại lệ dự kiến, hết thời gian chờ, v.v.).
topchef 29/10/10

1
@grigory: Bạn nói đúng rằng một pass()phương pháp không thể không làm gì cả, vì nó có thể xảy ra lỗi sau khi gọi nó. Vì vậy, tôi đã loại bỏ câu đó.
ColinD

Tôi không thể cảm ơn bạn đủ, đã giúp tôi thoát khỏi rất nhiều thất vọng!
N00b Pr0grammer

70

returnBáo cáo cuộc gọi bất cứ lúc nào bài kiểm tra của bạn kết thúc và đã vượt qua.


3
1 phải có được câu trả lời đúng (trong hầu hết trường hợp với ngoại lệ của mong đợi, timeout, vv)
topchef

Có vẻ thực sự là cách đơn giản và hữu dụng nhất để kết thúc một bài kiểm tra.
Benj

7

Tôi nghĩ câu hỏi này cần một câu trả lời cập nhật, vì hầu hết các câu trả lời ở đây đã khá lỗi thời.

Đầu tiên đối với câu hỏi của OP:

Tôi nghĩ rằng nó được chấp nhận khá tốt rằng việc giới thiệu khái niệm "dự kiến ​​excetion" vào JUnit là một động thái tồi, vì ngoại lệ đó có thể được đưa ra ở bất cứ đâu và nó sẽ vượt qua bài kiểm tra. Nó hoạt động nếu bạn ném (và khẳng định trên) các ngoại lệ rất cụ thể cho miền, nhưng tôi chỉ ném những loại ngoại lệ đó khi tôi đang làm việc trên mã cần phải hoàn toàn không tinh khiết, - hầu hết APIS sẽ chỉ đơn giản là ném các ngoại lệ được tích hợp sẵn như IllegalArgumentExceptionhoặc IllegalStateException. Nếu hai lệnh gọi của bạn thực sự có thể tạo ra những ngoại lệ này, thì @ExpectedExceptionchú thích sẽ hiển thị màu xanh cho bài kiểm tra của bạn ngay cả khi nó sai dòng dẫn đến ngoại lệ!

Đối với tình huống này, tôi đã viết một lớp mà tôi chắc rằng nhiều người khác ở đây đã viết, đó là một assertThrowsphương pháp:

public class Exceptions {
    private Exceptions(){}

    public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){
        try{
            actionThatShouldThrow.run();
            fail("expected action to throw " + expectedException.getSimpleName() + " but it did not.");
        }
        catch(Exception e){
            if ( ! expectedException.isInstance(e)) {
                throw e;
            }
        }
    }
}

phương thức này chỉ trả về nếu ngoại lệ được ném ra, cho phép bạn thực hiện thêm các xác nhận / xác minh trong thử nghiệm của mình.

với cú pháp java 8, bài kiểm tra của bạn trông rất đẹp. Dưới đây là một trong những thử nghiệm đơn giản hơn trên mô hình của chúng tôi sử dụng phương pháp:

@Test
public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() {
    //setup
    AxisRange range = new AxisRange(0,100);

    //act
    Runnable act = () -> range.setLowerBound(200);

    //assert
    assertThrows(IllegalArgumentException.class, act);
}

những bài kiểm tra này hơi khó hiểu vì bước "hành động" không thực sự thực hiện bất kỳ hành động nào, nhưng tôi nghĩ ý nghĩa vẫn khá rõ ràng.

cũng có một thư viện nhỏ nhỏ trên maven có tên là catch-exception sử dụng cú pháp kiểu mockito để xác minh rằng các ngoại lệ được ném ra. Nó trông khá đẹp, nhưng tôi không phải là một fan hâm mộ của proxy động. Điều đó nói rằng, có cú pháp rất mượt mà nó vẫn hấp dẫn:

// given: an empty list
List myList = new ArrayList();

// when: we try to get the first element of the list
// then: catch the exception if any is thrown 
catchException(myList).get(1);

// then: we expect an IndexOutOfBoundsException
assert caughtException() instanceof IndexOutOfBoundsException;

Cuối cùng, đối với tình huống mà tôi gặp phải để truy cập chủ đề này, có một cách để bỏ qua các bài kiểm tra nếu một số conidition được đáp ứng.

Hiện tại, tôi đang làm việc để nhận một số DLL được gọi thông qua một thư viện gốc-thư viện java có tên là JNA, nhưng máy chủ xây dựng của chúng tôi ở trong ubuntu. Tôi muốn cố gắng thúc đẩy loại phát triển này bằng các bài kiểm tra JUnit - ngay cả khi chúng khác xa "đơn vị" vào thời điểm này--. Những gì tôi muốn làm là chạy kiểm tra nếu tôi đang sử dụng máy cục bộ, nhưng bỏ qua kiểm tra nếu chúng tôi đang sử dụng ubuntu. JUnit 4 có một điều khoản cho điều này, được gọi là Assume:

@Test
public void when_asking_JNA_to_load_a_dll() throws URISyntaxException {
    //this line will cause the test to be branded as "ignored" when "isCircleCI" 
    //(the machine running ubuntu is running this test) is true.
    Assume.assumeFalse(BootstrappingUtilities.isCircleCI());
    //an ignored test will typically result in some qualifier being put on the results, 
    //but will also not typically prevent a green-ton most platforms. 

    //setup
    URL url = DLLTestFixture.class.getResource("USERDLL.dll");
    String path = url.toURI().getPath();
    path = path.substring(0, path.lastIndexOf("/"));

    //act
    NativeLibrary.addSearchPath("USERDLL", path);
    Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class);

    //assert
    assertThat(dll).isNotNull();
}

Như bạn đã nói, "hành động" không làm bất cứ điều gì cụ thể, vì vậy chúng tôi vẫn không biết chính xác điều gì gây ra ngoại lệ cho dù đó là dòng chúng tôi mong đợi hay không. Trong trường hợp này, ví dụ này khá đơn giản để được kiểm tra và xác minh nhưng hãy tưởng tượng bài kiểm tra của bạn bao gồm phương thức Tiện ích sử dụng các phương thức lồng nhau trước khi trả về kết quả. Vẫn không có cách nào để có được nguồn gốc của các vấn đề trừ khi IDE chỉ ra các trang web ngoại lệ
Farid

4

Tôi cũng đang tìm kiếm passphương pháp cho JUnit để có thể đoản mạch một số thử nghiệm không thể áp dụng trong một số trường hợp (có các thử nghiệm tích hợp, thay vì thử nghiệm đơn vị thuần túy). Vì vậy, quá tệ nó không có ở đó.

May mắn thay, có một cách để bỏ qua kiểm tra có điều kiện, điều này thực sự phù hợp hơn trong trường hợp của tôi bằng cách sử dụng assumeTruephương pháp:

Assume.assumeTrue (isTestApplicable);

Vì vậy, ở đây kiểm tra sẽ chỉ được thực hiện nếu isTestApplicable là true, nếu không kiểm tra sẽ bị bỏ qua.


2

Không cần phương thức vượt qua vì khi không có AssertionFailedException nào được ném ra từ mã thử nghiệm, trường hợp kiểm thử đơn vị sẽ vượt qua.

Phương thức fail () thực sự ném một AssertionFailedException để làm hỏng testCase nếu điều khiển đến thời điểm đó.


Tôi nghĩ đó thực sự là một junit.framework.AssertionFailedError.
Kyle

Những gì về các trường hợp lỗi. nói rằng tôi đang nhận phần tử không hiển thị ngoại lệ từ webdriver. Tôi có nên bắt ngoại lệ và trả về.
sasikumar,

1

Tôi nghĩ rằng câu hỏi này là kết quả của một chút hiểu lầm về quá trình thực hiện thử nghiệm. Trong JUnit (và các công cụ kiểm tra khác), kết quả được tính cho mỗi phương thức, không phải cho mỗi lần gọi xác nhận. Không có một bộ đếm, theo dõi số lượng vượt qua / thất bại assertXđã được thực thi.

JUnit thực hiện từng phương pháp thử nghiệm riêng biệt. Nếu phương thức trả về thành công, thì kiểm tra được đăng ký là "đạt". Nếu một ngoại lệ xảy ra, thì kiểm tra được đăng ký là "không thành công". Trong trường hợp sau, có thể có hai chữ cái con: 1) ngoại lệ khẳng định JUnit, 2) bất kỳ loại ngoại lệ nào khác. Trạng thái sẽ là "không thành công" trong trường hợp đầu tiên và "lỗi" trong trường hợp thứ hai.

Trong Assertlớp, nhiều phương thức tốc ký có sẵn để ném các ngoại lệ khẳng định. Nói cách khác, Assertlà một lớp trừu tượng trên các ngoại lệ của JUnit.

Ví dụ: đây là mã nguồn của assertEqualstrên GitHub :

/**
 * Asserts that two Strings are equal.
 */
static public void assertEquals(String message, String expected, String actual) {
    if (expected == null && actual == null) {
        return;
    }
    if (expected != null && expected.equals(actual)) {
        return;
    }
    String cleanMessage = message == null ? "" : message;
    throw new ComparisonFailure(cleanMessage, expected, actual);
}

Như bạn thấy, trong trường hợp bình đẳng thì không có gì xảy ra, nếu không sẽ bị loại trừ.

Vì thế:

assertEqual("Oh!", "Some string", "Another string!");

chỉ cần ném một ComparisonFailurengoại lệ, ngoại lệ này sẽ được JUnit xử lý và

assertEqual("Oh?", "Same string", "Same string");

Không lam gi cả.

Tóm lại, một cái gì đó giống như pass()sẽ không có ý nghĩa gì cả, bởi vì nó không làm gì cả.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.