Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cucumber 실습 #420

Open
wants to merge 6 commits into
base: testrace
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ dependencies {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}

// cucumber
testImplementation("io.cucumber:cucumber-java:7.14.0")
testImplementation("io.cucumber:cucumber-java8:7.14.0")
testImplementation("io.cucumber:cucumber-spring:7.14.0")
testImplementation("io.cucumber:cucumber-junit-platform-engine:7.14.0")
testImplementation("org.junit.platform:junit-platform-suite:1.10.0")
testImplementation("org.junit.platform:junit-platform-suite-api:1.10.0")
testImplementation("org.junit.platform:junit-platform-commons:1.10.0")
testImplementation("org.junit.platform:junit-platform-engine:1.10.0")

runtimeOnly 'com.h2database:h2'
}

Expand Down Expand Up @@ -81,4 +91,4 @@ task copyDocument(type: Copy) {

from file("build/docs/asciidoc")
into file("src/main/resources/static/docs")
}
}
4 changes: 4 additions & 0 deletions src/test/java/nextstep/subway/acceptance/LineSteps.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ public class LineSteps {
assertThat(response.jsonPath().getList("stations.id", Long.class)).containsExactly(idsOfStations);
}

public static void 경로_역_목록_조회됨(ExtractableResponse<Response> response, String[] stationNames) {
assertThat(response.jsonPath().getList("stations.name", String.class)).containsExactly(stationNames);
}

public static void 경로_전체_거리_조회됨(ExtractableResponse<Response> response, int distance) {
assertThat(response.jsonPath().getInt("distance")).isEqualTo(distance);
}
Expand Down
25 changes: 25 additions & 0 deletions src/test/java/nextstep/subway/cucumber/AcceptanceContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package nextstep.subway.cucumber;

import java.util.HashMap;
import java.util.Map;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Profile("test")
@Service
public class AcceptanceContext {

private Map<String, String> store = new HashMap<>();

public void put(final String name, final String id) {
store.putIfAbsent(name, id);
}

public String get(final String name) {
return store.get(name);
}

public Long getLongValue(final String name) {
return Long.valueOf(store.get(name));
}
}
17 changes: 17 additions & 0 deletions src/test/java/nextstep/subway/cucumber/BeforeDatabaseCleanup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package nextstep.subway.cucumber;

import io.cucumber.java8.En;
import nextstep.subway.utils.DatabaseCleanup;
import org.springframework.beans.factory.annotation.Autowired;

public class BeforeDatabaseCleanup implements En {

@Autowired
private DatabaseCleanup databaseCleanup;

public BeforeDatabaseCleanup() {
Before(() -> {
databaseCleanup.execute();
});
}
}
24 changes: 24 additions & 0 deletions src/test/java/nextstep/subway/cucumber/CucumberTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package nextstep.subway.cucumber;

import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;

import io.cucumber.spring.CucumberContextConfiguration;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

@ActiveProfiles("test")
@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "nextstep")
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
@CucumberContextConfiguration
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class CucumberTest {

}
107 changes: 107 additions & 0 deletions src/test/java/nextstep/subway/cucumber/steps/PathStepDef.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package nextstep.subway.cucumber.steps;

import static nextstep.subway.acceptance.LineSteps.경로_역_목록_조회됨;
import static nextstep.subway.acceptance.LineSteps.경로_전체_거리_조회됨;
import static nextstep.subway.acceptance.LineSteps.경로_전체_시간_조회됨;
import static nextstep.subway.acceptance.LineSteps.지하철_노선에_지하철_구간_생성_요청;
import static nextstep.subway.acceptance.PathAcceptanceSteps.경로_전체_요금_조회됨;
import static nextstep.subway.acceptance.PathAcceptanceSteps.두_역의_경로_조회를_요청;
import static nextstep.subway.acceptance.StationSteps.지하철역_생성_요청;

import io.cucumber.datatable.DataTable;
import io.cucumber.java8.En;
import io.restassured.RestAssured;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import nextstep.subway.acceptance.LineSteps;
import nextstep.subway.cucumber.AcceptanceContext;
import nextstep.subway.cucumber.CucumberTest;
import nextstep.subway.cucumber.steps.dto.PathStepResponse;
import nextstep.subway.domain.PathType;
import org.springframework.beans.factory.annotation.Autowired;

public class PathStepDef extends CucumberTest implements En {

@Autowired
private AcceptanceContext context;
private ExtractableResponse<Response> response;

public PathStepDef() {
Given("^지하철역을 생성하고$", (final DataTable dataTable) -> {
final List<String> stationNames = dataTable.asList();
for (final String stationName : stationNames) {
final Long id = 지하철역_생성_요청(stationName).jsonPath().getLong("id");

context.put(stationName, id + "");
}
});

And("^지하철 노선을 생성하고$", (final DataTable dataTable) -> {
final List<Map<String, String>> lines = dataTable.asMaps();
for (final Map<String, String> line : lines) {
final Map<String, String> lineParam = createLineParam(line);
final Long id = LineSteps.지하철_노선_생성_요청(lineParam).jsonPath().getLong("id");

context.put(line.get("name"), id + "");
}
});

And("{string}에 구간을 생성한다", (final String lineName, final DataTable dataTable) -> {
final Long lineId = context.getLongValue(lineName);
final Map<String, String> section = dataTable.asMap();
final Map<String, String> sectionParam = createSectionParam(section);

지하철_노선에_지하철_구간_생성_요청(lineId, sectionParam);
});

When("{string}에서 {string}까지 최단 경로 조회 요청하면", (final String source, final String target) -> {
final Long sourceId = context.getLongValue(source);
final Long targetId = context.getLongValue(target);

response = 두_역의_경로_조회를_요청(given(), sourceId, targetId, PathType.DISTANCE);
});

DataTableType((final Map<String, String> pathStepResponse) -> new PathStepResponse(
pathStepResponse.get("stations").split(","),
Integer.parseInt(pathStepResponse.get("distance")),
Integer.parseInt(pathStepResponse.get("duration")),
Integer.parseInt(pathStepResponse.get("fare"))
));

Then("^최단 경로 응답와 총 거리, 소요 시간, 요금정보를 조회한다$", (final PathStepResponse pathStepResponse) -> {
경로_역_목록_조회됨(response, pathStepResponse.getStations());
경로_전체_거리_조회됨(response, pathStepResponse.getDistance());
경로_전체_시간_조회됨(response, pathStepResponse.getDuration());
경로_전체_요금_조회됨(response, pathStepResponse.getFare());
});
}

private Map<String, String> createLineParam(final Map<String, String> line) {
final Map<String, String> lineParam = new HashMap<>();
lineParam.put("name", line.get("name"));
lineParam.put("color", line.get("color"));
lineParam.put("upStationId", context.get(line.get("upStation")));
lineParam.put("downStationId", context.get(line.get("downStation")));
lineParam.put("distance", line.get("distance"));
lineParam.put("duration", line.get("duration"));
lineParam.put("extraCharge", line.get("extraCharge"));
return lineParam;
}

private Map<String, String> createSectionParam(final Map<String, String> section) {
final Map<String, String> sectionParam = new HashMap<>();
sectionParam.put("upStationId", context.get(section.get("upStation")));
sectionParam.put("downStationId", context.get(section.get("downStation")));
sectionParam.put("distance", section.get("distance"));
sectionParam.put("duration", section.get("duration"));
return sectionParam;
}

private RequestSpecification given() {
return RestAssured.given().log().all();
}
}
45 changes: 45 additions & 0 deletions src/test/java/nextstep/subway/cucumber/steps/StationStepDef.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package nextstep.subway.cucumber.steps;

import static org.assertj.core.api.Assertions.assertThat;

import io.cucumber.java8.En;
import io.restassured.RestAssured;
import io.restassured.response.ExtractableResponse;
import io.restassured.response.Response;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;

public class StationStepDef implements En {

ExtractableResponse<Response> response;

public StationStepDef() {
When("지하철역을 생성하면", () -> {
Map<String, String> params = new HashMap<>();
params.put("name", "강남역");
response = RestAssured.given().log().all()
.body(params)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.when()
.post("/stations")
.then().log().all()
.extract();
});

Then("지하철역이 생성된다", () -> {
assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value());
});

Then("지하철역 목록 조회 시 생성한 역을 찾을 수 있다", () -> {
List<String> stationNames =
RestAssured.given().log().all()
.when().get("/stations")
.then().log().all()
.extract().jsonPath().getList("name", String.class);
assertThat(stationNames).containsAnyOf("강남역");
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package nextstep.subway.cucumber.steps.dto;

import java.util.Arrays;

public class PathStepResponse {

private final String[] stations;
private final int distance;
private final int duration;
private final int fare;

public PathStepResponse(final String[] stations, final int distance, final int duration, final int fare) {
this.stations = stations;
this.distance = distance;
this.duration = duration;
this.fare = fare;
}

public String[] getStations() {
return stations;
}

public int getDistance() {
return distance;
}

public int getDuration() {
return duration;
}

public int getFare() {
return fare;
}

@Override
public String toString() {
return "PathStepResponse{" +
"stations=" + Arrays.toString(stations) +
", distance=" + distance +
", duration=" + duration +
", fare=" + fare +
'}';
}
}
27 changes: 27 additions & 0 deletions src/test/resources/path.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Feature: 경로 조회 기능

Scenario: 두 역의 최단 경로 조회
# 교대역 --- *2호선*(10) --- 강남역
# | |
# *3호선*(2) *신분당선* (10)
# | |
# 남부터미널역 --- *3호선*(3) --- 양재
Given 지하철역을 생성하고
| 교대역 |
| 강남역 |
| 양재역 |
| 남부터미널역 |
And 지하철 노선을 생성하고
| name | color | upStation | downStation | distance | duration | extraCharge |
| 2호선 | green | 교대역 | 강남역 | 10 | 10 | 300 |
| 신분당선 | red | 강남역 | 양재역 | 10 | 10 | 0 |
| 3호선 | orange | 교대역 | 남부터미널역 | 2 | 2 | 1000 |
And '3호선'에 구간을 생성한다
| upStation | 남부터미널역 |
| downStation | 양재역 |
| distance | 3 |
| duration | 3 |
When '교대역'에서 '양재역'까지 최단 경로 조회 요청하면
Then 최단 경로 응답와 총 거리, 소요 시간, 요금정보를 조회한다
| stations | distance | duration | fare |
| 교대역,남부터미널역,양재역 | 5 | 5 | 1250 |
6 changes: 6 additions & 0 deletions src/test/resources/station.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Feature: 지하철역 관련 기능

Scenario: 지하철역을 생성한다.
When 지하철역을 생성하면
Then 지하철역이 생성된다
And 지하철역 목록 조회 시 생성한 역을 찾을 수 있다