1. 소개
이 기사에서는 JBehave 를 간략히 살펴본 다음 BDD 관점에서 REST API를 테스트하는 데 중점을 둡니다.
2. JBehave와 BDD
JBehave는 행동 기반 개발 프레임 워크입니다. 자동화 된 승인 테스트를위한 직관적이고 접근 가능한 방법을 제공하려고합니다.
BDD에 익숙하지 않다면 이 기사 부터 시작 하여 일반적인 BDD 구조와 기능을 소개하는 또 다른 BDD 테스트 프레임 워크 인 Cucumber를 다루는 것이 좋습니다 .
다른 BDD 프레임 워크와 마찬가지로 JBehave는 다음 개념을 채택합니다.
- 스토리 – 자동으로 실행 가능한 비즈니스 기능 증가를 나타내며 하나 이상의 시나리오로 구성됩니다.
- 시나리오 – 시스템 동작의 구체적인 예를 나타냅니다.
- 단계 – 기존 BDD 키워드를 사용하여 실제 행동을 나타냅니다 : Given , When , Then
일반적인 시나리오는 다음과 같습니다.
Given a precondition
When an event occurs
Then the outcome should be captured
시나리오의 각 단계는 JBehave의 어노테이션에 해당합니다.
- @Given : 컨텍스트 시작
- @When : 행동을
- @Then : 예상 결과 테스트
3. Maven 의존성
Maven 프로젝트에서 JBehave를 사용하려면 jbehave-core 의존성이 pom에 포함되어야합니다 .
<dependency>
<groupId>org.jbehave</groupId>
<artifactId>jbehave-core</artifactId>
<version>4.1</version>
<scope>test</scope>
</dependency>
4. 빠른 예
JBehave를 사용하려면 다음 단계를 따라야합니다.
- 사용자 스토리 작성
- 사용자 스토리의 단계를 Java 코드로 매핑
- 사용자 스토리 구성
- JBehave 테스트 실행
- 결과 검토
4.1. 이야기
다음과 같은 간단한 이야기부터 시작하겠습니다. "사용자로서 카운터 값을 1 씩 증가시킬 수 있도록 카운터를 늘리고 싶습니다."
스토리를 .story 파일로 정의 할 수 있습니다 .
Scenario: when a user increases a counter, its value is increased by 1
Given a counter
And the counter has any integral value
When the user increases the counter
Then the value of the counter must be 1 greater than previous value
4.2. 매핑 단계
단계가 주어지면 Java로 구현해 보겠습니다.
public class IncreaseSteps {
private int counter;
private int previousValue;
@Given("a counter")
public void aCounter() {
}
@Given("the counter has any integral value")
public void counterHasAnyIntegralValue() {
counter = new Random().nextInt();
previousValue = counter;
}
@When("the user increases the counter")
public void increasesTheCounter() {
counter++;
}
@Then("the value of the counter must be 1 greater than previous value")
public void theValueOfTheCounterMustBe1Greater() {
assertTrue(1 == counter - previousValue);
}
}
기억 어노테이션의 값이 정확하게 설명을 일치해야합니다 .
4.3. 스토리 구성
단계를 수행하려면 스토리의 무대를 설정해야합니다.
public class IncreaseStoryLiveTest extends JUnitStories {
@Override
public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(new LoadFromClasspath(this.getClass()))
.useStoryReporterBuilder(new StoryReporterBuilder()
.withCodeLocation(codeLocationFromClass(this.getClass()))
.withFormats(CONSOLE));
}
@Override
public InjectableStepsFactory stepsFactory() {
return new InstanceStepsFactory(configuration(), new IncreaseSteps());
}
@Override
protected List<String> storyPaths() {
return Arrays.asList("increase.story");
}
}
에서 storyPaths () , 우리는 우리의 제공 .story JBehave를 구문 분석 할 파일 경로를. 실제 단계 구현은 stepsFactory ()에 제공됩니다 . 그런 다음 configuration () 에서 스토리 로더 및 스토리 보고서가 올바르게 구성됩니다.
이제 모든 준비가 완료 되었으므로 mvn clean test를 실행하여 간단히 스토리를 시작할 수 있습니다 .
4.4. 테스트 결과 검토
콘솔에서 테스트 결과를 볼 수 있습니다. 테스트가 성공적으로 통과되었으므로 출력은 스토리와 동일합니다.
Scenario: when a user increases a counter, its value is increased by 1
Given a counter
And the counter has any integral value
When the user increases the counter
Then the value of the counter must be 1 greater than previous value
시나리오의 단계를 구현하는 것을 잊은 경우 보고서에서 알려줍니다. @When 단계를 구현하지 않았습니다 .
Scenario: when a user increases a counter, its value is increased by 1
Given a counter
And the counter has any integral value
When the user increases the counter (PENDING)
Then the value of the counter must be 1 greater than previous value (NOT PERFORMED)
@When("the user increases the counter")
@Pending
public void whenTheUserIncreasesTheCounter() {
// PENDING
}
보고서에는 @When a step is pending (단계가 보류 중일 때)가 표시되므로 @Then 단계가 수행되지 않습니다.
@Then 단계가 실패하면 어떻게 되나요? 보고서에서 바로 오류를 찾을 수 있습니다.
Scenario: when a user increases a counter, its value is increased by 1
Given a counter
And the counter has any integral value
When the user increases the counter
Then the value of the counter must be 1 greater than previous value (FAILED)
(java.lang.AssertionError)
5. REST API 테스트
이제 우리는 JBhave 의 기본을 이해했습니다 . REST API를 사용하여 테스트하는 방법을 살펴 보겠습니다. 테스트는 Java로 REST API를 테스트하는 방법을 논의한 이전 기사를 기반으로합니다 .
이 기사에서는 GitHub REST API를 테스트했으며 주로 HTTP 응답 코드, 헤더 및 페이로드에 중점을 두었습니다. 간단하게하기 위해 우리는 각각 3 개의 개별 스토리로 작성할 수 있습니다.
5.1. 상태 코드 테스트
이야기:
Scenario: when a user checks a non-existent user on github, github would respond 'not found'
Given github user profile api
And a random non-existent username
When I look for the random user via the api
Then github respond: 404 not found
When I look for eugenp1 via the api
Then github respond: 404 not found
When I look for eugenp2 via the api
Then github respond: 404 not found
단계:
public class GithubUserNotFoundSteps {
private String api;
private String nonExistentUser;
private int githubResponseCode;
@Given("github user profile api")
public void givenGithubUserProfileApi() {
api = "https://api.github.com/users/%s";
}
@Given("a random non-existent username")
public void givenANonexistentUsername() {
nonExistentUser = randomAlphabetic(8);
}
@When("I look for the random user via the api")
public void whenILookForTheUserViaTheApi() throws IOException {
githubResponseCode = getGithubUserProfile(api, nonExistentUser)
.getStatusLine()
.getStatusCode();
}
@When("I look for $user via the api")
public void whenILookForSomeNonExistentUserViaTheApi(
String user) throws IOException {
githubResponseCode = getGithubUserProfile(api, user)
.getStatusLine()
.getStatusCode();
}
@Then("github respond: 404 not found")
public void thenGithubRespond404NotFound() {
assertTrue(SC_NOT_FOUND == githubResponseCode);
}
//...
}
구현 단계 에서 매개 변수 삽입 기능을 어떻게 사용했는지 확인하세요 . 단계 후보에서 추출 된 인수는 어노테이션이있는 Java 메소드의 매개 변수에 자연 순서에 따라 일치됩니다.
또한 어노테이션이 달린 명명 된 매개 변수가 지원됩니다.
@When("I look for $username via the api")
public void whenILookForSomeNonExistentUserViaTheApi(
@Named("username") String user) throws IOException
5.2. 미디어 유형 테스트
다음은 간단한 MIME 유형 테스트 스토리입니다.
Scenario: when a user checks a valid user's profile on github, github would respond json data
Given github user profile api
And a valid username
When I look for the user via the api
Then github respond data of type json
그리고 단계는 다음과 같습니다.
public class GithubUserResponseMediaTypeSteps {
private String api;
private String validUser;
private String mediaType;
@Given("github user profile api")
public void givenGithubUserProfileApi() {
api = "https://api.github.com/users/%s";
}
@Given("a valid username")
public void givenAValidUsername() {
validUser = "eugenp";
}
@When("I look for the user via the api")
public void whenILookForTheUserViaTheApi() throws IOException {
mediaType = ContentType
.getOrDefault(getGithubUserProfile(api, validUser).getEntity())
.getMimeType();
}
@Then("github respond data of type json")
public void thenGithubRespondDataOfTypeJson() {
assertEquals("application/json", mediaType);
}
}
5.3. JSON 페이로드 테스트
마지막 이야기 :
Scenario: when a user checks a valid user's profile on github, github's response json should include a login payload with the same username
Given github user profile api
When I look for eugenp via the api
Then github's response contains a 'login' payload same as eugenp
그리고 단순하고 직접적인 단계 구현 :
public class GithubUserResponsePayloadSteps {
private String api;
private GitHubUser resource;
@Given("github user profile api")
public void givenGithubUserProfileApi() {
api = "https://api.github.com/users/%s";
}
@When("I look for $user via the api")
public void whenILookForEugenpViaTheApi(String user) throws IOException {
HttpResponse httpResponse = getGithubUserProfile(api, user);
resource = RetrieveUtil.retrieveResourceFromResponse(httpResponse, GitHubUser.class);
}
@Then("github's response contains a 'login' payload same as $username")
public void thenGithubsResponseContainsAloginPayloadSameAsEugenp(String username) {
assertThat(username, Matchers.is(resource.getLogin()));
}
}
6. 요약
이 기사에서는 JBehave를 간략하게 소개하고 BDD 스타일 REST API 테스트를 구현했습니다.
일반 Java 테스트 코드와 비교할 때 JBehave로 구현 된 코드는 훨씬 명확하고 직관적이며 테스트 결과 보고서는 훨씬 더 우아해 보입니다.
항상 그렇듯이 예제 코드는 Github 프로젝트 에서 찾을 수 있습니다 .
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/jbehave-rest-testing
'Java' 카테고리의 다른 글
Java에서 일정 시간 후에 실행을 중지하는 방법 (0) | 2021.03.19 |
---|---|
Open Liberty 소개 (0) | 2021.03.19 |
자바의 JSON (0) | 2021.03.18 |
Spring Cloud 작업 소개 (0) | 2021.03.18 |
Spring 5 기능성 Bean 등록 (0) | 2021.03.18 |