[ 
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)

Reply via email to