{"id":1106,"date":"2005-09-23T14:16:33","date_gmt":"2005-09-23T18:16:33","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/2005\/09\/23\/unit-testing\/"},"modified":"2005-09-23T14:37:02","modified_gmt":"2005-09-23T18:37:02","slug":"unit-testing","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2005\/09\/23\/unit-testing\/","title":{"rendered":"Unit Testing"},"content":{"rendered":"<p>\r\n<a\r\nhref=\"http:\/\/wilshipley.com\/blog\/2005\/09\/unit-testing-is-teh-suck-urr.html\">\r\nWil Shipley<\/a>&rsquo;s heart is in the right place. It&rsquo;s obvious that he\r\ncares about quality, and his experience and common sense rightly make\r\nhim skeptical of process. But I think he&rsquo;s absolutely wrong about unit\r\ntesting. In brief, I think he misunderstands what unit testing is (or\r\nshould be) and what it&rsquo;s useful for. He shoots down a stupid way of\r\ndoing testing, throws the baby out with the bathwater, and concludes\r\nthat it&rsquo;s better to write good code in the first place, do manual\r\ntesting (&ldquo;Try odd things. Whack keys.&rdquo;), and rely on beta testers.\r\n<\/p>\r\n\r\n<p>\r\nI don&rsquo;t deny that this approach has worked for him. He&rsquo;s written\r\na lot of code, people have generally been happy with the products,\r\nand they&rsquo;re not known for being buggy. But my hunch is that Wil&rsquo;s\r\nteams have gotten good results because they&rsquo;re unusually smart,\r\nexperienced, and hard-working. They&rsquo;ve succeeded in spite of their\r\ntesting philosophy. Wil makes a great case that manual testing\r\nand defensive programming are necessary, but I think most\r\nprogrammers would be more effective and efficient if they combined\r\nthese with extensive automated unit testing.\r\n<\/p>\r\n\r\n<p>\r\nNow, I&rsquo;ll be the first to say that by-the-book XP\/TDD goes overboard.\r\nIf you need a new class or method, I think it&rsquo;s a waste of time to\r\nwrite a test that simply checks for the existence of the class or\r\nmethod, then write a stub, then run the tests, and then then flip back\r\nand write the <em>real<\/em> tests. Perhaps that example is just for\r\npedagogical purposes and one isn&rsquo;t meant to do that in production code.\r\n<\/p>\r\n\r\n<p>\r\nI also think it&rsquo;s a waste of time to write tests for\r\n<em>everything<\/em>. Some parts of the code are so simple that they\r\ndon&rsquo;t need tests, though this applies less often than you might\r\nthink. Other times, it would take so much work to write a proper\r\ntest that it&rsquo;s better to punt and check that item manually. (I&rsquo;m\r\nthinking of user interface details that you&rsquo;d immediately notice\r\nwhen running the application, as well as more elaborate\r\nsituations\/interactions. In the latter case, write the test down in\r\nEnglish and make sure that you really do it manually before\r\nshipping.) Again, though, this applies less often than you might\r\nthink.\r\n<\/p>\r\n\r\n<p>\r\nMy overall point is that time is limited, so you should use it wisely. And this\r\nis why extensive unit testing is a big win. Yes, it&rsquo;s not possible for\r\nyour tests to cover all the pathways through the code, with all the\r\npossible inputs. And even if they could, it probably wouldn&rsquo;t be a good\r\nidea to spend your time writing tests to do that. This does\r\n<em>not<\/em> mean, however, that you should reject unit testing as\r\nimpractical and try to test everything manually. That&rsquo;s not a good use\r\nof time, either. In brief, proper unit testing saves time and improves\r\nquality because:\r\n<\/p>\r\n\r\n<ul>\r\n    <li>Most of your testing can be automated with little\r\n\t&ldquo;extra&rdquo; work, and the computer is both faster and more reliable\r\n\tthan you at executing the tests. You&rsquo;ll spend (maybe) a little\r\n\tmore time writing code, but much less time clicking around in\r\n\tyour application and using the debugger.<\/li>\r\n\r\n    <li>If you think it&rsquo;s hard to get good coverage writing unit tests,\r\n    imagine how much harder it would be if you&rsquo;re just doing manual\r\n    integrated system tests.<\/li>\r\n\r\n\t<li>Tests help you catch bugs earlier and isolate them more easily,\r\n\tso it&rsquo;s less expensive to fix them.<\/li>\r\n\r\n    <li>Tests make great documentation for other programmers (or\r\n    yourself next month).<\/li>\r\n\r\n\t<li>In general, code that&rsquo;s easier to test is better designed. If\r\n\tit&rsquo;s really hard to get your code into a test, there&rsquo;s probably\r\n\tsomething wrong with it. Writing tests helps you get the design right, and that saves you time.<\/li>\r\n\r\n\t<li>When (not if) your software has to evolve and change,\r\n\thaving tests will help guard against regressions. You don&rsquo;t want\r\n\tto waste time tracking down bugs that you introduced, nor do\r\n\tyou want to let your code ossify because you&rsquo;re afraid to risk \r\n\tbreaking anything.<\/li>\r\n<\/ul>\r\n\r\n<p>\r\nA lot of people seem to think that automated testing is only for\r\nframeworks, or for tools without graphical user interfaces and\r\ninteraction, or for academics, or for software that&rsquo;s directly\r\nresponsible for people&rsquo;s lives. Not true. I think unit tests are\r\nuseful in writing Mac applications, and even for testing large\r\nchunks of the user interface (i.e. checking that a table is showing\r\nthe right rows in the right order, that clicking a button has the\r\nright effect, that a certain sequence of actions causes a view to\r\nrefresh in the right way, etc.).\r\n<\/p>\r\n\r\n<p>\r\nThat said, your tests will not cover everything, or even close\r\nto everything. GUI software has many sources of input&mdash;all the\r\ndifferent user interface items, in addition to the disk, the\r\nnetwork, etc. It also has complex interactions with <em>huge<\/em>\r\nchunks of operating system and library code that you didn&rsquo;t write\r\nand don&rsquo;t have access to.\r\n<\/p>\r\n\r\n<p>\r\nSo, yes, you shouldn&rsquo;t believe that because you have unit tests\r\nyou don&rsquo;t have to do manual integration tests. I doubt anyone\r\nis in danger of thinking that. Wil says:<\/p>\r\n\r\n<blockquote cite=\"http:\/\/wilshipley.com\/blog\/2005\/09\/unit-testing-is-teh-suck-urr.html\">\r\n<p>\r\nTesting is hugely important. Much too important to trust to\r\nmachines. Test your program with actual users who have actual data,\r\nand you&rsquo;ll get actual results.\r\n<\/p>\r\n<\/blockquote>\r\n\r\n<p>\r\nAnd I doubt anyone would disagree with that. However, testing is\r\n<em>also<\/em> too important to trust to humans. This is one reason\r\nthat you need automated unit tests. The other is that it&rsquo;s not all\r\nabout how many bugs users will find in the binary that you ship. It\r\nalso matters how long it took you to create that binary, and how\r\neasily you&rsquo;ll be able to develop the next version. People who like\r\nautomated testing find that it helps them write better code more\r\nquickly. I believe it&rsquo;s at least as beneficial for small teams.\r\n<\/p>\r\n\r\n<p>\r\nDon&rsquo;t miss the comments from <a href=\"http:\/\/wilshipley.com\/blog\/2005\/09\/unit-testing-is-teh-suck-urr.html#c112746528878534489\">Chris Hanson<\/a>, \r\n<a href=\"http:\/\/wilshipley.com\/blog\/2005\/09\/unit-testing-is-teh-suck-urr.html#c112748074335711885\">Marcel Weiher<\/a>, and others.\r\n<\/p>","protected":false},"excerpt":{"rendered":"<p>Wil Shipley&rsquo;s heart is in the right place. It&rsquo;s obvious that he cares about quality, and his experience and common sense rightly make him skeptical of process. But I think he&rsquo;s absolutely wrong about unit testing. In brief, I think he misunderstands what unit testing is (or should be) and what it&rsquo;s useful for. He [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-1106","post","type-post","status-publish","format-standard","hentry","category-programming-category"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1106","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=1106"}],"version-history":[{"count":0,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/1106\/revisions"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=1106"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=1106"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=1106"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}