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

assertEquals enforces ordered equality for all subclasses of Collection and Iterable #2929

Open
2 of 7 tasks
kqarryzada opened this issue Jun 30, 2023 · 0 comments
Open
2 of 7 tasks

Comments

@kqarryzada
Copy link

kqarryzada commented Jun 30, 2023

TestNG Version

7.5.1, but the behavior is reproducible on the latest release (7.8.0).

Background

I am using Jackson, a very popular library that helps support JSON in Java. As a result of an upgrade from 7.4.0 to 7.5.1 (for JDK 8 support), I ran into a set of test failures involving the JsonNode class from Jackson, which implements Iterable. It appears that Iterables and Collections now must be in the same order to be considered equivalent by assertEquals. However, by definition, JSON objects do not have to have elements in the same order.

The biggest inconsistency is that for two JsonNodes node1 and node2 that have elements in differing orders, TestNG declares that:

  • assertEquals(node1, node2) is false
  • assertTrue(node1.equals(node2)) is true

Some history on this shows that this behavior has changed a few times.

The concerns noted on #2540 are fair and make sense. However, I'm unsure that the current behavior is appropriate. To me, having a set-specific implementation of assertEquals is the wrong approach to fix this problem when any subclass can decide whether ordering of the elements contained within the Iterable or Collection matters or not. But I recognize that this is nuanced.

I resolved this issue in my project by using the AssertJ library, which compares JsonNodes in a way that I expect. So this issue is not critical for me, but I think it's worth evaluating whether some of the inconsistencies mentioned here can potentially warrant a change in this behavior.

I've added a test case that defines my own subclass in an attempt to make a simple reproducible test. It involves a mathematical "unordered pair" object whose equivalency is evaluated incorrectly.

Expected behavior

assertEquals(one, two) should always have the same behavior as assertTrue(one.equals(two)).

Actual behavior

assertEquals(one, two) is not equivalent to assertTrue(one.equals(two)) in the example code provided below.

Is the issue reproducible on runner?

  • Shell
  • Maven
  • Gradle
  • Ant
  • Eclipse
  • IntelliJ
  • NetBeans

Test case sample

import org.testng.annotations.Test;
import java.util.*;
import static org.testng.Assert.*;

public class TestCase {
  private static class UnorderedPair implements Iterable<Integer> {
    List<Integer> children;

    public UnorderedPair(int a, int b) {
      children = Arrays.asList(a, b);
    }

    public int getFirst() {
      return children.get(0);
    }

    public int getLast() {
      return children.get(1);
    }

    @Override
    public boolean equals(Object o) {
      if (!(o instanceof UnorderedPair)) {
        return false;
      }

      UnorderedPair other = (UnorderedPair) o;
      if (getFirst() == other.getFirst() && getLast() == other.getLast()) {
        return true;
      }
      return getFirst() == other.getLast() && getLast() == other.getFirst();
    }

    @Override
    public Iterator<Integer> iterator() {
      return children.iterator();
    }
  }

  @Test
  public void testEquals() {
    UnorderedPair ascendingOrder = new UnorderedPair(1, 2);
    UnorderedPair descendingOrder = new UnorderedPair(2, 1);

    // This assertion passes.
    assertTrue(ascendingOrder.equals(descendingOrder));

    // This assertion fails.
    assertEquals(ascendingOrder, descendingOrder);
  }
}

Contribution guidelines

In case you plan to raise a pull request to fix this issue, please make sure you refer our
Contributing section for detailed set of steps.

@kqarryzada kqarryzada changed the title TestNG enforces ordered equality for all subclasses of Collection and Iterable assertEquals enforces ordered equality for all subclasses of Collection and Iterable Jun 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant