{"id":109736,"date":"2021-02-12T18:14:53","date_gmt":"2021-02-12T17:14:53","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=109736"},"modified":"2021-05-21T18:41:01","modified_gmt":"2021-05-21T17:41:01","slug":"tutorial-spock-part-5-other-useful-tips","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2021\/02\/tutorial-spock-part-5-other-useful-tips","title":{"rendered":"Tutorial: Spock Part 5 &#8211; Other Useful Tips"},"content":{"rendered":"<p>We&#8217;ve now covered all the key features for creating and running tests with Spock. In Part 5, we finish up the <a href=\"http:\/\/spockframework.org\" target=\"_blank\" rel=\"noopener\">Spock<\/a> tutorial by looking at additional features that can help you to write short, descriptive, correct tests.<\/p>\n<p><iframe loading=\"lazy\" title=\"IntelliJ IDEA. Writing Tests with Spock (2021)\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/i5Qu3qYOfsM?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p>Tutorial: Spock<\/p>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2021\/01\/tutorial-spock-part-1-getting-started\/\">Part 1 &#8211; Getting Started<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2021\/02\/tutorial-spock-part-2-writing-tests\/\">Part 2 &#8211; Writing Tests<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2021\/02\/tutorial-spock-part-3-data-driven-testing\/\">Part 3 &#8211; Data Driven Testing<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2021\/02\/tutorial-spock-part-4-mocking-and-stubbing\/\">Part 4 &#8211; Mocking and Stubbing<\/a><\/li>\n<li><strong>Part 5 &#8211; Other Useful Tips<\/strong><\/li>\n<\/ul>\n<p><em>These blog posts cover the same material as the video. This provides an easy way for people to skim the content quickly if they prefer reading to watching, and to give the reader\/watcher code samples and links to additional information.<\/em><\/p>\n<p><!--more--><\/p>\n<h2>Helper Methods<\/h2>\n<p>When tests get big, we may want to split out large parts of code, or common code, into <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_helper_methods\" target=\"_blank\" rel=\"noopener\">helper methods<\/a>.<\/p>\n<p>Let&#8217;s say we have a test like this one.<\/p>\n<pre><code class=\"language-groovy\">def \"should use a helper method\"() {\n    given:\n    Renderer renderer = Mock()\n    def shapeFactory = new ShapeFactory(renderer)\n\n    when:\n    def polygon = shapeFactory.createDefaultPolygon()\n\n    then:\n    polygon.numberOfSides == 4\n    polygon.renderer == renderer\n    \/\/could check lots of different values on this polygon... \n}\n<\/code><\/pre>\n<p>It uses a <a href=\"https:\/\/github.com\/trishagee\/spock-testing-demo\/blob\/main\/src\/main\/java\/com\/mechanitis\/demo\/spock\/ShapeFactory.java\" target=\"_blank\" rel=\"noopener\">ShapeFactory<\/a> to create a default shape, and then we perform a number of checks to make sure this meets our expectations. You can imagine in real production code there might be a lot of values to check here.<\/p>\n<p>We may be tempted to move all these checks into their own method, especially if they&#8217;re going to be used by more than one test.<\/p>\n<pre><code class=\"language-groovy\">def \"should use a helper method\"() {\n    \/\/given... when... code\n\n    then:\n    checkDefaultShape(polygon, renderer)\n}\n\nprivate static void checkDefaultShape(Polygon polygon, Renderer renderer) {\n    polygon.numberOfSides == 4\n    polygon.renderer == renderer\n}<\/code><\/pre>\n<p>Run the test &#8211; it will pass. However, if we change the code so it should fail, we&#8217;ll see that it still passes. This helper method is not doing what we expect.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/01\/23.png\" alt=\"\" \/><\/p>\n<p>If we move our assertions into a helper method like this, it can no longer use the comparison operators to define the expected behaviour. Instead, we need to add the <code>assert<\/code> keyword specifically.<\/p>\n<pre><code class=\"language-groovy\">private static void checkDefaultShape(Polygon polygon, Renderer renderer) {\n    assert polygon.numberOfSides == 4\n    assert polygon.renderer == renderer\n}<\/code><\/pre>\n<p>Now if you run the test with incorrect values in <code>checkDefaultShape<\/code>, it should fail.<\/p>\n<p>There&#8217;s something else to be aware of too &#8211; it fails on the first assertion that fails, it never runs the assertion to check the polygon&#8217;s renderer. Later we&#8217;ll look at how to address that.<\/p>\n<p><em><a href=\"https:\/\/youtu.be\/i5Qu3qYOfsM?t=1715\" target=\"_blank\" rel=\"noopener\">View steps in video<\/a><\/em><\/p>\n<h2>with()<\/h2>\n<p>Let&#8217;s look at one approach to testing multiple properties of a single object. We can change the previous test to the following:<\/p>\n<pre><code class=\"language-groovy\"> def \"should use a helper method\"() {\n    given:\n    Renderer mockRenderer = Mock()\n    def shapeFactory = new ShapeFactory(mockRenderer)\n\n    when:\n    def polygon = shapeFactory.createDefaultPolygon()\n\n    then:\n    with(polygon) {\n        numberOfSides == 4\n        renderer == null\n    }\n}<\/code><\/pre>\n<p>We can use Spock&#8217;s <a href=\"https:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_using_with_for_expectations\" target=\"_blank\" rel=\"noopener\">with()<\/a> and a closure to check multiple values on the <code>polygon<\/code>. Inside this closure, we don&#8217;t have to say <code>polygon.<\/code>, we just assert the property matches the expected value.<\/p>\n<p>Note that in this test the mock Renderer created in the <code>given<\/code> block is called <code>mockRenderer<\/code> &#8211; this is so that it&#8217;s clear that the <code>renderer<\/code> in the <code>with<\/code> block is <code>polygon.renderer<\/code>, not the renderer from the test scope.<\/p>\n<p>Change the test so it fails, so we can see what this looks like:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2021\/01\/24.png\" alt=\"\" \/><\/p>\n<p>As with the helper method, if the first assertion fails, it doesn&#8217;t run any further assertions. This might be what you want from your test, if one value is wrong the whole test should fail regardless. However, sometimes we want to run all the assertions so we can see exactly what&#8217;s working and what&#8217;s not.<\/p>\n<p><em><a href=\"https:\/\/youtu.be\/i5Qu3qYOfsM?t=1834\" target=\"_blank\" rel=\"noopener\">View steps in video<\/a><\/em><\/p>\n<h2>verifyAll()<\/h2>\n<p>Let&#8217;s look at how to make sure all our assertions are run, regardless of whether one of them fails. Try this test (note that with string method names we can easily add quotes and other special characters).<\/p>\n<pre><code class=\"language-groovy\">def \"should demonstrate 'verifyAll'\"() {\n    given:\n    Renderer mockRenderer = Mock()\n    def shapeFactory = new ShapeFactory(mockRenderer)\n\n    when:\n    def polygon = shapeFactory.createDefaultPolygon()\n\n    then:\n    verifyAll(polygon) {\n        numberOfSides == 5\n        renderer == null\n    }\n}<\/code><\/pre>\n<p>We can replace our <code>with()<\/code> call with <a href=\"https:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_using_verifyall_to_assert_multiple_expectations_together\" target=\"_blank\" rel=\"noopener\">verifyAll()<\/a> instead. Run this (the code above should fail) and see what happens &#8211; not only does the number of sides assertion fail, but the check on the renderer also fails.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"\">org.opentest4j.MultipleFailuresError: Multiple Failures (2 failures)\n    org.spockframework.runtime.SpockComparisonFailure: Condition not satisfied:\n\nnumberOfSides == 5\n|             |\n4             false\n\n    org.spockframework.runtime.SpockComparisonFailure: Condition not satisfied:\n\nrenderer == null\n|        |\n|        false\nMock for type &#039;Renderer&#039; named &#039;mockRenderer&#039;<\/pre>\n<p>With <code>verifyAll<\/code>, all assertions are run and we can see which fail and which pass. This can help us when we&#8217;re iterating quickly between writing and fixing tests.<\/p>\n<p>Go back and fix this test:<\/p>\n<pre><code class=\"language-groovy\">then:\nverifyAll(polygon) {\n    numberOfSides == 4\n    renderer == mockRenderer\n}<\/code><\/pre>\n<p>(Note that this code differs slightly from the video, since using two variables called <code>renderer<\/code> made it really hard to see what was being tested)<\/p>\n<p><em><a href=\"https:\/\/youtu.be\/i5Qu3qYOfsM?t=1892\" target=\"_blank\" rel=\"noopener\">View steps in video<\/a><\/em><\/p>\n<h2>Setup and Teardown<\/h2>\n<p>If you&#8217;ve used other testing frameworks, the concept of test or specification class <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_comparison_to_junit\" target=\"_blank\" rel=\"noopener\">setup and tear down will be familiar<\/a>.<\/p>\n<p>Spock provides a <code>setup<\/code> method (we can use IntelliJ IDEA&#8217;s <a href=\"https:\/\/www.jetbrains.com\/help\/idea\/generating-code.html\" target=\"_blank\" rel=\"noopener\">code generation<\/a> to create this), which will be <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_fixture_methods\" target=\"_blank\" rel=\"noopener\">run before every individual test method<\/a> in this class. This can be used to set up a clean state at the start of each test.<\/p>\n<p>To clean up data or state at the end of every test method, you need a <code>cleanup<\/code> method. This is run after every individual test method.<\/p>\n<p>Use the <code>setupSpec<\/code> method to set up state once at the start of the specification, this is for things that should not change between individual test methods.<\/p>\n<p>Create a <code>cleanupSpec<\/code> method for final teardown code, this method will be called once at the very end of running all the tests.<\/p>\n<p>One final piece of useful information. The tests in this tutorial created the &#8220;objects under test&#8221; in the test methods themselves. However, you might also want to create your test instance as a field in the test. You can use the <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_subject\" target=\"_blank\" rel=\"noopener\">@Subject<\/a> annotation on the field to show that this is the object under test (you can use this annotation on local variables in the methods too). You can then reference this field in the test methods just as you&#8217;d expect in any Java or Groovy class.<\/p>\n<pre><code class=\"language-groovy\">@Subject\nprivate Polygon polygon = new Polygon(5)<\/code><\/pre>\n<p><em><a href=\"https:\/\/youtu.be\/i5Qu3qYOfsM?t=1946\" target=\"_blank\" rel=\"noopener\">View steps in video<\/a><\/em><\/p>\n<h2>Specifications as Documentation<\/h2>\n<p>Let&#8217;s take a look at <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#specifications_as_documentation\" target=\"_blank\" rel=\"noopener\">one last feature<\/a> to help document the requirements via tests.<\/p>\n<p>We&#8217;ve seen that Spock has a focus on readability and tests as documentation. The <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_subject\" target=\"_blank\" rel=\"noopener\">@Subject<\/a> annotation, the <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_blocks\" target=\"_blank\" rel=\"noopener\">labelled blocks<\/a>, <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_feature_methods\" target=\"_blank\" rel=\"noopener\">Strings as test method names<\/a> plus all you can do to <a href=\"https:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#_unrolled_iteration_names\" target=\"_blank\" rel=\"noopener\">customise these String values<\/a> all contribute to being able to use the automated tests as a documentation for what the system should do.<\/p>\n<p>We can also <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#specifications_as_documentation\" target=\"_blank\" rel=\"noopener\">add more information<\/a>, again for readability or documentation purposes, to the blocks in our tests.<\/p>\n<pre><code class=\"language-groovy\">def \"should be able to create a stub\"() {\n    given: \"a palette with red as the primary colour\"\n    Palette palette = Stub()\n    palette.getPrimaryColour() &gt;&gt; Colour.Red\n\n    and: \"a renderer initialised with the red palette\"\n    def renderer = new Renderer(palette)\n\n    expect: \"the renderer to use the palette's primary colour as foreground\"\n    renderer.getForegroundColour() == Colour.Red\n}<\/code><\/pre>\n<p>We can add a String next to the label to give a more detailed description of the block. If we want to split a block into further blocks, for readability or to add documentation, we can use the <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html#specifications_as_documentation\" target=\"_blank\" rel=\"noopener\">and:<\/a> label, this is just to let us break things up further.<\/p>\n<p>The text is available to the Spock runtime, so these messages can be used in messages and reports.<\/p>\n<p><em><a href=\"https:\/\/youtu.be\/i5Qu3qYOfsM?t=2057\" target=\"_blank\" rel=\"noopener\">View steps in video<\/a><\/em><\/p>\n<h2>Conclusion<\/h2>\n<p>Spock is powerful and has even more to offer than we&#8217;ve looked at here.<\/p>\n<p>Believe it or not we&#8217;ve only touched the surface of what Spock can offer. We&#8217;ve seen the basics of a test, we&#8217;ve seen how to use labels to define tests, we&#8217;ve seen the power of data driven testing, and we&#8217;ve covered a range of tips and tricks for writing correct and readable tests.<\/p>\n<p>If you want to find out more about Spock, take a look at <a href=\"http:\/\/spockframework.org\/spock\/docs\/2.0\/all_in_one.html\" target=\"_blank\" rel=\"noopener\">the excellent reference documentation<\/a>. There&#8217;s also a <a href=\"http:\/\/spockframework.org\/spock\/docs\/1.0\/spock_primer.html\" target=\"_blank\" rel=\"noopener\">Spock Primer<\/a> which is a great place to start with Spock.<\/p>\n","protected":false},"author":360,"featured_media":109485,"comment_status":"closed","ping_status":"closed","template":"","categories":[4759,2347,126],"tags":[1130,1068,3178,6452,443],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/109736"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/users\/360"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/comments?post=109736"}],"version-history":[{"count":4,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/109736\/revisions"}],"predecessor-version":[{"id":144485,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/109736\/revisions\/144485"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media\/109485"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media?parent=109736"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/categories?post=109736"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/tags?post=109736"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/cross-post-tag?post=109736"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}