문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판 이전 판 다음 판 | 이전 판 | ||
wiki:java:junit:junit_a_cook_s_tour [2020/09/01 16:07] dhan |
wiki:java:junit:junit_a_cook_s_tour [2023/01/13 18:44] (현재) |
||
---|---|---|---|
줄 1: | 줄 1: | ||
====== JUnit A Cook's Tour ====== | ====== JUnit A Cook's Tour ====== | ||
- | |||
참고 :이 기사는 JUnit 3.8.x를 기반으로 합니다. | 참고 :이 기사는 JUnit 3.8.x를 기반으로 합니다. | ||
줄 239: | 줄 238: | ||
테스트가 아무리 실패하더라도 다음 테스트를 실행하려고 합니다. | 테스트가 아무리 실패하더라도 다음 테스트를 실행하려고 합니다. | ||
| | ||
- | JUnit은 실패와 오류를 구분합니다. | + | JUnit는 실패와 오류를 구분합니다. |
실패 가능성이 예상되고 assertions로 확인됩니다. | 실패 가능성이 예상되고 assertions로 확인됩니다. | ||
오류는 ArrayIndexOutOfBoundsException과 같은 예상치 못한 문제입니다. | 오류는 ArrayIndexOutOfBoundsException과 같은 예상치 못한 문제입니다. | ||
줄 267: | 줄 266: | ||
| | ||
AssertionFailedError는 TestCase에서 제공하는 assert 메서드에 의해 트리거 됩니다. | AssertionFailedError는 TestCase에서 제공하는 assert 메서드에 의해 트리거 됩니다. | ||
- | JUnit은 다양한 목적을 위해 일련의 assert 메서드를 제공합니다. | + | JUnit는 다양한 목적을 위해 일련의 assert 메서드를 제공합니다. |
다음은 가장 간단한 것입니다. | 다음은 가장 간단한 것입니다. | ||
| | ||
줄 332: | 줄 331: | ||
</ | </ | ||
| | ||
- | JUnit은 TestResult의 다양한 구현과 함께 제공됩니다. | + | JUnit는 TestResult의 다양한 구현과 함께 제공됩니다. |
기본 구현은 실패 및 오류 수를 계산하고 결과를 수집합니다. | 기본 구현은 실패 및 오류 수를 계산하고 결과를 수집합니다. | ||
TextTestResult는 결과를 수집하여 텍스트 형식으로 표시합니다. | TextTestResult는 결과를 수집하여 텍스트 형식으로 표시합니다. | ||
줄 402: | 줄 401: | ||
우리의 경우 우리는 인프라 프레임워크를 다루고 있으므로 reflection 모자를 쓰는 것이 좋습니다. | 우리의 경우 우리는 인프라 프레임워크를 다루고 있으므로 reflection 모자를 쓰는 것이 좋습니다. | ||
| | ||
- | JUnit은 클라이언트에게 pluggable Selector를 사용하거나 위에 표시된 대로 익명 adapter class를 구현할 수 있는 옵션을 제공합니다. | + | JUnit는 클라이언트에게 pluggable Selector를 사용하거나 위에 표시된 대로 익명 adapter class를 구현할 수 있는 옵션을 제공합니다. |
이를 위해 runTest 메서드의 기본 구현으로 pluggable Selector를 제공합니다. | 이를 위해 runTest 메서드의 기본 구현으로 pluggable Selector를 제공합니다. | ||
이 경우 테스트 케이스의 이름은 테스트 방법의 이름과 일치해야합니다. | 이 경우 테스트 케이스의 이름은 테스트 방법의 이름과 일치해야합니다. | ||
줄 434: | 줄 433: | ||
다음은 Adapter 및 pluggable selector가 추가된 다음 디자인 스냅샷입니다. | 다음은 Adapter 및 pluggable selector가 추가된 다음 디자인 스냅샷입니다. | ||
| | ||
- | {{: | + | {{: |
| | ||
- | 3.5 하나 또는 여러 개에 신경 쓰지 마십시오 | + | 3.5 Don’t care about one or many - TestSuite |
- | 시스템 상태에 대한 확신을 얻으려면 많은 테스트를 실행해야합니다. | + | 시스템 상태에 대한 확신을 얻으려면 많은 테스트를 실행해야 합니다. |
- | 지금까지 JUnit은 단일 테스트 케이스를 실행하고 테스트 결과에 결과를 보고 할 수 있습니다. | + | 지금까지 JUnit는 단일 테스트 케이스를 실행하고 테스트 결과에 결과를 보고 할 수 있습니다. |
다음 과제는 다양한 테스트를 실행할 수 있도록 확장하는 것입니다. | 다음 과제는 다양한 테스트를 실행할 수 있도록 확장하는 것입니다. | ||
이 문제는 테스트 호출자가 하나 또는 여러 테스트 케이스를 실행하는지에 대해 신경 쓸 필요가 없을 때 쉽게 해결할 수 있습니다. | 이 문제는 테스트 호출자가 하나 또는 여러 테스트 케이스를 실행하는지에 대해 신경 쓸 필요가 없을 때 쉽게 해결할 수 있습니다. | ||
이러한 상황에서 가장 많이 사용되는 패턴은 Composite입니다. | 이러한 상황에서 가장 많이 사용되는 패턴은 Composite입니다. | ||
- | " | + | " |
- | Composite를 사용하면 클라이언트가 개별 객체와 객체 구성을 균일하게 처리 할 수 있습니다." | + | |
부분 전체 계층 구조에 대한 요점은 여기서 중요합니다. | 부분 전체 계층 구조에 대한 요점은 여기서 중요합니다. | ||
| | ||
- | | + | |
| | ||
Composite는 다음 참가자를 소개합니다. | Composite는 다음 참가자를 소개합니다. | ||
- | | + | |
- | | + | |
- | Leaf : 컴포넌트 | + | Leaf : Component |
| | ||
이 패턴은 단일 및 복합 객체에 대한 공통 인터페이스를 정의하는 추상 클래스를 도입하도록 알려줍니다. | 이 패턴은 단일 및 복합 객체에 대한 공통 인터페이스를 정의하는 추상 클래스를 도입하도록 알려줍니다. | ||
클래스의 주요 목적은 인터페이스를 정의하는 것입니다. | 클래스의 주요 목적은 인터페이스를 정의하는 것입니다. | ||
- | Java에서 Composite를 적용 할 때 우리는 추상 클래스가 아닌 인터페이스를 정의하는 것을 선호합니다. | + | Java에서 Composite를 적용할 때 우리는 추상 클래스가 아닌 인터페이스를 정의하는 것을 선호합니다. |
- | 인터페이스를 사용하면 테스트를 위해 JUnit을 특정 기본 클래스로 커밋하지 않아도됩니다. | + | 인터페이스를 사용하면 테스트를 위해 JUnit를 특정 기본 클래스로 커밋하지 않아도 됩니다. |
- | 필요한 것은 테스트가이 인터페이스를 준수하는 것입니다. | + | 필요한 것은 테스트가 이 인터페이스를 준수하는 것입니다. |
- | 따라서 패턴 설명을 조정하고 테스트 인터페이스를 | + | 따라서 패턴 설명을 조정하고 테스트 인터페이스를 |
+ | | ||
<code java> | <code java> | ||
- | public interface Test { | + | public interface Test |
- | public abstract void run (TestResult result); | + | { |
+ | public abstract void run(TestResult result); | ||
} | } | ||
</ | </ | ||
- | TestCase는 Composite의 Leaf에 해당하며 위에서 본 것처럼이 인터페이스를 구현합니다. | + | |
- | 다음으로 | + | |
+ | 다음으로 | ||
클래스 이름을 TestSuite로 지정합니다. | 클래스 이름을 TestSuite로 지정합니다. | ||
- | TestSuite는 | + | TestSuite는 |
+ | |||
<code java> | <code java> | ||
- | 공용 클래스 | + | public class TestSuite |
private Vector fTests = new Vector (); | private Vector fTests = new Vector (); | ||
} | } | ||
</ | </ | ||
- | run () 메서드는 자식에게 위임합니다. | + | run() 메서드는 자식에게 위임합니다. |
<code java> | <code java> | ||
- | public void run (TestResult result) { | + | public void run(TestResult result) |
+ | { | ||
for (Enumeration e = fTests.elements (); e.hasMoreElements ();) { | for (Enumeration e = fTests.elements (); e.hasMoreElements ();) { | ||
- | Test test = (Test) e.nextElement (); | + | Test test = (Test)e.nextElement (); |
- | test.run (결과); | + | test.run (result); |
} | } | ||
} | } | ||
</ | </ | ||
- | {{: | + | {{: |
- | 마지막으로 클라이언트는 테스트를 | + | 마지막으로 클라이언트는 테스트를 |
<code java> | <code java> | ||
- | public void addTest (테스트 테스트) { | + | public void addTest (Test test) |
+ | { | ||
fTests.addElement (test); | fTests.addElement (test); | ||
} | } | ||
</ | </ | ||
+ | | ||
위의 모든 코드가 테스트 인터페이스에만 의존하는 방식에 유의하십시오. | 위의 모든 코드가 테스트 인터페이스에만 의존하는 방식에 유의하십시오. | ||
- | TestCase와 TestSuite는 모두 Test 인터페이스를 따르기 때문에 | + | TestCase와 TestSuite는 모두 Test 인터페이스를 따르기 때문에 |
- | 모든 개발자는 자신 | + | 모든 개발자는 자신 의 TestSuite를 만들 수 있습니다. |
이러한 제품군으로 구성된 TestSuite를 생성하여 모두 실행할 수 있습니다. | 이러한 제품군으로 구성된 TestSuite를 생성하여 모두 실행할 수 있습니다. | ||
다음은 TestSuite를 만드는 예입니다. | 다음은 TestSuite를 만드는 예입니다. | ||
+ | | ||
<code java> | <code java> | ||
public static Test suite() | public static Test suite() | ||
{ | { | ||
- | TestSuite | + | TestSuite |
- | suite.addTest (new MoneyTest ( " | + | suite.addTest(new MoneyTest ( " |
- | suite.addTest (new MoneyTest ( " | + | suite.addTest(new MoneyTest ( " |
} | } | ||
</ | </ | ||
- | + | | |
- | 이것은 잘 작동하지만 모든 테스트를 스위트에 수동으로 추가해야합니다. | + | 이것은 잘 작동하지만 모든 테스트를 스위트에 수동으로 추가해야 합니다. |
- | JUnit의 얼리 어답터들은 이것이 어리 석다고 말했습니다. | + | JUnit의 얼리 어답터들은 이것이 어리석다고 말했습니다. |
- | 새로운 테스트 케이스를 작성할 때마다이를 static suite () 메서드에 추가해야합니다. | + | 새로운 테스트 케이스를 작성할 때마다 이를 static suite() 메서드에 추가해야합니다. |
그렇지 않으면 실행되지 않습니다. | 그렇지 않으면 실행되지 않습니다. | ||
테스트 케이스 클래스를 인수로 취하는 편리한 생성자를 TestSuite에 추가했습니다. | 테스트 케이스 클래스를 인수로 취하는 편리한 생성자를 TestSuite에 추가했습니다. | ||
- | 그 목적은 테스트 메서드를 추출하고이를 포함하는 제품군을 만드는 것입니다. | + | 그 목적은 테스트 메서드를 추출하고 이를 포함하는 제품군을 만드는 것입니다. |
- | 테스트 메서드는 접두사 " | + | 테스트 메서드는 접두사 " |
- | 편의 생성자는이 규칙을 사용하여 테스트 방법을 찾기 위해 | + | 편의 생성자는 이 규칙을 사용하여 테스트 방법을 찾기 위해 |
이 생성자를 사용하면 위의 코드가 다음과 같이 단순화됩니다. | 이 생성자를 사용하면 위의 코드가 다음과 같이 단순화됩니다. | ||
줄 525: | 줄 529: | ||
} | } | ||
</ | </ | ||
- | | + | |
+ | |||
3.6 요약 | 3.6 요약 | ||
JUnit A Cook's Tour는 끝이 났습니다. | JUnit A Cook's Tour는 끝이 났습니다. | ||
줄 535: | 줄 539: | ||
프레임워크의 추상화 중심인 TestCase가 4가지의 디자인 패턴과 어떻게 관련되어 있는지 확인하십시오 | 프레임워크의 추상화 중심인 TestCase가 4가지의 디자인 패턴과 어떻게 관련되어 있는지 확인하십시오 | ||
성숙한 객체 디자인의 그림은 이와 동일한 " | 성숙한 객체 디자인의 그림은 이와 동일한 " | ||
- | 디자인의 스타는 지원하는 플레이어와 풍부한 관계를 | + | 디자인의 스타는 지원하는 플레이어와 풍부한 관계를 |
| | ||
다음은 JUnit의 모든 패턴을 보는 또 다른 방법입니다. | 다음은 JUnit의 모든 패턴을 보는 또 다른 방법입니다. | ||
이 스토리보드에서는 각 패턴의 효과에 대한 추상적인 표현을 차례로 볼 수 있습니다. | 이 스토리보드에서는 각 패턴의 효과에 대한 추상적인 표현을 차례로 볼 수 있습니다. | ||
따라서 Command 패턴은 TestCase 클래스를 만들고 Templage Method 패턴은 run 메서드를 만드는 식입니다. | 따라서 Command 패턴은 TestCase 클래스를 만들고 Templage Method 패턴은 run 메서드를 만드는 식입니다. | ||
- | (스토리보드의 표기법은 모든 텍스트가 삭제된 그림 6의 표기법 입니다.) | + | (스토리보드의 표기법은 모든 텍스트가 삭제된 그림 6의 표기법입니다.) |
{{: | {{: | ||
| | ||
- | 스토리 보드에서 주목해야 할 점은 Composite를 적용 할 때 그림의 복잡성이 어떻게 점프하는지 입니다. | + | 스토리보드에서 주목해야 할 점은 Composite를 적용할 때 그림의 복잡성이 어떻게 점프하는지입니다. |
- | 이것은 Composite가 강력한 패턴이지만 " | + | 이것은 Composite가 강력한 패턴이지만 " |
따라서 주의해서 사용해야 합니다. | 따라서 주의해서 사용해야 합니다. | ||
줄 554: | 줄 558: | ||
우리는 프레임워크를 개발할 때와 다른 사람들에게 설명하려고 할 때 | 우리는 프레임워크를 개발할 때와 다른 사람들에게 설명하려고 할 때 | ||
패턴 측면에서 디자인을 논의하는 것이 매우 중요하다는 것을 알았습니다. | 패턴 측면에서 디자인을 논의하는 것이 매우 중요하다는 것을 알았습니다. | ||
- | 이제 패턴이 있는 프레임 워크를 설명하는 것이 효과적인지 판단할 수 있는 완벽한 위치에 있습니다. | + | 이제 패턴이 있는 프레임워크를 설명하는 것이 효과적인지 판단할 수 있는 완벽한 위치에 있습니다. |
위의 설명이 마음에 들면 자신의 시스템에 동일한 스타일의 프레젠테이션을 시도해 보십시오. | 위의 설명이 마음에 들면 자신의 시스템에 동일한 스타일의 프레젠테이션을 시도해 보십시오. | ||
Pattern density | Pattern density | ||
- | JUnit의 핵심 추상화 인 TestCase 주변에는 높은 패턴 " | + | JUnit의 핵심 추상화인 TestCase 주변에는 높은 패턴 " |
패턴 밀도가 높은 디자인은 사용하기 쉽지만 변경하기가 더 어렵습니다. | 패턴 밀도가 높은 디자인은 사용하기 쉽지만 변경하기가 더 어렵습니다. | ||
우리는 키 추상화 주변의 높은 패턴 밀도가 성숙한 프레임 워크에서 일반적이라는 것을 발견했습니다. | 우리는 키 추상화 주변의 높은 패턴 밀도가 성숙한 프레임 워크에서 일반적이라는 것을 발견했습니다. | ||
- | 미성숙 한 프레임워크는 그 반대입니다. | + | 미성숙한 프레임워크는 그 반대입니다. |
- | 패턴 밀도가 낮아야합니다. | + | 패턴 밀도가 낮아야 합니다. |
- | 실제로 해결하고있는 문제를 발견하면 솔루션을 " | + | 실제로 해결하고 있는 문제를 발견하면 솔루션을 " |
| | ||
- | Eat your own dog food | + | Eat your own dog food (내부에서 사용) |
기본 단위 테스트 기능을 구현하자마자 직접 적용했습니다. | 기본 단위 테스트 기능을 구현하자마자 직접 적용했습니다. | ||
TestTest는 프레임워크가 오류, 성공 및 실패에 대한 올바른 결과를 보고하는지 확인합니다. | TestTest는 프레임워크가 오류, 성공 및 실패에 대한 올바른 결과를 보고하는지 확인합니다. | ||
줄 573: | 줄 577: | ||
Intersection, | Intersection, | ||
프레임워크 개발에는 가능한 모든 기능을 포함하려는 유혹이 있습니다. | 프레임워크 개발에는 가능한 모든 기능을 포함하려는 유혹이 있습니다. | ||
- | 결국 프레임 워크를 가능한 한 가치있게 만들고 싶습니다. | + | 결국 프레임워크를 가능한 한 가치 있게 만들고 싶습니다. |
- | 그러나 이에 대응하는 힘이 있습니다. 개발자는 프레임 워크를 사용하기로 | + | 그러나 이에 대응하는 힘이 있습니다. 개발자는 프레임워크를 사용하기로 해야 합니다. |
- | 프레임 워크에있는 기능이 적을수록 배우기가 더 쉬울수록 개발자가이를 사용할 가능성이 | + | 프레임워크에 있는 기능이 적을수록 배우기가 더 쉬울수록 개발자가 이를 사용할 가능성이 |
- | JUnit은이 스타일로 작성되었습니다. 테스트 실행에 절대적으로 필요한 기능 (테스트 모음 실행, 서로 테스트 실행 격리, 테스트 자동 실행) 만 구현합니다. | + | JUnit는 이 스타일로 작성되었습니다. 테스트 실행에 절대적으로 필요한 기능 (테스트 모음 실행, 서로 테스트 실행 격리, 테스트 자동 실행)만 구현합니다. |
- | 물론 우리는 일부 기능을 추가하는 것을 거부 할 수 없었지만 그것들을 자체 확장 패키지 (test.extensions)에 넣도록주의했습니다. | + | 물론 우리는 일부 기능을 추가하는 것을 거부할 수 없었지만, 그것들을 자체 확장 패키지 (test.extensions)에 넣도록 주의했습니다. |
- | 이 패키지의 주목할만한 멤버는 테스트 전후에 추가 코드를 실행할 수있는 TestDecorator입니다. | + | 이 패키지의 주목할만한 멤버는 테스트 전후에 추가 코드를 실행할 수 있는 TestDecorator입니다. |
+ | |||
프레임워크 작성자는 코드를 읽습니다. | 프레임워크 작성자는 코드를 읽습니다. | ||
우리는 JUnit 코드를 작성하는 것보다 훨씬 더 많은 시간을 소비했고, | 우리는 JUnit 코드를 작성하는 것보다 훨씬 더 많은 시간을 소비했고, | ||
- | 새로운 기능을 추가하는 데 소비 한 것만큼 중복 기능을 제거하는 데 거의 시간을 소비했습니다. | + | 새로운 기능을 추가하는 데 소비한 것만큼 중복 기능을 제거하는 데 거의 시간을 소비했습니다. |
우리는 우리가 상상할 수 있는 한 다양한 방식으로 새로운 클래스를 추가하고 책임을 이동하면서 디자인을 적극적으로 실험했습니다. | 우리는 우리가 상상할 수 있는 한 다양한 방식으로 새로운 클래스를 추가하고 책임을 이동하면서 디자인을 적극적으로 실험했습니다. | ||
- | 우리는 JUnit, 테스트, 객체 디자인, 프레임워크 개발 및 추가 기사에 대한 기회에 대한 지속적인 인사이트 흐름을 통해 우리의 | + | 우리는 JUnit, 테스트, 객체 디자인, 프레임워크 개발 및 추가 기사에 대한 기회에 대한 지속적인 인사이트 흐름을 통해 우리의 |
(그리고 여전히 보상을 받고 있습니다). | (그리고 여전히 보상을 받고 있습니다). | ||
- | 최신 버전의 JUnit은 http:// | + | 최신 버전의 JUnit는 http:// |
5. 감사의 말 | 5. 감사의 말 | ||
John Vlissides, Ralph Johnson, Nick Edgar에게 감사드립니다. | John Vlissides, Ralph Johnson, Nick Edgar에게 감사드립니다. | ||
+ | | ||
+ | 원문: http:// | ||
+ | |||
+ | |||
+ | {{tag> |