[ 
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 many 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}
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}

  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 many comparison failure due to this {{toString}} 
assertions.

Several options to enhance these assertions.
h1. Option 1: Assertion using Map
{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}
h1. Option 2: Create assertEqualsOnJson
{code:java}
    assertEqualsOnJson(
        "{\"cumulative\":true, \"integer\":{\"highBits\":0, \"lowBits\":0}, "
            + "\"nameAndKind\":{\"kind\":\"SUM\", "
            + "\"name\":\"transformedValue-ElementCount\"}}",
        result);
{code}
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}


> 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 many 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}
> 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}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to