DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations

Trending

  • Micro Frontends on Monorepo With Remote State Management
  • CDNs: Speed Up Performance by Reducing Latency
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • Mainframe Development for the "No Mainframe" Generation
  1. DZone
  2. Coding
  3. Java
  4. Test Collection Implementations with Guava

Test Collection Implementations with Guava

Nicolai Parlog user avatar by
Nicolai Parlog
·
May. 01, 15 · Interview
Like (0)
Save
Tweet
Share
3.89K Views

Join the DZone community and get the full member experience.

Join For Free

I’m currently adding a new feature to LibFX, for which I create some custom collections akin to those from the Java Collections Framework. I went looking for tests I could run against them and was delighted to find out that Google’s Guava contains just what I need: a massive test suite which verifies every nook and cranny of my implementation for all collection interfaces from the JDK and Guava.

Let’s have a quick look at it.

Overview

This post will first show how to set up the project before looking at how to get started with the actual tests.

I created no dedicated examples but you can see how I used this in LibFX.

Contents [hide]

  • Setup
    • Get JUnit
    • Get Guava
    • Write Some Boilerplate
  • Test Your Implementations
    • Generator For Elements And The Unit Under Test
    • Test Suite Builder
      • Features
      • Suppressing Tests
      • Setup & Teardown
    • Available Test Suites
  • Reflection
  • Share & Follow

Setup

For this to work we need JUnit, the Guava-Testlib and a little boilerplate code.

Get JUnit

In case you’re not already using JUnit in your project, get it here. If you use Maven or Gradle:

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
	<scope>test</scope>
</dependency>
testCompile 'junit:junit:4.12'

Get Guava

What we actually need is not Guava itself but the Guava-Testlib. You can download it from the central repository, which also contains the dependency information for different managers.

For your convenience:

<dependency>
	<groupId>com.google.guava</groupId>
	<artifactId>guava-testlib</artifactId>
	<version>18.0</version>
	<scope>test</scope>
</dependency>
testCompile 'com.google.guava:guava-testlib:18.0'

Write Some Boilerplate

Assume you want to write a MySet and the corresponding MySetTest.

Doing this the JUnit-3.8.x-way, create a method publicstaticTest suite();. JUnit looks for this method and uses it to identify all tests which it will run for that class. Inside that method create a TestSuite and add the tests we’re going to write further down:

public class MySetTest {

	public static Test suite() {
		return new MySetTest().allTests();
	}

	public Test allTests() {
		TestSuite suite =
			new TestSuite("package.name.of.MySetTest");
		suite.addTest(testForOneToWayUseMySet());
		suite.addTest(testForAnotherWayToUseMySet());
		return suite;
	}
	
}

(I did not try to do this with JUnit 4’s annotations. If you did, ping me and I will include it here.)

With this boilerplate in place you can run this class with JUnit, e.g. from inside your IDE or on your CI server.

Test Your Implementations

Now that that’s done we can start actually creating tests for our implementations. Or, more precisely, tell Guava how to do that for us. This is a two part process: one creates a generator for the elements in the collection and the unit under test, the other uses one of Guava’s test suite builders to create a comprehensive set of tests tailored to the implementation.

We will continue to test an implementation of Set. Below we will see for what other interfaces test suites are available.

Generator For Elements And The Unit Under Test

The test suite builder requires you to give it a possibility to create the sample elements in the collection and instantiate your collection. To do this you have to implement the TestSetGenerator<E> (where E is the type of the elements).

This is straight forward with order(List<E>) being the only method which may require some thought. Note that contrary to the documentation the current versoin of the testlib (18.0) does call this method even when CollectionFeature.KNOWN_ORDER is not reported (see below for details about features). In my case it suffices to return the insertion order.

Test Suite Builder

Now this is were the real magic happens. You take your generator from above, pass it to the correct test suite builder, specify which features your collection has and it will create a tailored and comprehensive suite of tests:

public Test testForOneToWayUseMySet() {
	return SetTestSuiteBuilder
			.using(new MySetGenerator())
			.named("one way to use MySet")
			.withFeatures(
					CollectionSize.ANY,
					CollectionFeature.ALLOWS_NULL_VALUES,
					CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
					CollectionFeature.SUPPORTS_ADD,
					CollectionFeature.SUPPORTS_ITERATOR_REMOVE,
					CollectionFeature.SUPPORTS_REMOVE,
			)
			.createTestSuite();
}

Features

It is important to specify the correct features. Take a look at the two enums CollectionSize and CollectionFeatures to see which possibilities exist to describe your collection’s behavior.

Note that the created tests verify the features both ways! E.g. if ALLOWS_NULL_VALUES is left out, the builder will generate tests which verify that adding null to the collection throws a NullPointerException.

Suppressing Tests

By calling suppressing on the builder, you can specify test methods which will not be run. It seems to exist as a last resort when the features do not suffice to precisely specify the behavior. I did not use it.

Setup & Teardown

If you have to run code before or after each test, you can hand it as a Runnable to withSetUp or withTearDown, respectively (can both be called on the builder).

Available Test Suites

Of course you can generate tests suites for other interfaces as well. A first glance yields these possibilities:

Java’s collections:

  • Collection
  • Iterator
  • List
  • Map
  • NavigableMap
  • NavigableSet
  • Queue
  • Set
  • SortedMap
  • SortedSet

Guava’s collections:

  • BiMap
  • ListMultimap
  • Multimap
  • Multiset
  • SetMultimap
  • SortedMultiset
  • SortedSetMultimap

A type search for *TestSuiteBuilder (note the wildcard) yields some other builders. I did not investigate them but it is possible that those can be used to create tests for other cases.

In order to use these, simply implement the according Test...Generator and hand it to the respective ...TestSuiteBuilder.

Reflection

We have seen how to test collection implementations with Guava’s Testlib: how to include it and JUnit in our project, what boilerplate we need to make it run and an overview over the generator and test suite builder. The latter is where all the magic happens as it creates comprehensive tests, tailored to our description of our implementation and its features.

Testing Implementation Google Guava Test suite

Published at DZone with permission of Nicolai Parlog, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Micro Frontends on Monorepo With Remote State Management
  • CDNs: Speed Up Performance by Reducing Latency
  • How To Manage Vulnerabilities in Modern Cloud-Native Applications
  • Mainframe Development for the "No Mainframe" Generation

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: