{"id":126,"date":"2024-03-06T08:04:51","date_gmt":"2024-03-06T11:04:51","guid":{"rendered":"https:\/\/springmasteryhub.com\/?p=126"},"modified":"2024-03-06T08:04:51","modified_gmt":"2024-03-06T11:04:51","slug":"less-code-more-tests-exploring-parameterized-tests-in-junit","status":"publish","type":"post","link":"https:\/\/springmasteryhub.com\/?p=126","title":{"rendered":"Less Code, More Tests: Exploring Parameterized Tests in JUnit"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>Regarding writing tests, some developers are lazy writing fewer test scenarios as possible. And sometimes they can write no scenarios at all. Imagine being able to test many scenarios without writing much code. Isn\u2019t that great?<\/p>\n\n\n\n<p>A parameterized test lets you test many scenarios. You just send a list of parameters. This way, you don\u2019t need to write many test methods.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understanding Parameterized Tests: A Key Tool for Efficient Testing<\/h2>\n\n\n\n<p>Normally our test methods don\u2019t receive any parameters at all. Because we won\u2019t call them directly, JUnit calls them for us when we run the tests. With parameterized tests, you can use a list of parameters in your test.<\/p>\n\n\n\n<p>JUnit will iterate through that list calling our test method for each element in it.<\/p>\n\n\n\n<p>That\u2019s the beauty of this feature. You can increase your test scenarios by only growing the parameter list. No need to write another method to test each different value.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What source of inputs does it support?<\/h2>\n\n\n\n<p>This feature lets you use parameters from various sources in your tests. Here are some examples:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A list of values<\/li>\n\n\n\n<li>Enums<\/li>\n\n\n\n<li>CSV format<\/li>\n\n\n\n<li>You can create a method that returns a list of arguments.<\/li>\n<\/ul>\n\n\n\n<p>And much more. You can even combine two sources. You can check all possible ways in the JUnit documentation. This can vary from version to version.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to use it?<\/h2>\n\n\n\n<p>So let\u2019s go to the fun part. I\u2019ll combine this with the <a href=\"https:\/\/springmasteryhub.com\/2023\/12\/23\/how-to-find-bugs-before-sending-it-to-production-using-boundary-testing-technique\/\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">boundary testing technique<\/a> I shared in another post to apply this. If you didn\u2019t read it, don\u2019t worry, I\u2019ll summarize it for you. It consists of testing the borders of your code where it\u2019s most likely that bugs arise. To apply this technique you can follow these steps:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Test the exact minimum valid value possible.<\/li>\n\n\n\n<li>Test the first invalid value. Which will be the minimum valid value minus one.<\/li>\n\n\n\n<li>The minimum valid value plus one.<\/li>\n\n\n\n<li>A valid value in the valid range.<\/li>\n\n\n\n<li>The maximum valid value in the range minus one.<\/li>\n\n\n\n<li>The exact maximum valid value.<\/li>\n\n\n\n<li>And the first invalid after the maximum. Which will be valid maximum plus one.<\/li>\n<\/ul>\n\n\n\n<p>Let\u2019s take this password validation as an example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic static boolean validatePassword(String password) {\n    if (password == null || password.length() &lt; 8 || password.length() &gt; 20) {\n        return false;\n    }\n    return true;\n}\n\n<\/pre><\/div>\n\n\n<p>We can break it down to identify the partitions, and what the boundaries will be:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>password == null\n<ul class=\"wp-block-list\">\n<li>For this partition, a null and a non-null string would be enough<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>password.length() \u2264 8\n<ul class=\"wp-block-list\">\n<li>For this partition:\n<ul class=\"wp-block-list\">\n<li>test a password that is 7 characters long. (minimum &#8211; 1, first invalid value)<\/li>\n\n\n\n<li>test a password that has a length that is exactly 8 characters. (exact minimum)<\/li>\n\n\n\n<li>and a test that has a length of 9 characters.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>password.length() &gt; 20:\n<ul class=\"wp-block-list\">\n<li>For this partition:\n<ul class=\"wp-block-list\">\n<li>test a password that is 19 characters long. (maximum &#8211; 1)<\/li>\n\n\n\n<li>test a password that has a length that is exactly 20 characters. (exact maximum)<\/li>\n\n\n\n<li>and another that is 21 characters long. (maximum + 1)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Now we can write a parameterized test to help simply achieve this. We started creating a source of data to test. Like said before it can be CSV, Method, Enum, etc. In this case, we\u2019re going to use the <code>MethodSource<\/code>.<\/p>\n\n\n\n<p>Now we create a method of arguments (input, and expected value) that will be passed to our test method:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic static Stream&lt;Arguments&gt; boundaries() {\n    return Stream.of(\n        Arguments.of(null, false), \/\/ null value\n        Arguments.of(&quot;1234567&quot;, false),  \/\/minimum - 1\n        Arguments.of(&quot;12345678&quot;, true), \/\/ exact minimum\n        Arguments.of(&quot;123456789&quot;, true), \/\/ minimum + 1\n        Arguments.of(&quot;123456789012345678&quot;, true), \/\/ maximum - 1\n        Arguments.of(&quot;1234567890123456789&quot;, true), \/\/ exact maximum\n        Arguments.of(&quot;123456789012345678901&quot;, false) \/\/ maximum + 1\n    );\n}\n\n<\/pre><\/div>\n\n\n<p>Then we create a simple <code>@ParametizedTest<\/code>that will exercise all the scenarios described above:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@ParameterizedTest\n@MethodSource(&quot;boundaries&quot;)\nvoid validatePassword(String password, boolean expected) {\n    assertEquals(expected, PasswordValidator.validatePassword(password));\n}\n\n<\/pre><\/div>\n\n\n<p>See, a straightforward test case, that will test all boundary scenarios of our code. To add more tests for this method, add a line of input and expected values in the boundaries source method. You won\u2019t need to create more test methods.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>In this post, you learned a way to write more tests without adding too much code to your tests. Parameterized tests easily add extra scenarios. This ensures everything is okay<\/p>\n\n\n\n<p>Now it\u2019s your turn, to look at your code, and see which places in your code you can start using some parameterized tests. Use this with boundary tests. Your code and tests will be more reliable.<\/p>\n\n\n\n<p>Don\u2019t forget to follow me on social media to be the first to read when my next article comes out!<\/p>\n\n\n\n<p><a href=\"https:\/\/twitter.com\/WillianFMoya\">Willian Moya (@WillianFMoya) \/ X (twitter.com)<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.linkedin.com\/in\/willianmoya\/\">Willian Ferreira Moya | LinkedIn<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Regarding writing tests, some developers are lazy writing fewer test scenarios as possible. And sometimes they can write no scenarios at all. Imagine being able to test many scenarios without writing much code. Isn\u2019t that great? A parameterized test lets you test many scenarios. You just send a list of parameters. This way, you [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":129,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[2,4],"tags":[13,18,27],"class_list":["post-126","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-pratices","category-junit","tag-java","tag-programming","tag-testing"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts\/126","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=126"}],"version-history":[{"count":0,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts\/126\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/"}],"wp:attachment":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=126"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=126"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=126"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}