Skip to content

Commit

Permalink
refactor(Various new tests):
Browse files Browse the repository at this point in the history
  • Loading branch information
br648 committed Aug 16, 2024
1 parent 1d57cd6 commit 208ea3c
Show file tree
Hide file tree
Showing 21 changed files with 738 additions and 193 deletions.
583 changes: 459 additions & 124 deletions src/test/java/com/conveyal/gtfs/GTFSFaresV2Test.java

Large diffs are not rendered by default.

62 changes: 43 additions & 19 deletions src/test/java/com/conveyal/gtfs/TestUtils.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
package com.conveyal.gtfs;

import com.conveyal.gtfs.error.NewGTFSErrorType;
import com.conveyal.gtfs.loader.FeedLoadResult;
import com.conveyal.gtfs.loader.SnapshotResult;
import com.conveyal.gtfs.loader.Table;
import com.conveyal.gtfs.storage.ErrorExpectation;
import com.conveyal.gtfs.storage.ExpectedFieldType;
import com.conveyal.gtfs.storage.PersistenceExpectation;
import com.conveyal.gtfs.storage.RecordExpectation;
import com.conveyal.gtfs.util.InvalidNamespaceException;
import com.conveyal.gtfs.validator.FeedValidatorCreator;
import com.conveyal.gtfs.validator.ValidationResult;
import com.csvreader.CsvReader;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.BOMInputStream;
import org.hamcrest.Matcher;
import org.hamcrest.comparator.ComparatorMatcherBuilder;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -28,25 +15,19 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import static com.conveyal.gtfs.util.Util.randomIdString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class TestUtils {
Expand Down Expand Up @@ -301,4 +282,47 @@ public static void checkFileTestCases(ZipFile zip, FileTestCase[] fileTestCases)
);
}
}


/**
* Asserts that a given value for the specified field in result set matches provided matcher.
*/
public static void assertResultValue(ResultSet resultSet, String field, Matcher matcher) throws SQLException {
assertThat(resultSet.getObject(field), matcher);
}

/**
* Executes SQL query for the specified ID and columns and returns the resulting result set.
*/
public static ResultSet getResultSetForId(DataSource dataSource, String namespace, int id, Table table, String... columns) throws SQLException {
String sql = getColumnsForId(namespace, id, table, columns);
return dataSource.getConnection().prepareStatement(sql).executeQuery();
}

/**
* Constructs SQL query for the specified ID and columns and returns the resulting result set.
*/
public static String getColumnsForId(String namespace, int id, Table table, String... columns) {
String sql = String.format(
"select %s from %s.%s where id=%d",
columns.length > 0 ? String.join(", ", columns) : "*",
namespace,
table.name,
id
);
LOG.info(sql);
return sql;
}

public static void assertThatSqlQueryYieldsRowCount(DataSource dataSource, String sql, int expectedRowCount) throws SQLException {
LOG.info(sql);
int recordCount = 0;
ResultSet rs = dataSource.getConnection().prepareStatement(sql).executeQuery();
while (rs.next()) recordCount++;
assertThat("Records matching query should equal expected count.", recordCount, equalTo(expectedRowCount));
}

public static void assertThatSqlQueryYieldsZeroRows(DataSource dataSource, String sql) throws SQLException {
assertThatSqlQueryYieldsRowCount(dataSource, sql, 0);
}
}
14 changes: 14 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/AreaDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.Area} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class AreaDTO {
public Integer id;
public String area_id;
public String area_name;
}
20 changes: 20 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/FareLegRuleDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.FareLegRule} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class FareLegRuleDTO {
public Integer id;
public String leg_group_id;
public String network_id;
public String from_area_id;
public String to_area_id;
public String from_timeframe_group_id;
public String to_timeframe_group_id;
public String fare_product_id;
public int rule_priority;
}
15 changes: 15 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/FareMediaDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.FareMedia} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class FareMediaDTO {
public Integer id;
public String fare_media_id;
public String fare_media_name;
public int fare_media_type;
}
17 changes: 17 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/FareProductDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.FareProduct} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class FareProductDTO {
public Integer id;
public String fare_product_id;
public String fare_product_name;
public String fare_media_id;
public double amount;
public String currency;
}
19 changes: 19 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/FareTransferRuleDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.FareTransferRule} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class FareTransferRuleDTO {
public Integer id;
public String from_leg_group_id;
public String to_leg_group_id;
public int transfer_count;
public int duration_limit;
public int duration_limit_type;
public int fare_transfer_type;
public String fare_product_id;
}
14 changes: 14 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/NetworkDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.Network} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class NetworkDTO {
public Integer id;
public String network_id;
public String network_name;
}
14 changes: 14 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/RouteNetworkDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.RouteNetwork} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class RouteNetworkDTO {
public Integer id;
public String network_id;
public String route_id;
}
14 changes: 14 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/StopAreaDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.StopArea} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class StopAreaDTO {
public Integer id;
public String area_id;
public String stop_id;
}
16 changes: 16 additions & 0 deletions src/test/java/com/conveyal/gtfs/dto/TimeFrameDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.conveyal.gtfs.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
* DTO used to model expected {@link com.conveyal.gtfs.model.TimeFrame} JSON structure for the editor. NOTE: reference types
* (e.g., Integer and Double) are used here in order to model null/empty values in JSON object.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class TimeFrameDTO {
public Integer id;
public String timeframe_group_id;
public Integer start_time;
public Integer end_time;
public String service_id;
}
93 changes: 93 additions & 0 deletions src/test/java/com/conveyal/gtfs/graphql/GTFSGraphQLTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public class GTFSGraphQLTest {
private static DataSource testInjectionDataSource;
private static String testInjectionNamespace;
private static String badCalendarDateNamespace;

public static String faresDBName;
private static DataSource faresDataSource;
private static String faresNamespace;

private static final int TEST_TIMEOUT = 5000;

@BeforeAll
Expand Down Expand Up @@ -75,12 +80,25 @@ public static void setUpClass() throws IOException {
testInjectionNamespace = injectionFeedLoadResult.uniqueIdentifier;
// validate feed to create additional tables
validate(testInjectionNamespace, testInjectionDataSource);

String folderName = "fake-agency-with-fares-v2";
String faresZipFileName = TestUtils.zipFolderFiles(folderName, true);
// create a new database
faresDBName = TestUtils.generateNewDB();
String faresConnectionUrl = String.format("jdbc:postgresql://localhost/%s", faresDBName);
faresDataSource = TestUtils.createTestDataSource(faresConnectionUrl);
// load feed into db
FeedLoadResult faresFeedLoadResult = load(faresZipFileName, faresDataSource);
faresNamespace = faresFeedLoadResult.uniqueIdentifier;
// validate feed to create additional tables
validate(faresNamespace, faresDataSource);
}

@AfterAll
public static void tearDownClass() {
TestUtils.dropDB(testDBName);
TestUtils.dropDB(testInjectionDBName);
TestUtils.dropDB(faresDBName);
}

/** Tests that the graphQL schema can initialize. */
Expand Down Expand Up @@ -230,6 +248,69 @@ public void canFetchServices() {
});
}

@Test
void canFetchAreas() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedAreas.txt"), matchesSnapshot());
});
}

@Test
void canFetchStopAreas() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedStopAreas.txt"), matchesSnapshot());
});
}

@Test
void canFetchFareTransferRules() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedFareTransferRules.txt"), matchesSnapshot());
});
}

@Test
void canFetchFareProducts() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedFareProducts.txt"), matchesSnapshot());
});
}

@Test
void canFetchFareMedias() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedFareMedias.txt"), matchesSnapshot());
});
}

@Test
void canFetchFareLegRules() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedFareLegRules.txt"), matchesSnapshot());
});
}

@Test
void canFetchTimeFrames() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedTimeFrames.txt"), matchesSnapshot());
});
}

@Test
void canFetchNetworks() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedNetworks.txt"), matchesSnapshot());
});
}

@Test
void canFetchRouteNetworks() {
assertTimeout(Duration.ofMillis(TEST_TIMEOUT), () -> {
MatcherAssert.assertThat(queryFaresGraphQL("feedRouteNetworks.txt"), matchesSnapshot());
});
}

/** Tests that the stop times of a feed can be fetched. */
@Test
public void canFetchRoutesAndFilterTripsByDateAndTime() {
Expand Down Expand Up @@ -352,6 +433,18 @@ private Map<String, Object> queryGraphQL(String queryFilename) throws IOExceptio
return queryGraphQL(queryFilename, variables, testDataSource);
}

/**
* Helper method to make a fares query with default variables.
*
* @param queryFilename the filename that should be used to generate the GraphQL query. This file must be present
* in the `src/test/resources/graphql` folder
*/
private Map<String, Object> queryFaresGraphQL(String queryFilename) throws IOException {
Map<String, Object> variables = new HashMap<>();
variables.put("namespace", faresNamespace);
return queryGraphQL(queryFilename, variables, faresDataSource);
}

/**
* Helper method to execute a GraphQL query and return the result.
*
Expand Down
Loading

0 comments on commit 208ea3c

Please sign in to comment.