{"id":2845,"date":"2012-09-25T22:31:33","date_gmt":"2012-09-25T21:31:33","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=2845"},"modified":"2021-07-03T13:31:16","modified_gmt":"2021-07-03T12:31:16","slug":"google-guava-collection-test-suite","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2012\/09\/google-guava-collection-test-suite\/","title":{"rendered":"Google Guava Collection Test Suite"},"content":{"rendered":"<p>Did you even implement your own collections for some reason? Collections which implement the Java collection interfaces? Did you ever wonder if there is test suite for collections, which tests the specified collection-interface behavior? When your answer is yes to these questions then you should check out the Google Guava Testlib.<\/p>\n<div id=\"attachment_2880\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/testing-things.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2880\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/testing-things-300x255.png\" alt=\"Testing Collections, Ahoi\" title=\"testing-things\" class=\"size-medium wp-image-2880\" width=\"300\" height=\"255\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/testing-things-300x255.png 300w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/testing-things.png 700w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-2880\" class=\"wp-caption-text\">Testing Collections, Ahoi<\/p><\/div>\n<p>The Google Guava Testlib brings a whole test suite which tests the behavior of Set, List and Map implementations. You can specify which features your collections support and then profit from the hundreds of tests Google has written for you.<\/p>\n<h2>Getting Started<\/h2>\n<p>First we need to get the library. The easiest way to get it is with Maven:<br \/>\n<script src=\"https:\/\/gist.github.com\/3571743.js?file=grab-with-maven.xml\"><\/script><noscript><pre><code class=\"language-xml xml\">&lt;dependency&gt;\n\t&lt;groupId&gt;com.google.guava&lt;\/groupId&gt;\n\t&lt;artifactId&gt;guava-testlib&lt;\/artifactId&gt;\n\t&lt;version&gt;13.0&lt;\/version&gt;\n\t&lt;scope&gt;test&lt;\/scope&gt;\n&lt;\/dependency&gt;<\/code><\/pre><\/noscript><\/p>\n<p>After that we can start to write a test suite. There are test-suite builders for this purpose, the most important ones are ListTestSuiteBuilder, SetTestSuiteBuilder and MapTestSuiteBuilder. These builder allow you to create a test-suite according to your needs.<br \/>\nFirst you specify the collection to be used and the test data with the using-method. Afterwards you can specify what features are implemented by your collection. Here&#8217;s an example:<\/p>\n<script src=\"https:\/\/gist.github.com\/3571743.js?file=MyListTest.java\"><\/script><noscript><pre><code class=\"language-java java\">private Test myListTestSuite() {\n\treturn ListTestSuiteBuilder.using(\n\t\t\/\/ This class is responsible for creating the collection\n\t\t\/\/ And providing data, which can be put into the collection\n\t\t\/\/ Here we use a abstract generator which will create strings\n\t\t\/\/ which will be put into the collection\n\t\tnew TestStringListGenerator(){\n\t\t\t@Override\n\t\t\tprotected List&lt;String&gt; create(String[] elements) {\n\t\t\t\t\/\/ Fill here your collection with the given elements\n\t\t\t\treturn new MyListImplementation&lt;String&gt;(elements);\n\t\t\t}\n\t\t})\n\t\t\/\/ The name of the test suite\n\t\t.named(&quot;My List Tests&quot;)\n\t\t\/\/ Here we give a hit what features our collection supports\n\t\t.withFeatures(ListFeature.GENERAL_PURPOSE,\n\t\t\t\t\t\tCollectionFeature.ALLOWS_NULL_VALUES,\n\t\t\t\t\t\tCollectionFeature.SERIALIZABLE,\n\t\t\t\t\t\tCollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,\n\t\t\t\t\t\tCollectionSize.ANY)\n\t\t.createTestSuite();\n}<\/code><\/pre><\/noscript>\n<p>Take a good look into the available constants in CollectionFeature, ListFeature and MapFeature for the features sets to test.<br \/>\nAnyway, BAAAMM! Now I&#8217;ve already a huge suite of test running, which cover a lot of dirty details. For example my implementation seems to have issues with the equals method of the returned sub-lists:<\/p>\n<div id=\"attachment_2871\" style=\"width: 646px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/oh-collection-failures.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2871\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/oh-collection-failures.png\" alt=\"Oh Oh\" title=\"oh-collection-failures\" class=\"size-full wp-image-2871\" width=\"636\" height=\"553\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/oh-collection-failures.png 636w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2012\/09\/oh-collection-failures-300x260.png 300w\" sizes=\"(max-width: 636px) 100vw, 636px\" \/><\/a><p id=\"caption-attachment-2871\" class=\"wp-caption-text\">Oh Oh<\/p><\/div>\n<h2>Setup\/Tear-Down, Suppressing Tests<\/h2>\n<p>Now the actual tests do run in already written test classes. So what if your collection needs some setup- \/ tear down code? For example I use the test-suite to test collections which are backed up by a database. That means I need a setup- \/ tear down phase.<br \/>\nThis can be done by providing a runnable for the setup and tear down:<\/p>\n<script src=\"https:\/\/gist.github.com\/3571743.js?file=SetupTeardown.java\"><\/script><noscript><pre><code class=\"language-java java\">return ListTestSuiteBuilder\n\t.using(new TestStringListGenerator(){\n\t\t@Override\n\t\tprotected List&lt;String&gt; create(String[] elements) {\n\t\t\treturn new MyListImplementation&lt;String&gt;(elements);\n\t\t}\n\t})\n\t.named(&quot;My List Tests&quot;)\n\t.withFeatures(ListFeature.GENERAL_PURPOSE,\n\t\t\t\t\tCollectionFeature.ALLOWS_NULL_VALUES,\n\t\t\t\t\tCollectionFeature.SERIALIZABLE,\n\t\t\t\t\tCollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,\n\t\t\t\t\tCollectionSize.ANY)\n\t.withSetUp(new Runnable() {\n\t\t@Override\n\t\tpublic void run() {\n\t\t\t\/\/ some setup\n\t\t}\n\t})\n\t.withTearDown(new Runnable() {\n\t\t@Override\n\t\tpublic void run() {\n\t\t\t\/\/ some setup\n\t\t}\n\t})\n\t.createTestSuite();\n<\/code><\/pre><\/noscript>\n<p>You also can suppress very specific methods of the test suite. This is done by giving the methods which should be suppressed:<\/p>\n<script src=\"https:\/\/gist.github.com\/3571743.js?file=SuppressTest.java\"><\/script><noscript><pre><code class=\"language-java java\">\/\/ previous calls\n.suppressing(Arrays.asList(suppressMethod(ListSubListTester.class, &quot;testSubList_entireList&quot;)))\n.createTestSuite();\n\n\nprivate Method suppressMethod(Class testClass,\n\t\tString methodName) {\n\ttry {\n\t\treturn testClass.getMethod(methodName, new Class[0]);\n\t} catch (NoSuchMethodException e) {\n\t\tthrow new AssertionError(&quot;Could not find method to suppress &quot;, e);\n\t}\n}<\/code><\/pre><\/noscript>\n<h2>Your Own TestData<\/h2>\n<p>Perhaps your collection implementation can only hold very specialized elements. In that case you might need to generate the test-items yourself, which are added to the list. Instead of using the Google test data provider, you can use your own. Here&#8217;s an example, which tests the collection with a custom type:<\/p>\n<script src=\"https:\/\/gist.github.com\/3571743.js?file=SpecializedCollections.java\"><\/script><noscript><pre><code class=\"language-java java\">\n\/\/ Pass your test data provider to the using method\nListTestSuiteBuilder.using(new MyTestDataGenerator())\n\t. \/\/ continue as normal\n\t\n\t\n\/**\n * Own implementation of a test data generator.\n * First look if an existing one fits your needs\n *\/\nclass MyTestDataGenerator implements TestListGenerator&lt;MySpecialItem&gt; {\n\n    @Override\n    public SampleElements&lt;MySpecialItem&gt; samples() {\n        return new SampleElements&lt;MySpecialItem&gt;(\n                new MySpecialItem(&quot;1&quot;),\n                new MySpecialItem(&quot;2&quot;),\n                new MySpecialItem(&quot;3&quot;),\n                new MySpecialItem(&quot;4&quot;),\n                new MySpecialItem(&quot;5&quot;)\n\n        );\n    }\n\n    @Override\n    public List&lt;MySpecialItem&gt; create(Object... elementsAsObjects) {\n        \/\/ Put the elements in the given array\n        \/\/ into the collection.\n        MySpecialItem[] castedElements = new MySpecialItem[elementsAsObjects.length];\n        int i = 0;\n        for (Object elementAsObject : elementsAsObjects) {\n            castedElements[i++] = (MySpecialItem) elementAsObject;\n        }\n        return new MyListImplementation&lt;MySpecialItem&gt;((MySpecialItem[])castedElements);\n    }\n\n    @Override\n    public MySpecialItem[] createArray(int length) {\n        \/\/ Just create an array of the element type with the given length\n        return new MySpecialItem[length];\n    }\n\n    @Override\n    public Iterable&lt;MySpecialItem&gt; order(List&lt;MySpecialItem&gt; insertionOrder) {\n        \/\/ In case your collection reorders elements,\n        \/\/ Then you should return the original order here\n        return insertionOrder;\n    }\n}\n\n\/\/ Let&#039;s assume our collection only can handle specialized items\nclass MySpecialItem implements Serializable{\n    private final String data;\n\n    MySpecialItem(String data) {\n        this.data = data;\n    }\n\n    @Override\n    public String toString() {\n        return &quot;MySpecialItem{&quot; +\n                &quot;data=&#039;&quot; + data + &#039;\\&#039;&#039; +\n                &#039;}&#039;;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n\n        MySpecialItem that = (MySpecialItem) o;\n\n        if (data != null ? !data.equals(that.data) : that.data != null) return false;\n\n        return true;\n    }\n\n    @Override\n    public int hashCode() {\n        return data != null ? data.hashCode() : 0;\n    }\n}\n\n\t\n\t<\/code><\/pre><\/noscript>\n<h2>Other Types<\/h2>\n<p>Above I&#8217;ve shown examples for a List implementation. For Sets and Maps it works more or less exactly the same way. Instead of <strong>List<\/strong>SomeThingSomething the classes are called <strong>Set<\/strong>SomethingSomething or <strong>Map<\/strong>SomethingSomething. Otherwise the same principals apply.<\/p>\n<h2>Conclusion<\/h2>\n<p>If you ever implement your own Java collections, take a look at the Guava Test lib. It saves you a ton of work!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Did you even implement your own collections for some reason? Collections which implement the Java collection interfaces? Did you ever wonder if there is test suite for collections, which tests&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[268,15],"tags":[290,295,289],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/2845"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=2845"}],"version-history":[{"count":16,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/2845\/revisions"}],"predecessor-version":[{"id":3886,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/2845\/revisions\/3886"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=2845"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=2845"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=2845"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}