Skip to content

testlib collections: Improve test names / assertion stack traces for collection test suites #7585

Open
@Marcono1234

Description

@Marcono1234

API(s)

com.google.common.collect.testing.*

For example MapTestSuiteBuilder or ListTestSuiteBuilder

How do you want it to be improved?

The collection test suites should make it easier to identify where in the user code the test suite was created / to which user test class it belongs, especially if an assertion fails in the test suite

Why do we need it to be improved?

There are two issues with the collection test suites:

  • You have to specify a test suite name with named(String), however if you specify
    • a custom short name, then depending on where you run the test, you don't immediately understand which user class created the test suite
      (this differs between tooling / IDEs; in Eclipse there seems to be no indication which of the user's test classes created the test suite, in IntelliJ and Maven on console it does include the test class name in the UI / console output)
    • the name of the enclosing test class, then the test output becomes verbose because Guava seems to repeat the name for its nested tests, e.g. " [collection size: one]"
  • if an assertion fails, the complete stack trace is only Guava code

Example

Take for example this Maven test failure from Gson:

[INFO] Running com.google.gson.JsonArrayAsListSuiteTest
Error:  Tests run: 404, Failures: 2, Errors: 0, Skipped: 0, Time elapsed: 0.445 s <<< FAILURE! -- in com.google.gson.JsonArrayAsListSuiteTest
Error:  com.google.common.collect.testing.testers.CollectionCreationTester.testCreateWithNull_unsupported[JsonArray#asList [collection size: one]] -- Time elapsed: 0.001 s <<< FAILURE!
java.lang.AssertionError: expected to throw NullPointerException
	at com.google.common.collect.testing.testers.ReflectionFreeAssertThrows.doAssertThrows(ReflectionFreeAssertThrows.java:101)
	at com.google.common.collect.testing.testers.ReflectionFreeAssertThrows.assertThrows(ReflectionFreeAssertThrows.java:61)
	at com.google.common.collect.testing.testers.CollectionCreationTester.testCreateWithNull_unsupported(CollectionCreationTester.java:58)
	at jdk.internal.reflect.GeneratedMethodAccessor96.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at junit.framework.TestCase.runTest(TestCase.java:177)
	at junit.framework.TestCase.runBare(TestCase.java:142)
	at junit.framework.TestResult$1.protect(TestResult.java:122)
	at junit.framework.TestResult.runProtected(TestResult.java:142)
	at junit.framework.TestResult.run(TestResult.java:125)
	at junit.framework.TestCase.run(TestCase.java:130)
	at junit.framework.TestSuite.runTest(TestSuite.java:241)
	at junit.framework.TestSuite.run(TestSuite.java:236)
	at junit.framework.TestSuite.runTest(TestSuite.java:241)
	at junit.framework.TestSuite.run(TestSuite.java:236)
	at junit.framework.TestSuite.runTest(TestSuite.java:241)
	at junit.framework.TestSuite.run(TestSuite.java:236)
	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
	at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:316)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:240)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:214)
	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:155)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
	at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
	at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)

Or generally how the test suites are used in Gson:

Current Behavior

Luckily Maven includes the name of the test Java class it is executing (in the example JsonArrayAsListSuiteTest), but besides that:

  • The test name is (mostly) a Guava defined test name: com.google.common.collect.testing.testers.CollectionCreationTester.testCreateWithNull_unsupported
  • The complete stack trace is either Guava or JUnit, there is not a single mention of the Gson test class which created the test suite

You would have to notice the test suite name (in the example "JsonArray#asList") and then manually look for the user test class which creates a test suite with that name.

Desired Behavior

See "How do you want it to be improved?" above

Not completely sure how it could be improved; some ideas:

  • Guava could get the caller of createTestSuite() and include its qualified class name in the test suite name (maybe?)
    That might be mostly relevant for Eclipse, see "Why do we need it to be improved?" above. Alternatively the user could do that themselves by creating an additional TestSuite with that qualified class name, wrapping the Guava test suite.
  • Guava could get the caller of createTestSuite() and include it in the stack trace of assertion errors (possibly as dummy 'suppressed' or 'cause' exception)
  • Guava could get the class name of the used TestContainerGenerator implementation and somehow include it in the test suite names or assertion errors (?)

These ideas are not ideal; any other ideas are welcome!

Concrete Use Cases

See "Example" section above

Checklist

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions