CodeGym /Java Blog /무작위의 /JUnit을 사용한 Java 단위 테스트
John Squirrels
레벨 41
San Francisco

JUnit을 사용한 Java 단위 테스트

무작위의 그룹에 게시되었습니다

Java에서 단위 테스트란 무엇입니까?

Java에서 JUnit을 배우기 전에 단위 테스트가 무엇이고 왜 인기가 있는지 간략하게 살펴보겠습니다(이미 알고 있는 경우 'JUnit 테스트를 Java로 작성하려면 어떻게 해야 합니까?'로 건너뛰십시오). Java의 단위 테스트는 대규모 소프트웨어 개발을 훨씬 더 효율적이고 쉽게 만듭니다. 개인과 팀 모두 디버깅 시간을 줄이고 협업 프로세스를 크게 간소화하는 데 도움이 될 수 있습니다. JUnit을 사용한 Java 단위 테스트 - 1

https://junit.org/junit4/

단위 테스트의 기본 아이디어는 다음과 같습니다. 개별 기능의 원자 테스트(단위 테스트라고 함)를 작성하고 테스트 후 천천히 더 많은 기능을 추가하고 이전 기능이 작동하는지 확인합니다. 매우 간단하지만 강력한 아이디어입니다. 이 프로세스가 어떻게 보이는지에 대한 예로 가상 공학용 계산기를 구축하고 있다고 상상해 보십시오. +명백한 산술 연산자( , -, x, ) 외에도 %이 계산기에는 다른 하위 기능이 작동해야 하는 고급 기능이 있습니다. 지수를 계산하려면 계산기가 올바르게 곱할 수 있어야 합니다. 따라서 이 계산기를 구축하고 테스트하기 위한 단위 테스트 접근 방식은 다음과 같습니다.
  • 덧셈 함수를 작성합니다. 신중하게 테스트하고, 변경하고, 작동할 때까지 반복하십시오.
  • 뺄셈, 곱셈, 나눗셈 함수에 대해 동일한 작업을 수행합니다.
  • 이러한 기본 연산자를 사용하여 지수와 같은 고급 연산자 함수를 작성한 다음 해당 함수도 테스트합니다.
이렇게 하면 다른 작은 하위 기능을 기반으로 하는 기능이 자체적으로 제대로 작동할 뿐만 아니라 결함이 있는 하위 기능이 포함되지 않습니다. 예를 들어, 지수 함수를 테스트하고 있는데 문제가 발생하는 경우 곱셈 함수가 이미 광범위하게 테스트되었기 때문에 곱셈 하위 기능에 버그가 없을 수 있음을 알고 있습니다. 이렇게 하면 버그를 찾기 위해 역추적하고 검사해야 하는 총 코드 양이 크게 제거됩니다. 이 간단한 예를 통해 단위 테스트에 대한 사고 프로세스가 어떻게 구성되어 있는지 명확하게 알 수 있기를 바랍니다. 그러나 단위 테스트는 나머지 소프트웨어 개발 프로세스와 어떻게 상호 작용합니까? 함께 작업하고 통신할 수 있어야 하는 훨씬 더 복잡한 기능이 있다면 어떨까요? 단위 테스트는 이러한 복잡한 기능이 함께 제대로 작동하는지 확인하기에는 불충분합니다. 사실 이것은 4단계 소프트웨어 테스팅의 첫 번째 단계일 뿐입니다. 마지막 세 단계는통합 테스팅 , 시스템 테스팅 , 승인 테스팅. 이것들은 아마도 당신이 생각하는 것과 정확히 일치할 것입니다. 하지만 명확히 하겠습니다. 통합 테스트는 위에서 언급한 "복잡한 기능"이 서로 적절하게 상호 작용하는지 확인하기 위해 수행하는 것입니다. (예: 계산기가 "3 + 7 * 4 - 2"를 처리할 수 있는지 확인) 시스템 테스트는 특정 시스템의 전체 설계를 테스트하는 것입니다. 하나의 제품에서 함께 작동하는 복잡한 기능의 여러 시스템이 있는 경우가 많으므로 이러한 시스템을 시스템으로 그룹화하고 개별적으로 테스트합니다. (예를 들어 그래프 계산기를 만들고 있다면 먼저 숫자를 처리하기 위해 산술 '시스템'을 구축하고 의도한 대로 작동할 때까지 테스트한 다음 인출을 처리하기 위해 그래프 '시스템'을 구축하고 테스트합니다. 그것은 산술 시스템에서 구축됩니다). 수락 테스트는 사용자 수준 테스트입니다. 모든 시스템이 동기화되어 사용자가 받아들일 준비가 된 완제품을 생성할 수 있는지 확인합니다(예: 계산기를 테스트하는 사용자). 소프트웨어 개발자는 때때로 프로세스의 이 마지막 단계를 무시할 수 있습니다. 회사에서는 다른 직원이 사용자(베타) 테스트를 별도로 배포하도록 하는 경우가 많기 때문입니다.

Java에서 JUnit 테스트를 어떻게 작성합니까?

이제 단위 테스트의 이점과 제한 사항에 대해 더 명확하게 이해했으므로 몇 가지 코드를 살펴보겠습니다! 우리는 JUnit이라는 인기 있는 Java 테스트 프레임워크를 사용할 것입니다(또 다른 인기 있는 프레임워크는 TestNG로, 원하는 경우 사용할 수도 있습니다. 구문적으로 매우 유사합니다. TestNG는 JUnit에서 영감을 받았습니다). 여기에서 JUnit을 다운로드하고 설치할 수 있습니다 . 이 예제 코드에서는 앞에서 언급한 '과학 계산기' 예제를 계속 진행합니다. 머리를 감싸는 것은 매우 간단하고 테스트 코드는 매우 쉽습니다. 기존 방식은 각 클래스에 대해 별도의 테스트 클래스를 작성하는 것이므로 그렇게 하겠습니다. 이 시점에서 Math.java모든 수학 함수(포함 Math.add)가 포함된 파일이 있고 다음을 작성 중이라고 가정해 보겠습니다.MathTests.java동일한 패키지의 파일입니다. 이제 가져오기 문과 클래스 본문을 설정해 보겠습니다. (가능한 JUnit 인터뷰 질문: JUnit 테스트를 배치할 위치와 소스 파일을 가져와야 하는지 여부를 묻는 메시지가 표시될 수 있습니다. 테스트 클래스를 동일한 패키지에 작성하는 경우 기본 클래스인 경우 테스트 클래스의 소스 파일에 대한 import 문이 필요하지 않습니다. 그렇지 않으면 소스 파일을 가져오고 있는지 확인하십시오!)

import org.junit.jupiter.Test;    //gives us the @Test header
import static org.junit.jupiter.api.Assertions.assertEquals; //less typing :) 

public class MathTests {
	//...
}
첫 번째 import 문은 헤더를 제공합니다 @Test. @Test우리는 JUnit이 이것이 개별적으로 실행할 수 있는 단일 단위 테스트임을 알 수 있도록 모든 테스트 함수 정의 위에 직접 ' '를 작성합니다 . 나중에 이 헤더를 사용하여 특정 단위 테스트를 실행하는 방법을 보여드리겠습니다. 두 번째 import 문은 타이핑을 약간 줄여줍니다. 함수를 테스트하는 데 사용하는 기본 JUnit 함수는 Assert.assertEquals()두 개의 매개변수(실제 값과 예상 값)를 사용하여 동일한지 확인하는 to 입니다. assertEquals(...이 두 번째 가져오기 문을 사용하면 패키지가 속한 패키지를 매번 지정하지 않고 ' '만 입력하면 됩니다 . 이제 2 + 2가 실제로 4인지 확인하는 매우 간단한 테스트 케이스를 작성해 봅시다!

import org.junit.jupiter.Test; // gives us the @Test header
import static org.junit.jupiter.api.Assertions.assertEquals; // less typing :) 


public class MathTests {
	@Test
	public void add_twoPlusTwo_returnsFour(){
	final int expected = 4;
	final int actual = Math.add(2, 2);
	assertEquals(“2+2 is 4”, actual, expected);
	}
}
테스트 함수의 5개 라인과 그 기능을 살펴보겠습니다. 라인 5: 이 @Test헤더는 아래의 함수 정의가 add_twoPlusTwo_returnsFour()실제로 JUnit이 별도로 실행할 수 있는 테스트 함수임을 지정합니다. 6행: 테스트 케이스의 함수 서명입니다. 테스트 케이스는 항상 매우 특이합니다. 2+2=4와 같은 하나의 특정 예만 테스트합니다. [function]_[params]_returns[expected]()테스트 케이스의 이름을 “ ” 형식으로 지정하는 것이 관례입니다. 여기서 [function]는 테스트 중인 함수의 이름, [params]테스트 중인 특정 예제 매개변수, [expected]함수의 예상 반환 값입니다. void전체 함수의 주요 포인트는 실행하는 것이기 때문에 테스트 함수는 거의 항상 ' ' 반환 유형을 갖습니다.assertEquals, 테스트 통과 여부에 관계없이 콘솔에 출력됩니다. 어디에도 반환할 다른 데이터가 필요하지 않습니다. final7행: 의 반환 유형의 ' ' 변수를 선언 Math.add (int)하고 관례에 따라 이름을 'expected'로 지정합니다. 그 가치는 우리가 기대하는 대답입니다(4). final8행: 의 반환 유형의 ' ' 변수를 선언 Math.add (int)하고 관례에 따라 이름을 'actual'로 지정합니다. 그 값은 의 결과입니다 Math.add(2, 2). 라인 9: 골든 라인. 이것은 실제와 예상을 비교하고 동일한 경우에만 테스트를 통과했음을 알려주는 라인입니다. "2+2 is 4"를 전달한 첫 번째 매개변수는 테스트 기능에 대한 설명입니다.

내 함수가 예외를 발생시켜야 하는 경우 어떻게 해야 합니까?

특정 테스트 예제에서 실제 값과 예상 값이 같다고 주장하는 대신 예외를 발생시켜야 하는 경우 JUnit은 헤더에서 이를 명확히 할 수 있는 방법이 있습니다 @Test. 아래의 예를 살펴보겠습니다. Math.java에 함수가 있다고 가정하면 Math.divide입력을 0으로 나눌 수 없도록 해야 합니다. 대신 Math.divide(a, 0)'a' 값을 호출하려고 하면 예외( ArithmeticException.class)가 발생합니다. 헤더에 다음과 같이 지정합니다.

import org.junit.jupiter.Test; // gives us the @Test header
import static org.junit.jupiter.api.Assertions.assertEquals; // less typing :) 


public class MathTests {
	@Test (expectedExceptions = ArithmeticException.class)
	public void divide_byZero_throwsException() throws ArithmeticException{
	Math.divide(1, 0);
	}
}
에 대해 둘 이상의 예외가 있을 수 있습니다 expectedExceptions. 다음과 같이 대괄호와 쉼표를 사용하여 예외 클래스를 나열해야 합니다.

expectedException = {FirstException.class, SecondException.class, … }

Java에서 JUnit 테스트를 어떻게 실행합니까?

IntelliJ에 JUnit을 추가하는 방법: https://stackoverflow.com/questions/19330832/setting-up-junit-with-intellij-idea 일반적으로 테스트를 실행하는 것처럼 프로젝트를 실행할 수 있습니다. 테스트 클래스의 모든 테스트를 실행하면 알파벳순으로 실행됩니다. JUnit 5에서는 태그를 추가하여 테스트에 우선순위를 추가할 수 있습니다 @Order. 예:

@TestMethodOrder(OrderAnnotation.class)
public class Tests {
…
@Test
@Order(2)
public void a_test() { … }

@Test
@Order (1)
public void b_test() { … }
…
}
알파벳순으로 코드에서 a_test()앞에 오더라 도 순서상 1이 2보다 앞에 오므로 여기 보다 먼저 실행됩니다 . 이것이 JUnit의 기초에 대한 전부입니다. 이제 몇 가지 일반적인 JUnit 인터뷰 질문에 답하고 그 과정에서 JUnit에 대해 자세히 알아봅시다! b_test()b_test()a_test()

JUnit 인터뷰 질문(추가 정보)

여기에 가장 인기 있는 JUnit 면접 질문을 모았습니다. 추가할 사항이 있으면 아래 의견에서 자유롭게 추가하십시오. Q: 자동으로 테스트에 실패하도록 테스트 메서드에서 호출할 수 있는 메서드는 무엇입니까? A: fail("오류 설명은 여기!"); Q: Dog 클래스를 테스트하고 있습니다. Dog 개체를 테스트하려면 테스트를 실행하기 전에 개체를 인스턴스화해야 합니다. 따라서 setUp() 함수를 작성하여 Dog를 인스턴스화합니다. 모든 테스트 중에 이 기능을 한 번만 실행하려고 합니다. JUnit이 테스트를 실행하기 전에 setUp()을 실행하는 것을 알 수 있도록 setUp() 함수 서명 바로 위에 무엇을 넣어야 합니까? A: @BeforeClass(JUnit 5의 @BeforeAll) Q:위에서 설명한 setUp() 함수의 함수 서명은 무엇이어야 합니까? A: 공공 정적 무효. @BeforeClass(JUnit 5의 @BeforeAll) 또는 @AfterClass(JUnit 5의 @AfterAll)가 있는 모든 함수는 정적이어야 합니다. Q: Dog 클래스 테스트를 마쳤습니다. 데이터를 정리하고 각 테스트 후 콘솔에 정보를 인쇄하는 void tearDown() 함수를 작성합니다. 모든 단일 테스트 후에 이 기능이 실행되기를 원합니다. JUnit이 각 테스트 실행 후 tearDown() 실행을 알 수 있도록 tearDown() 함수 서명 바로 위에 무엇을 넣어야 합니까? A: @After(JUnit 5의 @AfterEach)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION