[ https://issues.apache.org/jira/browse/BEAM-9000?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Tomo Suzuki updated BEAM-9000: ------------------------------ Description: As of now, there are many tests that assert on {{toString()}} of objects. {code:java} CounterUpdate result = testObject.transform(monitoringInfo); assertEquals( "{cumulative=true, integer={highBits=0, lowBits=0}, " + "nameAndKind={kind=SUM, " + "name=transformedValue-ElementCount}}", result.toString()); {code} This style is prone to unnecessary maintenance of the test code when upgrading dependencies. Dependencies may change the internal ordering of fields and trivial change in {{toString()}}. In BEAM-8695, where I tried to upgrade google-http-client, there are ~30 comparison failure due to this {{toString}} assertions. They are subclasses of {{com.google.api.client.json.GenericJson}}. Several options to enhance these assertions. h1. Option 1: Assertion using Map Leveraging the fact that GenericJson is a subclass of AbstractMap<String, Object>, the assertion can be written as {code:java} ImmutableMap<String, Object> expected = ImmutableMap.of("cumulative", true, "integer", ImmutableMap.of("highBits", 0, "lowBits", 0), "nameAndKind", ImmutableMap.of("kind", "SUM", "name", "transformedValue-ElementCount")); assertEquals(expected, (Map<String, Object>)result); {code} Credit: Ben Whitehead. h1. Option 2: Create assertEqualsOnJson Leveraging the fact that instance of GenericJson can be instantiated through JSON, the assertion can be written as {code:java} assertEqualsOnJson( "{\"cumulative\":true, \"integer\":{\"highBits\":0, \"lowBits\":0}, " + "\"nameAndKind\":{\"kind\":\"SUM\", " + "\"name\":\"transformedValue-ElementCount\"}}", result); {code} {{assertEqualsOnJson}} is implemented as below. The following field and methods should go to shared test utility class (sdks/testing?) {code:java} private static final JacksonFactory jacksonFactory = JacksonFactory.getDefaultInstance(); public static <T extends GenericJson> void assertEqualsOnJson(String expectedJsonText, T actual) { CounterUpdate expected = parse(expectedJsonText, CounterUpdate.class); assertEquals(expected, actual); } public static <T extends GenericJson> T parse(String text, Class<T> clazz) { try { JsonParser parser = jacksonFactory.createJsonParser(text); return parser.parse(clazz); } catch (IOException ex) { throw new IllegalArgumentException("Could not parse the text as " + clazz, ex); } } {code} A feature request to handle escaping double quotes via JacksonFactory: [https://github.com/googleapis/google-http-java-client/issues/923] h1. Option3: Check JSON equality via JSONassert * https://github.com/skyscreamer/JSONassert * https://github.com/hertzsprung/hamcrest-json (Not using as last commit was in 2012) The JSONassert example does not carry quoted double quote characters. The implementation would be converting actual object into JSON object and calling {{JSONAssert.assertEqual}}. Credit: Luke Cwik was: As of now, there are many tests that assert on {{toString()}} of objects. {code:java} CounterUpdate result = testObject.transform(monitoringInfo); assertEquals( "{cumulative=true, integer={highBits=0, lowBits=0}, " + "nameAndKind={kind=SUM, " + "name=transformedValue-ElementCount}}", result.toString()); {code} This style is prone to unnecessary maintenance of the test code when upgrading dependencies. Dependencies may change the internal ordering of fields and trivial change in {{toString()}}. In BEAM-8695, where I tried to upgrade google-http-client, there are ~30 comparison failure due to this {{toString}} assertions. They are subclasses of {{com.google.api.client.json.GenericJson}}. Several options to enhance these assertions. h1. Option 1: Assertion using Map Leveraging the fact that GenericJson is a subclass of AbstractMap<String, Object>, the assertion can be written as {code:java} ImmutableMap<String, Object> expected = ImmutableMap.of("cumulative", true, "integer", ImmutableMap.of("highBits", 0, "lowBits", 0), "nameAndKind", ImmutableMap.of("kind", "SUM", "name", "transformedValue-ElementCount")); assertEquals(expected, (Map<String, Object>)result); {code} Credit: Ben Whitehead. h1. Option 2: Create assertEqualsOnJson Leveraging the fact that instance of GenericJson can be instantiated through JSON, the assertion can be written as {code:java} assertEqualsOnJson( "{\"cumulative\":true, \"integer\":{\"highBits\":0, \"lowBits\":0}, " + "\"nameAndKind\":{\"kind\":\"SUM\", " + "\"name\":\"transformedValue-ElementCount\"}}", result); {code} {{assertEqualsOnJson}} is implemented as below. The following field and methods should go to shared test utility class (sdks/testing?) {code:java} private static final JacksonFactory jacksonFactory = JacksonFactory.getDefaultInstance(); public static <T extends GenericJson> void assertEqualsOnJson(String expectedJsonText, T actual) { CounterUpdate expected = parse(expectedJsonText, CounterUpdate.class); assertEquals(expected, actual); } public static <T extends GenericJson> T parse(String text, Class<T> clazz) { try { JsonParser parser = jacksonFactory.createJsonParser(text); return parser.parse(clazz); } catch (IOException ex) { throw new IllegalArgumentException("Could not parse the text as " + clazz, ex); } } {code} A feature request to handle escaping double quotes via JacksonFactory: [https://github.com/googleapis/google-http-java-client/issues/923] h1. Check JSON equality via JSONassert * https://github.com/skyscreamer/JSONassert * https://github.com/hertzsprung/hamcrest-json (Not using as last commit was in 2012) The JSONassert example does not carry quoted double quote characters. The implementation would be converting actual object into JSON object and calling {{JSONAssert.assertEqual}}. Credit: Luke Cwik > Java Test Assertions without toString for GenericJson subclasses > ---------------------------------------------------------------- > > Key: BEAM-9000 > URL: https://issues.apache.org/jira/browse/BEAM-9000 > Project: Beam > Issue Type: Improvement > Components: testing > Reporter: Tomo Suzuki > Assignee: Tomo Suzuki > Priority: Minor > > As of now, there are many tests that assert on {{toString()}} of objects. > {code:java} > CounterUpdate result = testObject.transform(monitoringInfo); > assertEquals( > "{cumulative=true, integer={highBits=0, lowBits=0}, " > + "nameAndKind={kind=SUM, " > + "name=transformedValue-ElementCount}}", > result.toString()); > {code} > This style is prone to unnecessary maintenance of the test code when > upgrading dependencies. Dependencies may change the internal ordering of > fields and trivial change in {{toString()}}. In BEAM-8695, where I tried to > upgrade google-http-client, there are ~30 comparison failure due to this > {{toString}} assertions. > They are subclasses of {{com.google.api.client.json.GenericJson}}. > Several options to enhance these assertions. > h1. Option 1: Assertion using Map > Leveraging the fact that GenericJson is a subclass of AbstractMap<String, > Object>, the assertion can be written as > {code:java} > ImmutableMap<String, Object> expected = ImmutableMap.of("cumulative", > true, > "integer", ImmutableMap.of("highBits", 0, "lowBits", 0), > "nameAndKind", ImmutableMap.of("kind", "SUM", "name", > "transformedValue-ElementCount")); > assertEquals(expected, (Map<String, Object>)result); > {code} > Credit: Ben Whitehead. > h1. Option 2: Create assertEqualsOnJson > Leveraging the fact that instance of GenericJson can be instantiated through > JSON, the assertion can be written as > {code:java} > assertEqualsOnJson( > "{\"cumulative\":true, \"integer\":{\"highBits\":0, \"lowBits\":0}, " > + "\"nameAndKind\":{\"kind\":\"SUM\", " > + "\"name\":\"transformedValue-ElementCount\"}}", > result); > {code} > > {{assertEqualsOnJson}} is implemented as below. The following field and > methods should go to shared test utility class (sdks/testing?) > {code:java} > private static final JacksonFactory jacksonFactory = > JacksonFactory.getDefaultInstance(); > public static <T extends GenericJson> void assertEqualsOnJson(String > expectedJsonText, T actual) { > CounterUpdate expected = parse(expectedJsonText, CounterUpdate.class); > assertEquals(expected, actual); > } > public static <T extends GenericJson> T parse(String text, Class<T> clazz) { > try { > JsonParser parser = jacksonFactory.createJsonParser(text); > return parser.parse(clazz); > } catch (IOException ex) { > throw new IllegalArgumentException("Could not parse the text as " + > clazz, ex); > } > } > {code} > A feature request to handle escaping double quotes via JacksonFactory: > [https://github.com/googleapis/google-http-java-client/issues/923] > > h1. Option3: Check JSON equality via JSONassert > * https://github.com/skyscreamer/JSONassert > * https://github.com/hertzsprung/hamcrest-json (Not using as last commit was > in 2012) > The JSONassert example does not carry quoted double quote characters. The > implementation would be converting actual object into JSON object and calling > {{JSONAssert.assertEqual}}. > Credit: Luke Cwik > -- This message was sent by Atlassian Jira (v8.3.4#803005)