{"id":872,"date":"2020-09-13T08:46:46","date_gmt":"2020-09-13T08:46:46","guid":{"rendered":"https:\/\/www.crccheck.com\/blog\/?p=872"},"modified":"2020-09-13T08:46:48","modified_gmt":"2020-09-13T08:46:48","slug":"code-review-organize-your-tests-for-your-sanity","status":"publish","type":"post","link":"https:\/\/www.crccheck.com\/blog\/code-review-organize-your-tests-for-your-sanity\/","title":{"rendered":"Code review: organize your tests for your sanity"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I really didn&#8217;t want to write this, but every good link about structuring unit tests is dead. And I don&#8217;t want to hype this too much, but learning to arrange my tests in a certain order was one of the biggest productivity gains in my career.<\/p>\n\n\n\n<pre class=\"wp-block-verse\"><span class=\"has-inline-color has-vivid-red-color\"><em>This is a \"Code review\" post. This is designed to be copy pasted into code reviews<\/em><\/span><\/pre>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">You should arrange your test into three distinct sections, <strong>AAA:<\/strong> Arrange, Act, and Assert. You&#8217;ll also see articles touting four sections called <strong>SEVT<\/strong>: Setup, Execute, Verify, and Teardown, but in practice, we never put teardown in the actual tests because then they would only run if the test succeeds.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Arrange<\/strong> \u00e2\u20ac\u201c Set up the conditions for the test<\/li><li><strong>Act<\/strong> \u00e2\u20ac\u201c Execute the code<\/li><li><strong>Assert<\/strong> \u00e2\u20ac\u201c Verify your assumptions<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If you arrange all your tests like this, then every test will looks familiar even if you&#8217;ve never seen before, which mean you&#8217;ll be able to understand unfamiliar code much faster.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Make the sections obvious<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The easiest way to convey the three sections is to group the lines into the three sections separated by a blank line. If your test only has two or three lines, you probably don&#8217;t need the blank lines, and if for some reason your test is so long that it can&#8217;t fit on one screen, you<em> might<\/em> need comments to label the sections. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bad:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>expected = {...}\nuser = {}\n\nstubs...\n\nresult = foo(user)\nassert result == expected<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Better:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>user = {}\nstubs...\n\nresult = foo(user)\n\nexpected = {...}\nassert result == expected<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Your first test<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">I like to make my first test case either a trivial case (for pure functions) or the happy path (for request\/response). And I try to get these tests to have zero lines of setup.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bad:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>test(\"knight is worthy\")\n  user =\n    id: 1234\n    email: lancelot@camelot.silly.place\n    name: Sir Lancelot of Camelot\n    favorite_color: yellow  # This should be blue\n    quest: to seek the Holy Grail\n    ...a million other things\n\n  assert user.is_worthy()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Good:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>setUp()\n  user =\n    id: 1234\n    email: lancelot@camelot.silly.place\n    name: Sir Lancelot of Camelot\n    favorite_color: yellow  # This should be blue\n    quest: to seek the Holy Grail\n    ...a million other things\n\ntest(\"knight is worthy\")\n  assert user.is_worthy()<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Copy paste your tests<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">New test scenarios should be a variation of an existing test; every test starts as a copy paste. This repetition makes your code easy for to read because everything looks familiar! Let&#8217;s say we need to check if the user is no longer worthy now.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One consequence is you&#8217;ll often end up with extra assertions. I usually keep them, but it&#8217;s a balance. If you&#8217;re not sure, I ask myself: &#8220;is this assertion relevant to the test name?&#8221; <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Make the &#8220;arrange&#8221; section as small as possible<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Minimize the setup for all your tests. The higher up you can get the &#8220;act&#8221; section of your test, the more readable your tests will be. Remember that the &#8220;arrange&#8221;\/setup section is boilerplate, and we hate boilerplate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>User<\/code> object may require twelve things, but your arrange section should have none of them. Take advantage of fixtures, <code>before<\/code> blocks, factories; whatever tools you have at your disposal.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bad:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>user =\n  id: 1234\n  email: lancelot@camelot.silly.place\n  name: Sir Lancelot of Camelot\n  favorite_color: yellow\n  quest: to seek the Holy Grail\n  ...a million other things\n\nassert user.is_worthy() == false<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Good:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>user.favorite_color = blue\n\nassert user.is_worthy() == false<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">In the &#8220;bad&#8221; example, it&#8217;s not clear why this user fails the worthiness test. The reader is expected to compare it to a good example or to know the data. On top of that, it&#8217;s many lines before we actually get past the boilerplate. In the &#8220;good&#8221; example, it&#8217;s clear that the user has the wrong color.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Places this doesn&#8217;t work<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">You&#8217;ll be able to split up tests into these sections almost every time, but there are some common exceptions:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><strong>Events<\/strong>, when you need to set up assertions <code>.on('end', () =&gt; { assert ... }<\/code> as part of the test setup<\/li><li><strong>Catching exceptions<\/strong>, you&#8217;ll be able to arrange in AAA order, but you won&#8217;t be able to add line breaks.<\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"><br>Better articles about this subject:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/web.archive.org\/web\/20170625115645\/http:\/\/www.agile-code.com\/blog\/the-anatomy-of-a-unit-test\/\">http:\/\/www.agile-code.com\/blog\/the-anatomy-of-a-unit-test\/<\/a> (Wayback version)<\/li><li><a href=\"https:\/\/giang-pham.net\/2019\/01\/07\/patterns-in-constructing-unit-tests\/\">https:\/\/giang-pham.net\/2019\/01\/07\/patterns-in-constructing-unit-tests\/<\/a> (link is broken)<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I really didn&#8217;t want to write this, but every good link about structuring unit tests is dead. And I don&#8217;t want to hype this too much, but learning to arrange my tests in a certain order was one of the biggest productivity gains in my career. You should arrange your test into three distinct sections,&hellip;<\/p>\n <a href=\"https:\/\/www.crccheck.com\/blog\/code-review-organize-your-tests-for-your-sanity\/\" title=\"Code review: organize your tests for your sanity\" class=\"entry-more-link\"><span>Read More<\/span> <span class=\"screen-reader-text\">Code review: organize your tests for your sanity<\/span><\/a>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[1],"tags":[],"class_list":["entry","author-showmewhatyougot","post-872","post","type-post","status-publish","format-standard","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/872","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/comments?post=872"}],"version-history":[{"count":6,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/872\/revisions"}],"predecessor-version":[{"id":883,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/posts\/872\/revisions\/883"}],"wp:attachment":[{"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/media?parent=872"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/categories?post=872"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.crccheck.com\/blog\/wp-json\/wp\/v2\/tags?post=872"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}