{"version":3,"sources":["webpack:///./src/assets/images/coverprofile.png","webpack:///./src/assets/images/coverprofile_schema.png","webpack:///./src/assets/images/strings_dir_tree.png","webpack:///./src/assets/images/testdatadir_archive_zip.png","webpack:///./src/assets/images/test_function_name.png","webpack:///./src/views/Chap19UnitTests.vue?a7e7","webpack:///src/views/Chap19UnitTests.vue","webpack:///./src/views/Chap19UnitTests.vue?9623","webpack:///./src/views/Chap19UnitTests.vue","webpack:///./src/assets/images/coverprofile_count.png"],"names":["module","exports","render","_vm","this","_h","$createElement","_c","_self","staticClass","attrs","_v","directives","name","rawName","pre","staticRenderFns","components","FeedbackInvite","BuyCopyInvite","NewsletterInput","ChapterHeading","ChapterBibliography","TOCChapter","NavBar","BIconLink45deg","Footer","mounted","i","mathElements","length","tagName","window","displayMode","throwOnError","macros","fleqn","created","data","publicPath","metaInfo","title","htmlAttrs","lang","meta","charset","content","property","link","rel","href","component"],"mappings":"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","file":"js/chunk-658f3442.cee6b384.js","sourcesContent":["module.exports = __webpack_public_path__ + \"img/coverprofile.7c88947f.png\";","module.exports = __webpack_public_path__ + \"img/coverprofile_schema.c82c76f2.png\";","module.exports = __webpack_public_path__ + \"img/strings_dir_tree.ba3b2379.png\";","module.exports = __webpack_public_path__ + \"img/testdatadir_archive_zip.f27c11a0.png\";","module.exports = __webpack_public_path__ + \"img/test_function_name.05c7f228.png\";","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('NavBar'),_c('div',{staticClass:\"container-fluid\"},[_c('b-row',[_c('TOCChapter',{attrs:{\"chapter-id\":\"Chap19UnitTests\"}}),_c('b-col'),_c('b-col',{attrs:{\"role\":\"main\",\"md\":\"6\"}},[_c('ChapterHeading',{attrs:{\"chapter-title\":\"Chapter 19: Unit Tests\",\"image-name\":\"tests.jpg\",\"image-alt\":\"Unit Tests\"}}),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"what-will-you-learn-in-this-chapter\"}}),_c('h1',{attrs:{\"data-number\":\"1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"1\")]),_vm._v(\" What will you learn in this chapter? \"),_c('a',{attrs:{\"href\":\"#what-will-you-learn-in-this-chapter\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ul',[_c('li',[_c('p',[_vm._v(\"What are unit tests\")])]),_c('li',[_c('p',[_vm._v(\"How to write unit tests\")])]),_c('li',[_c('p',[_vm._v(\"How to test your Go program with the go tool\")])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"technical-concepts-covered\"}}),_c('h2',{attrs:{\"data-number\":\"1.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"1.1\")]),_vm._v(\" Technical concepts covered \"),_c('a',{attrs:{\"href\":\"#technical-concepts-covered\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ul',[_c('li',[_c('p',[_vm._v(\"Unit tests\")])]),_c('li',[_c('p',[_vm._v(\"Test case\")])]),_c('li',[_c('p',[_vm._v(\"Test function\")])]),_c('li',[_c('p',[_vm._v(\"Assertion\")])]),_c('li',[_c('p',[_vm._v(\"Test-Driven Development (TDD)\")])]),_c('li',[_c('p',[_vm._v(\"Code coverage\")])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"introduction\"}}),_c('h1',{attrs:{\"data-number\":\"2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"2\")]),_vm._v(\" Introduction \"),_c('a',{attrs:{\"href\":\"#introduction\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Here is a function :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// compute and return the total price of a hotel booking\\n// all amounts in input must be multiplied by 100. Currency is Dollar\\n// the amount returned must be divided by 100. (ex: 10132 => 101.32 $)\\nfunc totalPrice(nights, rate, cityTax uint) uint {\\n return nights*rate + cityTax\\n}\")])]),_c('p',[_vm._v(\"This function computes the price of a booking. It seems right, no? How to be sure that the amount returned is correct? We can run it with some data as argument and check its result :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"package main\\n\\nimport \\\"fmt\\\"\\n\\nfunc main() {\\n price := totalPrice(3, 10000, 132)\\n fmt.Println(price)\\n}\")])]),_c('p',[_vm._v(\"The program outputs \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"30132\")])]),_vm._v(\" which is equivalent to \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"301.32$\")])]),_vm._v(\". We should divide it by 100 to get an amount in dollars.\")]),_c('p',[_vm._v(\"Is it correct? Let’s compute it by hand. The total price of a room is the number of nights multiplied by the rate plus the city tax : \"),_c('span',{staticClass:\"math inline\"},[_vm._v(\"3\\\\times(100+1,32)=3\\\\times101.32=303.96\")]),_vm._v(\". Have you spotted the bug in the function?\")]),_c('p',[_vm._v(\"This statement :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"return nights*rate + cityTax\")])]),_c('p',[_vm._v(\"It should be replaced by this one :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"return nights * (rate + cityTax)\")])]),_c('p',[_vm._v(\"This way, the function returns the right answer. What if our program checks it directly?\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/intro/main.go\\npackage main\\n\\nimport \\\"fmt\\\"\\n\\n//...\\n\\nfunc main() {\\n price := totalPrice(3, 10000, 132)\\n if price == 30396 {\\n fmt.Println(\\\"function works\\\")\\n } else {\\n fmt.Println(\\\"function is buggy\\\")\\n }\\n}\")])]),_c('p',[_vm._v(\"The program itself will check if the function implementation is correct. No surprises it outputs the \"),_c('strong',[_vm._v(\"function works\")]),_vm._v(\" ! This \"),_c('strong',[_vm._v(\"program is a unit test!\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"what-is-unit-testing\"}}),_c('h1',{attrs:{\"data-number\":\"3\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"3\")]),_vm._v(\" What is unit testing? \"),_c('a',{attrs:{\"href\":\"#what-is-unit-testing\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"If we take the definition from the IEEE (Institute for Electrical and Electronics Engineers) \"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"institute1990ieee\",\"href\":\"#institute1990ieee\"}},[_vm._v(\"[@institute1990ieee]\")]),_vm._v(\" unit testing is the “testing of individual hardware or software units or groups of related units”.\")],1),_c('p',[_vm._v(\"We take individual parts of the system to test them. In other words, we check that individual parts of the system work. The whole system is not tested.\")]),_c('p',[_vm._v(\"The unit test is created and run by the developer of the code. With this tool, we can check that our methods and functions run as expected. Unit tests are focused exclusively on checking that those small programming units are working.\")]),_c('p',[_vm._v(\"Some developers will argue that unit tests are useless. Often they say that when they develop their code, they are testing permanently that the system work. For instance, a web developer that has to create a website will often have two screens, the one with the source code and the one with the program running. When he wants to implement something new, he will start with the code and checks if it works.\")]),_c('p',[_vm._v(\"This process is purely manual and depends on the experience of the developer on the system. A newly hired might not detect errors and breaking changes. What if we can run those tests automatically? Imagine that you can run those tests each time you build your Go program! Or even better, you could run them each time you make a change to a package!\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"what-is-a-test-case-a-test-set-an-assertion\"}}),_c('BuyCopyInvite'),_c('h1',{attrs:{\"data-number\":\"4\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"4\")]),_vm._v(\" What is a test case, a test set, an assertion? \"),_c('a',{attrs:{\"href\":\"#what-is-a-test-case-a-test-set-an-assertion\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"A single unit test is called a test case. A group of test cases is called a test set (or test suite).\")]),_c('p',[_vm._v(\"To better understand what a test case is, let’s take an example. Imagine that you have developed a function to capitalize a string. We will build a test case to check it.\")]),_c('p',[_vm._v(\"Our test case will be composed of :\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"A \"),_c('strong',[_vm._v(\"test input\")]),_vm._v(\". For instance : “coffee”\")])]),_c('li',[_c('p',[_vm._v(\"An \"),_c('strong',[_vm._v(\"expected output\")]),_vm._v(\" : In our example, it will be the string “COFFEE”\")])]),_c('li',[_c('p',[_vm._v(\"The \"),_c('strong',[_vm._v(\"actual output\")]),_vm._v(\" of our function under test\")])]),_c('li',[_c('p',[_vm._v(\"A way to \"),_c('strong',[_vm._v(\"assert\")]),_vm._v(\" that the actual returned value of our function is the one that is expected. We could use string comparison features of Go to check that the two strings are equal. We can also use a Go package to do it. This part of the unit test is called the \"),_c('strong',[_vm._v(\"assertion\")])])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"why-unit-testing-your-code\"}}),_c('h1',{attrs:{\"data-number\":\"5\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"5\")]),_vm._v(\" Why Unit testing your code? \"),_c('a',{attrs:{\"href\":\"#why-unit-testing-your-code\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"In this section, I will go through some reasons extracted from an IEEE survey about unit testing \"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"runeson2006survey\",\"href\":\"#runeson2006survey\"}},[_vm._v(\"[@runeson2006survey]\")]),_vm._v(\":\")],1),_c('ul',[_c('li',[_c('p',[_vm._v(\"Unit tests will control that functions and methods work as expected. Without unit tests, developers test their functionality during the development phase. Those tests are not \"),_c('strong',[_vm._v(\"reproducible\")]),_vm._v(\". After the development of the feature, those manual tests are no longer run.\")])]),_c('li',[_c('p',[_vm._v(\"If they write their tests into the project sources, they can run those tests later. They \"),_c('strong',[_vm._v(\"protect the project against nasty regressions\")]),_vm._v(\" (development of new features breaks something in the code of another one).\")])]),_c('li',[_c('p',[_vm._v(\"The presence of unit test can be \"),_c('strong',[_vm._v(\"a customer requirement\")]),_vm._v(\". It seems to be pretty rare, but some specifications include test coverage requirements.\")])]),_c('li',[_c('p',[_vm._v(\"A \"),_c('strong',[_vm._v(\"better focus on API design\")]),_vm._v(\" is also generally observed when developers write unit tests. You have to call the function you are developing; as a consequence you can see improvements. This focus is even bigger if you use the TDD method.\")])]),_c('li',[_c('p',[_vm._v(\"Unit tests also serve as \"),_c('strong',[_vm._v(\"code documentation\")]),_vm._v(\". Users that want to know how to call a specific function can take a look at the unit test to get their answer immediately.\")])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"where-to-put-the-tests\"}}),_c('h1',{attrs:{\"data-number\":\"6\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"6\")]),_vm._v(\" Where to put the tests? \"),_c('a',{attrs:{\"href\":\"#where-to-put-the-tests\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Several languages are putting the tests into a specific directory, often called \"),_c('strong',[_vm._v(\"tests.\")]),_vm._v(\" In Go unit tests are living next to the code they test. Tests are part of the package under test.\")]),_c('p',[_vm._v(\"Here is the list of files from the directory src/strings :\")]),_c('figure',[_c('b-img',{staticClass:\"img-book\",attrs:{\"src\":require('@/assets/images/strings_dir_tree.png'),\"alt\":\"strings package directory\",\"fluid\":\"\",\"thumbnail\":\"\"}}),_c('figcaption',{attrs:{\"aria-hidden\":\"true\"}},[_vm._v(\"strings package directory\")])],1),_c('p',[_vm._v(\"You can see that there is a naming pattern: there is a file named \"),_c('strong',[_vm._v(\"xxx_test.go\")]),_vm._v(\" for each file named \"),_c('strong',[_vm._v(\"xxx.go.\")])]),_c('p',[_vm._v(\"When you build your program, the file named xxx_test.go will be ignored by the compiler.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"how-to-write-a-basic-unit-test\"}}),_c('h1',{attrs:{\"data-number\":\"7\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"7\")]),_vm._v(\" How to write a basic unit test \"),_c('a',{attrs:{\"href\":\"#how-to-write-a-basic-unit-test\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Let’s write our very first unit test together. We will test the package foo :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/basic/foo/foo.go\\npackage foo\\n\\nimport \\\"fmt\\\"\\n\\nfunc Foo() string {\\n return fmt.Sprintf(\\\"Foo\\\")\\n}\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"the-test-file\"}}),_c('h4',{attrs:{\"data-number\":\"7.0.0.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"7.0.0.1\")]),_vm._v(\" The test file \"),_c('a',{attrs:{\"href\":\"#the-test-file\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Let’s create a file \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"foo_test.go\")])]),_vm._v(\" in the same folder as \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"foo.go\")])]),_vm._v(\" :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/basic/foo/foo_test.go \\npackage foo\\n\\nimport \\\"testing\\\"\\n\\nfunc TestFoo(t *testing.T) {\\n\\n}\")])]),_c('p',[_vm._v(\"You can see that this source file is part of the \"),_c('strong',[_vm._v(\"foo\")]),_vm._v(\" package. We have imported the package testing from the standard library (that we will use later).\")]),_c('p',[_vm._v(\"A single function is defined: TestFoo. This function takes as input a pointer to testing.T (*testing.T).\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"naming-of-a-test-case\"}}),_c('h4',{attrs:{\"data-number\":\"7.0.0.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"7.0.0.2\")]),_vm._v(\" Naming of a test case \"),_c('a',{attrs:{\"href\":\"#naming-of-a-test-case\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"A test function should be named following the same convention :\")]),_c('figure',[_c('b-img',{staticClass:\"img-book\",attrs:{\"src\":require('@/assets/images/test_function_name.png'),\"alt\":\"Test function signature\",\"fluid\":\"\",\"thumbnail\":\"\"}}),_c('figcaption',{attrs:{\"aria-hidden\":\"true\"}},[_vm._v(\"Test function signature\")])],1),_c('ul',[_c('li',[_c('p',[_vm._v(\"The first part of the test function name is the word Test. It is fixed. It’s always \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"\\\"Test\\\"\")])])])]),_c('li',[_c('p',[_vm._v(\"The second part is often the name of the function you want to test. It must start with a capital letter.\")])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"the-contents-of-a-test-case\"}}),_c('h4',{attrs:{\"data-number\":\"7.0.0.3\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"7.0.0.3\")]),_vm._v(\" The contents of a test case \"),_c('a',{attrs:{\"href\":\"#the-contents-of-a-test-case\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Here is an example of the function \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Foo\")])]),_vm._v(\". The function has no argument, but it always returns the string “Foo”. If we want to unit test it, we will assert (verify) that the return of the function is \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"\\\"Foo\\\"\")])]),_vm._v(\":\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/basic/foo/foo_test.go\\npackage foo\\n\\nimport \\\"testing\\\"\\n\\nfunc TestFoo(t *testing.T) {\\n expected := \\\"Foo\\\"\\n actual := Foo()\\n if expected != actual {\\n t.Errorf(\\\"Expected %s do not match actual %s\\\", expected, actual)\\n }\\n}\")])]),_c('p',[_vm._v(\"We first define a variable \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"expected\")])]),_vm._v(\" that holds our expected result. Then we define the variable \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"actual\")])]),_vm._v(\" that will hold the actual return value of the function \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Foo\")])]),_vm._v(\" from the package \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"foo\")])]),_vm._v(\".\")]),_c('p',[_vm._v(\"Please remember those two terms : \"),_c('strong',[_vm._v(\"actual\")]),_vm._v(\" and \"),_c('strong',[_vm._v(\"expected\")]),_vm._v(\". They are classic variables names in the context of testing.\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"The \"),_c('strong',[_vm._v(\"expected\")]),_vm._v(\" variable is the result as expected by the user.\")])]),_c('li',[_c('p',[_vm._v(\"The \"),_c('strong',[_vm._v(\"actual\")]),_vm._v(\" variable holds the execution result of the unit of the code we want to test.\")])])]),_c('p',[_vm._v(\"Then the test continues with an \"),_c('strong',[_vm._v(\"assertion\")]),_vm._v(\". We test the equality between the actual value and the expected one. If that’s not the case, we make the test fail by using a t.Errorf method (that is defined on the type struct \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"T\")])]),_vm._v(\" from the package \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"testing\")])]),_vm._v(\") :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"t.Errorf(\\\"Expected %s do not match actual %s\\\", expected, actual)\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"about-success-and-errors\"}}),_c('h4',{attrs:{\"data-number\":\"7.0.0.4\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"7.0.0.4\")]),_vm._v(\" About Success and Errors \"),_c('a',{attrs:{\"href\":\"#about-success-and-errors\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"There is no method defined on the type \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"T\")])]),_vm._v(\" to signal the test success.\")]),_c('p',[_vm._v(\"When the test function returns without calling a failure method, then it is interpreted as a success.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"failure-signal\"}}),_c('h4',{attrs:{\"data-number\":\"7.0.0.5\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"7.0.0.5\")]),_vm._v(\" Failure signal \"),_c('a',{attrs:{\"href\":\"#failure-signal\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"To signal a failure, you can use the following methods :\")]),_c('ul',[_c('li',[_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Error\")])]),_vm._v(\" : will log and marks the test function as failed. Execution will continue.\")])]),_c('li',[_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Errorf\")])]),_vm._v(\" : will log (with the specified format) and marks the test function as failed. Execution will continue.\")])]),_c('li',[_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Fail\")])]),_vm._v(\" : will mark the function as failing. Execution will continue.\")])]),_c('li',[_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"FailNow\")])]),_vm._v(\" : this one will mark the test as failed and stop the execution of the current test function (if you have other assertions, they will not be tested).\")])])]),_c('p',[_vm._v(\"You also have the methods \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Fatal\")])]),_vm._v(\" and \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Fatalf\")])]),_vm._v(\" that will log and call internally \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"FailNow\")])]),_vm._v(\".\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"test-files\"}}),_c('h4',{attrs:{\"data-number\":\"7.0.0.6\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"7.0.0.6\")]),_vm._v(\" Test files \"),_c('a',{attrs:{\"href\":\"#test-files\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Sometimes you need to store files that will support your unit tests. For instance, an example of a configuration file, a model CSV file (for an application that will generate files)...\")]),_c('p',[_vm._v(\"Store those files into the \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"testdata\")])]),_vm._v(\" folder.\")]),_c('figure',[_c('b-img',{staticClass:\"img-book\",attrs:{\"src\":require('@/assets/images/testdatadir_archive_zip.png'),\"alt\":\"The testdata folder inside a package can hold files used in tests (tree view of standard library archive/zip)\",\"fluid\":\"\",\"thumbnail\":\"\"}}),_c('figcaption',{attrs:{\"aria-hidden\":\"true\"}},[_vm._v(\"The testdata folder inside a package can hold files used in tests (tree view of standard library archive/zip)\")])],1),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"assertion-libraries\"}}),_c('BuyCopyInvite'),_c('h1',{attrs:{\"data-number\":\"8\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"8\")]),_vm._v(\" Assertion libraries \"),_c('a',{attrs:{\"href\":\"#assertion-libraries\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"The Go standard library gives all the necessary tools to build your unit test without external libraries. Despite this fact, it is common to see projects that use external “assertion libraries”. An assertion library exposes many functions and methods to build assertions. One very popular module is \"),_c('strong',[_vm._v(\"github.com/stretchr/testify.\")])]),_c('p',[_vm._v(\"To add it to your project, type the following command in your terminal :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go get github.com/stretchr/testify\")])]),_c('p',[_vm._v(\"As an example, this is the previous unit test written with the help of the package \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"assert\")])]),_vm._v(\" from the module \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"github.com/stretchr/testify\")])]),_vm._v(\" :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/assert-lib/foo/foo_test.go\\npackage foo\\n\\nimport (\\n \\\"testing\\\"\\n\\n \\\"github.com/stretchr/testify/assert\\\"\\n)\\n\\nfunc TestFoo(t *testing.T) {\\n assert.Equal(t, \\\"Foo\\\", Foo(), \\\"they should be equal\\\")\\n}\")])]),_c('p',[_vm._v(\"Other libraries exist a quick search on GitHub can give you some additional references: https://github.com/search?l=Go&q=assertion+library&type=Repositories\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"how-to-run-unit-test\"}}),_c('h1',{attrs:{\"data-number\":\"9\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"9\")]),_vm._v(\" How to run unit test \"),_c('a',{attrs:{\"href\":\"#how-to-run-unit-test\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"run-the-tests-of-a-specific-package\"}}),_c('h2',{attrs:{\"data-number\":\"9.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"9.1\")]),_vm._v(\" Run the tests of a specific package \"),_c('a',{attrs:{\"href\":\"#run-the-tests-of-a-specific-package\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"To run your unit tests, you have to use the command-line interface. Open a terminal and cd to your project directory :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ cd go/src/gitlab.com/loir402/foo\")])]),_c('p',[_vm._v(\"Then run the following command :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\")])]),_c('p',[_vm._v(\"The following output result is displayed in the terminal :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"PASS\\nok gitlab.com/loir402/foo 0.005s\")])]),_c('p',[_vm._v(\"This command will run all the unit tests for the package located into the current directory. For instance, if you want to run the unit tests of the \"),_c('strong',[_vm._v(\"path\")]),_vm._v(\" package of the current directory :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ cd /usr/local/go/src/path\\n$ go test\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"run-all-the-tests-of-a-project\"}}),_c('h2',{attrs:{\"data-number\":\"9.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"9.2\")]),_vm._v(\" Run all the tests of a project \"),_c('a',{attrs:{\"href\":\"#run-all-the-tests-of-a-project\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"You can run all the unit tests of your current project by launching the command :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test ./...\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"test-failure\"}}),_c('h2',{attrs:{\"data-number\":\"9.3\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"9.3\")]),_vm._v(\" Test failure \"),_c('a',{attrs:{\"href\":\"#test-failure\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"What is the output of a failed unit test? Here is an example. We have modified our unit test to make it crash. Instead of the string \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"\\\"Foo\\\"\")])]),_vm._v(\" we are no expecting \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"\\\"Bar\\\"\")])]),_vm._v(\". Consequently, the test fails.\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\\n--- FAIL: TestFoo (0.00s)\\n foo_test.go:9: Expected Bar do not match actual Foo\\nFAIL\\nexit status 1\\nFAIL gitlab.com/loir402/foo 0.005s\")])]),_c('p',[_vm._v(\"You can note that the test result is more verbose in the case of a failure. It will indicate which test case fail by printing the test case name (\"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"TestFoo\")])]),_vm._v(\" ). it will also give you the line of the test that fails (\"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"foo_test.go:9\")])]),_vm._v(\").\")]),_c('p',[_vm._v(\"Then you can see that the system is printing the error message that we have told him to print in the case of a failure.\")]),_c('p',[_vm._v(\"The program exits with a status code of 1, allowing you to autodetect it if you want to create continuous integration tools.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"exit-code-or-exit-status\"}}),_c('h4',{attrs:{\"data-number\":\"9.3.0.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"9.3.0.1\")]),_vm._v(\" Exit Code (or exit status) \"),_c('a',{attrs:{\"href\":\"#exit-code-or-exit-status\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ul',[_c('li',[_c('p',[_vm._v(\"An exit code different from 0 signals an error.\")])]),_c('li',[_c('p',[_vm._v(\"An exit code of 0 signals NO errors\")])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"go-test-and-go-vetsubsecgo-testvet\"}}),_c('h2',{attrs:{\"data-number\":\"9.4\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"9.4\")]),_vm._v(\" go test and go vet\"),_c('span',{attrs:{\"id\":\"subsec:Go-testvet\",\"label\":\"subsec:Go-testvet\"}},[_vm._v(\"[subsec:Go-testvet]\")]),_vm._v(\" \"),_c('a',{attrs:{\"href\":\"#go-test-and-go-vetsubsecgo-testvet\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"When you run the \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"go test\")])]),_vm._v(\" command, the go tool will also run \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"go vet\")])]),_vm._v(\" automatically on the tested packages (source of the packages and test files).\")]),_c('p',[_vm._v(\"The \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"go vet\")])]),_vm._v(\" command is part of the Go toolchain. It performs syntax verification on your source code to detect potential errors.\")]),_c('p',[_vm._v(\"This command has a whole list of checks; when you run a go test, only a small subset is launched :\")]),_c('dl',[_c('dt',[_vm._v(\"atomic\")]),_c('dd',[_c('p',[_vm._v(\"will detect the bad usages of the package sync/atomic\")])]),_c('dt',[_vm._v(\"bool\")]),_c('dd',[_c('p',[_vm._v(\"this check will verify the usages of boolean conditions.\")])]),_c('dt',[_vm._v(\"buildtags\")]),_c('dd',[_c('p',[_vm._v(\"when you run a go test you can specify build tags to the command line, this check will verify that you have correctly formed build tags in the command you type.\")])]),_c('dt',[_vm._v(\"nilfunc\")]),_c('dd',[_c('p',[_vm._v(\"checks that you never compare a function with nil\")])])]),_c('p',[_vm._v(\"Running a set of \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"go vet\")])]),_vm._v(\" command automatically before launching unit tests is a brilliant idea. It can make you discover mistakes before they cause harm to your program!\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"just-compile\"}}),_c('h2',{attrs:{\"data-number\":\"9.5\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"9.5\")]),_vm._v(\" Just compile \"),_c('a',{attrs:{\"href\":\"#just-compile\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"To compile our test without running it, you can type the following command :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test -c\")])]),_c('p',[_vm._v(\"This will create a test binary called “\"),_c('strong',[_vm._v(\"packageName.test\")]),_vm._v(\"”.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"how-to-write-a-table-test\"}}),_c('h1',{attrs:{\"data-number\":\"10\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"10\")]),_vm._v(\" How to write a table test \"),_c('a',{attrs:{\"href\":\"#how-to-write-a-table-test\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"In the previous example, we tested our function against one expected result. In a real situation, you might want to test your function with several test cases.\")]),_c('p',[_vm._v(\"One approach could be to build a test function like that :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/table-test/price/price_test.go\\npackage price\\n\\nimport \\\"testing\\\"\\n\\nfunc Test_totalPrice1(t *testing.T) {\\n // test case 1\\n expected := uint(0)\\n actual := totalPrice(0, 150, 12)\\n if expected != actual {\\n t.Errorf(\\\"Expected %d does not match actual %d\\\", expected, actual)\\n }\\n // test case 2\\n expected = uint(112)\\n actual = totalPrice(1, 100, 12)\\n if expected != actual {\\n t.Errorf(\\\"Expected %d does not match actual %d\\\", expected, actual)\\n }\\n\\n // test case 3\\n expected = uint(224)\\n actual = totalPrice(2, 100, 12)\\n if expected != actual {\\n t.Errorf(\\\"Expected %d does not match actual %d\\\", expected, actual)\\n }\\n\\n}\")])]),_c('ul',[_c('li',[_c('p',[_vm._v(\"We have 3 test cases; each test case follow the previous one\")])]),_c('li',[_c('p',[_vm._v(\"This is a good approach; it works as expected. However, we can use the table test approach that can be more convenient :\")])])]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/table-test/price/price_test.go\\npackage price\\n\\nimport \\\"testing\\\"\\n\\nfunc Test_totalPrice(t *testing.T) {\\n type parameters struct {\\n nights uint\\n rate uint\\n cityTax uint\\n }\\n type testCase struct {\\n name string\\n args parameters\\n want uint\\n }\\n tests := []testCase{\\n {\\n name: \\\"test 0 nights\\\",\\n args: parameters{nights: 0, rate: 150, cityTax: 12},\\n want: 0,\\n },\\n {\\n name: \\\"test 1 nights\\\",\\n args: parameters{nights: 1, rate: 100, cityTax: 12},\\n want: 112,\\n },\\n {\\n name: \\\"test 2 nights\\\",\\n args: parameters{nights: 2, rate: 100, cityTax: 12},\\n want: 224,\\n },\\n }\\n for _, tt := range tests {\\n t.Run(tt.name, func(t *testing.T) {\\n if got := totalPrice(tt.args.nights, tt.args.rate, tt.args.cityTax); got != tt.want {\\n t.Errorf(\\\"totalPrice() = %v, want %v\\\", got, tt.want)\\n }\\n })\\n }\\n}\")])]),_c('ul',[_c('li',[_c('p',[_vm._v(\"We create a type struct named \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"parameters\")])]),_vm._v(\". Each field of that struct is a function parameter of the function under test\")])]),_c('li',[_c('p',[_vm._v(\"Then we create a struct named \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"testCase\")])]),_vm._v(\". With three fields:\")]),_c('ul',[_c('li',[_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"name\")])]),_vm._v(\": the name of the test case: a human-readable name\")])]),_c('li',[_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"args\")])]),_vm._v(\": the parameters to give to the function under test\")])]),_c('li',[_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"want\")])]),_vm._v(\": the expected value returned by the function\")])])])]),_c('li',[_c('p',[_vm._v(\"A slice named \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"tests\")])]),_vm._v(\" containing elements of type \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"testCase\")])]),_vm._v(\" is created. This is here that we will manually define each test case\")]),_c('ul',[_c('li',[_vm._v(\"One test case = one element of the slice.\")])])]),_c('li',[_c('p',[_vm._v(\"Then with a for loop, we iterate over the elements of the slice \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"tests\")])]),_vm._v(\".\")])]),_c('li',[_c('p',[_vm._v(\"At each iteration, we call the method \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"t.Run\")])])]),_c('ul',[_c('li',[_c('p',[_vm._v(\"Parameters :\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"the test name \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"tt.name\")])])])]),_c('li',[_c('p',[_vm._v(\"An anonymous function that contains the test to run (its signature is similar to a standard test case)\")])])])])])]),_c('li',[_c('p',[_vm._v(\"At each iteration, we compare what we got (the actual value) to what we expect.\")])])]),_c('p',[_vm._v(\"Here is the run output of this test (successful) :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"=== RUN Test_totalPrice\\n=== RUN Test_totalPrice/test_0_nights\\n=== RUN Test_totalPrice/test_1_nights\\n=== RUN Test_totalPrice/test_2_nights\\n--- PASS: Test_totalPrice (0.00s)\\n --- PASS: Test_totalPrice/test_0_nights (0.00s)\\n --- PASS: Test_totalPrice/test_1_nights (0.00s)\\n --- PASS: Test_totalPrice/test_2_nights (0.00s)\\nPASS\")])]),_c('ul',[_c('li',[_c('p',[_vm._v(\"The run result gives the information that three subtests are run.\")])]),_c('li',[_c('p',[_vm._v(\"It also gives the result for each test along with the name of the test.\")])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"the-two-go-test-modes\"}}),_c('h1',{attrs:{\"data-number\":\"11\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"11\")]),_vm._v(\" The two go test modes \"),_c('a',{attrs:{\"href\":\"#the-two-go-test-modes\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"go test\")])]),_vm._v(\" is a command that we can run in two different modes :\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"local-directory-mode\"}}),_c('h2',{attrs:{\"data-number\":\"11.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"11.1\")]),_vm._v(\" Local directory mode \"),_c('a',{attrs:{\"href\":\"#local-directory-mode\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"This mode is triggered when you run the command :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\")])]),_c('p',[_vm._v(\"Here nothing is added, just \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"go test\")])]),_vm._v(\". In this mode, Go will build the package located in the current directory.\")]),_c('p',[_vm._v(\"All unit tests of the project will not be executed, but only the ones defined at the current package level. Some IDEs will run this command each time you save a source file; that’s a pretty good idea because each time you modify a package file, you can check that the unit tests are passing.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"package-list-mode\"}}),_c('h2',{attrs:{\"data-number\":\"11.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"11.2\")]),_vm._v(\" Package list mode \"),_c('a',{attrs:{\"href\":\"#package-list-mode\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"In this mode, you can ask Go to unit test some specific packages or all the project packages.\")]),_c('p',[_vm._v(\"For instance, if you have a project that defines a \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"pkgName\")])]),_vm._v(\" strings you can run the following command :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"go test modulePath/pkgName\")])]),_c('p',[_vm._v(\"This command will work in any project directory. It will run the test of the package \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"pkgName\")])]),_vm._v(\" from the module \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"modulePath\")])]),_vm._v(\".\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"caching\"}}),_c('h2',{attrs:{\"data-number\":\"11.3\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"11.3\")]),_vm._v(\" Caching \"),_c('a',{attrs:{\"href\":\"#caching\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"When you are \"),_c('strong',[_vm._v(\"in package list mode\")]),_vm._v(\" go will cache the test result of \"),_c('strong',[_vm._v(\"successful\")]),_vm._v(\" tests. This mechanism has been developed to avoid testing packages multiple time.\")]),_c('p',[_vm._v(\"To test this behavior, launch the tests on the package strings :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test strings\")])]),_c('p',[_vm._v(\"It will output the following :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"ok strings 4.256s\")])]),_c('p',[_vm._v(\"You can see here that the unit test’s time is 4.256s, which is quite long.\")]),_c('p',[_vm._v(\"Try to launch it again :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test strings\\nok strings (cached)\")])]),_c('p',[_vm._v(\"You can see here that the result is instantaneous, and instead of the duration, the (cached) is displayed. It means that go has retrieved the cached version of the test result.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"disabling-cache\"}}),_c('h4',{attrs:{\"data-number\":\"11.3.0.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"11.3.0.1\")]),_vm._v(\" Disabling cache \"),_c('a',{attrs:{\"href\":\"#disabling-cache\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Note that when you modify a test file or a source file of the package, the test result that has been cached is invalidated, and the test will be effectively run.\")]),_c('p',[_vm._v(\"To disable caching, you can use the following command flag :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test strings -count=1\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"environnement-variables-and-cache\"}}),_c('h4',{attrs:{\"data-number\":\"11.3.0.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"11.3.0.2\")]),_vm._v(\" Environnement variables and cache \"),_c('a',{attrs:{\"href\":\"#environnement-variables-and-cache\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"If you are using environment variables in your source files, Go will cache the test result if the environment variables set are not changing.\")]),_c('p',[_vm._v(\"Let’s take an example, imagine that you are using the environment variable \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"MYENV\")])]),_vm._v(\" inside your test script :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestFoo(t *testing.T) {\\n env := os.Getenv(\\\"MYENV\\\")\\n fmt.Println(env)\\n //..\\n}\")])]),_c('p',[_vm._v(\"The first time, when you execute the test with the environment variable set to \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"\\\"BAR\\\"\")])]),_vm._v(\", then the test will run :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ export MYENV=BAR && go test gitlab.com/loir402/foo\\nok gitlab.com/loir402/foo 0.005s\")])]),_c('p',[_vm._v(\"At the second run of the same command, Go will retrieve the test result directly from cache :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"ok gitlab.com/loir402/foo (cached)\")])]),_c('p',[_vm._v(\"But if you change the value of the environment variable \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"MYENV\")])]),_vm._v(\" then the test will be executed :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ export MYENV=CORGE && go test gitlab.com/loir402/foo\\nok gitlab.com/loir402/foo 0.005s\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"open-files\"}}),_c('h4',{attrs:{\"data-number\":\"11.3.0.3\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"11.3.0.3\")]),_vm._v(\" Open files \"),_c('a',{attrs:{\"href\":\"#open-files\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"The same mechanism is in place when your code opens a file. If you run your test for the first time, Go will cache the result. But if the file has changed, the result is no longer cached, and the test is executed again :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestFoo(t *testing.T) {\\n d, err := ioutil.ReadFile(\\\"testdata/lol.txt\\\")\\n if err != nil {\\n t.Errorf(\\\"impossible to open file\\\")\\n }\\n fmt.Print(string(d))\\n //..\\n}\")])]),_c('p',[_vm._v(\"Here we open the file \"),_c('strong',[_vm._v(\"testdata/lol.txt.\")]),_vm._v(\" If we run the test for the first time, it is executed, and it’s cached.\")]),_c('p',[_vm._v(\"If we modify the content of testdata/lol.txt and rerun the test, it will be executed because the file’s content has changed, then the test conditions are not the same.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"running-unit-test-in-parallel\"}}),_c('BuyCopyInvite'),_c('h1',{attrs:{\"data-number\":\"12\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"12\")]),_vm._v(\" Running unit test in parallel \"),_c('a',{attrs:{\"href\":\"#running-unit-test-in-parallel\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"In a big project, the number of unit tests can become very large. Running the unit tests can become time-consuming for the team.\")]),_c('p',[_vm._v(\"You need to add a call to the \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Parallel\")])]),_vm._v(\" method from the package testing to allow your test to be run concurrently by the go command line.\")]),_c('p',[_vm._v(\"Let’s take an example:\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestCorge1(t *testing.T) {\\n time.Sleep(300 * time.Millisecond)\\n}\\n\\nfunc TestCorge2(t *testing.T) {\\n time.Sleep(300 * time.Millisecond)\\n}\\n\\nfunc TestCorge3(t *testing.T) {\\n time.Sleep(300 * time.Millisecond)\\n}\")])]),_c('p',[_vm._v(\"Here we have 3 unit tests, that are testing nothing but that just wait for 300 milliseconds each. We did not add any assertion on purpose to facilitate the reading of the source code.\")]),_c('p',[_vm._v(\"Let’s run those tests\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\")])]),_c('p',[_vm._v(\"The test result is the following :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"PASS\\nok gitlab.com/loir402/corge 0.913s\")])]),_c('p',[_vm._v(\"Tests are taking 0.913seconds to run which is roughly \"),_c('span',{staticClass:\"math inline\"},[_vm._v(\"3\\\\times300ms\")]),_vm._v(\".\")]),_c('p',[_vm._v(\"Let’s make them run in parallel :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestCorge1(t *testing.T) {\\n t.Parallel()\\n time.Sleep(300 * time.Millisecond)\\n}\\n\\nfunc TestCorge2(t *testing.T) {\\n t.Parallel()\\n time.Sleep(300 * time.Millisecond)\\n}\\n\\nfunc TestCorge3(t *testing.T) {\\n t.Parallel()\\n time.Sleep(300 * time.Millisecond)\\n}\")])]),_c('p',[_vm._v(\"Here we just added\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"t.Parallel()\")])]),_c('p',[_vm._v(\"at the beginning of the test. This simple method call will increase the running speed of our test :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\\nPASS\\nok gitlab.com/loir402/corge 0.308s\")])]),_c('p',[_vm._v(\"We have divided the running time by 3 ! This gain of time is precious for the development team, so use this feature when you build your unit tests !\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"advanced-usage-of-the-go-test-command\"}}),_c('h1',{attrs:{\"data-number\":\"13\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"13\")]),_vm._v(\" Advanced usage of the go test command \"),_c('a',{attrs:{\"href\":\"#advanced-usage-of-the-go-test-command\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"arguments--args\"}}),_c('h2',{attrs:{\"data-number\":\"13.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"13.1\")]),_vm._v(\" Arguments (-args) \"),_c('a',{attrs:{\"href\":\"#arguments--args\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"You can build a test that will accept command line arguments. Those arguments can be passed to the test executable by using a flag. Let’s take an example of a test that requires command-line arguments.\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestArgs(t *testing.T) {\\n arg1 := os.Args[1]\\n if arg1 != \\\"baz\\\" {\\n t.Errorf(\\\"Expected baz do not match actual %s\\\", arg1)\\n }\\n}\")])]),_c('p',[_vm._v(\"Here we retrieve the second command-line argument. Note that \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"os.Args\")])]),_vm._v(\" is a slice of strings (\"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"[]string\")])]),_vm._v(\"), and the first index (0) is occupied by internal values of the go test command line (the emplacement of the cached build).\")]),_c('p',[_vm._v(\"To pass arguments when the test run, we can use the flag \"),_c('strong',[_vm._v(\"-args :\")])]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test gitlab.com/loir402/foo -args bar\")])]),_c('p',[_vm._v(\"The execution result is the following :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"--- FAIL: TestArgs (0.00s)\\n foo_test.go:24: Expected baz do not match actual bar\\nFAIL\\nFAIL gitlab.com/loir402/foo 0.005s\")])]),_c('p',[_vm._v(\"You can add as many flags as you want with this method. Note that \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"-args\")])]),_vm._v(\" is not part of the cacheable flags.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"flags\"}}),_c('h2',{attrs:{\"data-number\":\"13.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"13.2\")]),_vm._v(\" Flags \"),_c('a',{attrs:{\"href\":\"#flags\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"You can pass all the existing build flags to the go test command line. In addition to that, specific testing flags are available.\")]),_c('p',[_vm._v(\"We intentionally do not cover benchmark-specific flags. We will explain them in a dedicated chapter.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"coverage-flags\"}}),_c('h4',{attrs:{\"data-number\":\"13.2.0.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"13.2.0.1\")]),_vm._v(\" Coverage flags \"),_c('a',{attrs:{\"href\":\"#coverage-flags\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('div',{staticClass:\"list\"},[_c('p',[_vm._v(\"This flag will display the coverage data analysis. It’s, in my opinion, the most important flag to know. The coverage data give you a statistic about the percentage of statements of your code that is covered by a unit test :\")])]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test -cover\\nPASS\\ncoverage: 100.0% of statements\\nok gitlab.com/loir402/foo 0.005s\")])]),_c('div',{staticClass:\"list\"},[_c('p',[_vm._v(\"This flag allows you to choose a method to compute the coverage percentage. (the default is “set”, other values available are “count” or “atomic”). For more information about the computation method, see the specific section.\")]),_c('p',[_vm._v(\"You can specify that coverage data will be computed only for a subset of your project’s package.\")]),_c('p',[_vm._v(\"write somewhere the cover data\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"test-run-flags\"}}),_c('h4',{attrs:{\"data-number\":\"13.2.0.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"13.2.0.2\")]),_vm._v(\" Test run flags \"),_c('a',{attrs:{\"href\":\"#test-run-flags\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('div',{staticClass:\"list\"},[_c('p',[_vm._v(\"With this flag, when the first test break, all the other tests are not run. This is useful when you want to debug your code and fix problems one by one (when they happen)\")]),_c('p',[_vm._v(\"This flag will define the maximum number of tests that will be run in parallel. By default, it is set to the variable GOMAXPROCS\")]),_c('p',[_vm._v(\"By default, the timeout is set to 10 minutes when you run your tests. Consequently, unit tests that run for more than 10 minutes will panic. If your test suite needs more than 10 minutes to be executed, you can overwrite that setting and set a specific duration (the value of this flag is a string that will be parsed as a time.Duration)\")]),_c('p',[_vm._v(\"Verbose mode will display the names of the test functions as they are run :\")])]),_c('p',[_vm._v(\"Here is an example output of the verbose mode :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"=== RUN TestCorge1\\n=== PAUSE TestCorge1\\n=== RUN TestCorge2\\n=== PAUSE TestCorge2\\n=== RUN TestCorge3\\n=== PAUSE TestCorge3\\n=== CONT TestCorge1\\n=== CONT TestCorge3\\n=== CONT TestCorge2\\n--- PASS: TestCorge2 (0.31s)\\n--- PASS: TestCorge3 (0.31s)\\n--- PASS: TestCorge1 (0.31s)\\nPASS\\nok gitlab.com/loir402/corge 0.311s\")])]),_c('p',[_vm._v(\"The log is pretty long for three tests because we run them in parallel. Tests that are not running in parallel do not log the PAUSE and CONT steps :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"=== RUN TestCorge1\\n--- PASS: TestCorge1 (0.31s)\\n=== RUN TestCorge2\\n--- PASS: TestCorge2 (0.31s)\\n=== RUN TestCorge3\\n--- PASS: TestCorge3 (0.31s)\\nPASS\\nok gitlab.com/loir402/corge 0.921s\")])]),_c('div',{staticClass:\"list\"},[_c('p',[_vm._v(\"When you run your test go will automatically run go vet for a set of common errors (see \"),_c('a',{attrs:{\"href\":\"#subsec:Go-testvet\",\"data-reference-type\":\"ref\",\"data-reference\":\"subsec:Go-testvet\"}},[_vm._v(\"[subsec:Go-testvet]\")]),_vm._v(\"). If you want to deactivate it totally (I do not recommend), you can set this flag to off. But you can also add complimentary checks.\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"profiling-flags\"}}),_c('h4',{attrs:{\"data-number\":\"13.2.0.3\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"13.2.0.3\")]),_vm._v(\" Profiling flags \"),_c('a',{attrs:{\"href\":\"#profiling-flags\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"The go test command line also defines specific flags to identify performances issues of your code. Those flags are covered in the specific chapter “Profiling”\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"code-coverage\"}}),_c('h1',{attrs:{\"data-number\":\"14\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"14\")]),_vm._v(\" Code Coverage \"),_c('a',{attrs:{\"href\":\"#code-coverage\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ul',[_c('li',[_c('p',[_vm._v(\"Is a project sufficiently tested?\")])]),_c('li',[_c('p',[_vm._v(\"What defines a good test level?\")])]),_c('li',[_c('p',[_vm._v(\"How to measure the testing level of a project?\")])])]),_c('p',[_vm._v(\"Code coverage answers those questions. Code coverage is a measure of how a project is tested. It is often given as a percentage.\")]),_c('p',[_vm._v(\"The measure’s definition is not unique, and different code coverage definitions exist.\")]),_c('p',[_vm._v(\"The go tool can compute this code coverage statistic for you. Three modes (or computation methods) are available.\")]),_c('p',[_vm._v(\"To output the test coverage of your code, run the following command :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test -cover\\nPASS\\ncoverage: 66.7% of statements\\n\\nok go_book/testCoverage 0.005s\")])]),_c('p',[_vm._v(\"You see that a new line has been added to the test summary. It gives the percentage of code coverage.\")]),_c('p',[_vm._v(\"We will go through this figure’s different computation methods in the next sections.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"cover-mode-set\"}}),_c('h2',{attrs:{\"data-number\":\"14.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"14.1\")]),_vm._v(\" Cover mode set \"),_c('a',{attrs:{\"href\":\"#cover-mode-set\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"This is the default mode. In literature, we call this mode the “statement coverage” that because it counts the percentage of executed statements in tests \"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"zhu1997software\",\"href\":\"#zhu1997software\"}},[_vm._v(\"[@zhu1997software]\")]),_vm._v(\".\")],1),_c('p',[_vm._v(\"Perfect test coverage is 100%, meaning that all the code statements have been tested.\")]),_c('p',[_vm._v(\"Let’s take an example with the following code :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"package testCoverage\\n\\nfunc BazBaz(number int) int {\\n if number < 10 {\\n return number\\n } else {\\n return number\\n }\\n}\")])]),_c('p',[_vm._v(\"This package defines one single function. Inside this function, a conditional statement discriminates two cases. Input numbers under ten and numbers above.\")]),_c('p',[_vm._v(\"Let’s write a test :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestBazBaz(t *testing.T) {\\n expected := 3\\n actual := BazBaz(3)\\n if actual != expected {\\n t.Errorf(\\\"actual %d, expected %d\\\", actual, expected)\\n }\\n}\")])]),_c('p',[_vm._v(\"In this unit test, we execute \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"BazBaz\")])]),_vm._v(\" with the number 3 as input.\")]),_c('p',[_vm._v(\"Let’s run the test :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"go test -cover\\nPASS\\ncoverage: 66.7% of statements\\n\\nok go_book/testCoverage 0.005s\")])]),_c('p',[_vm._v(\"We only covered 66.7% of statements.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"cover-profile\"}}),_c('h4',{attrs:{\"data-number\":\"14.1.0.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"14.1.0.1\")]),_vm._v(\" Cover Profile \"),_c('a',{attrs:{\"href\":\"#cover-profile\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"To help us understand the computation go can generate a coverprofile, which is a file detailing which statements are covered.\")]),_c('figure',[_c('b-img',{staticClass:\"img-book\",attrs:{\"src\":require('@/assets/images/coverprofile.png'),\"alt\":\"Coverprofile HTML generated[fig:Coverprofile-HTML-generated]\",\"fluid\":\"\",\"thumbnail\":\"\"}}),_c('figcaption',{attrs:{\"aria-hidden\":\"true\"}},[_vm._v(\"Coverprofile HTML generated\"),_c('span',{attrs:{\"id\":\"fig:Coverprofile-HTML-generated\",\"label\":\"fig:Coverprofile-HTML-generated\"}},[_vm._v(\"[fig:Coverprofile-HTML-generated]\")])])],1),_c('p',[_vm._v(\"To generate this file, you have to use two commands in your terminal :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test -coverprofile profile\")])]),_c('p',[_vm._v(\"This first command will generate the profile file :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"mode: set\\nunit-test/coverage/testCoverage.go:3.29,4.17 1 1\\nunit-test/coverage/testCoverage.go:4.17,6.3 1 1\\nunit-test/coverage/testCoverage.go:6.8,8.3 1 0\")])]),_c('p',[_vm._v(\"This file details the blocks of code of your application. Each line represent a “block”. At the end of each line you can see two figures: the total number of statements and the number of statements covered (see figure \"),_c('a',{attrs:{\"href\":\"#fig:Coverprofile-file\",\"data-reference-type\":\"ref\",\"data-reference\":\"fig:Coverprofile-file\"}},[_vm._v(\"2\")]),_vm._v(\")\")]),_c('figure',[_c('b-img',{staticClass:\"img-book\",attrs:{\"src\":require('@/assets/images/coverprofile_schema.png'),\"alt\":\"Coverprofile file[fig:Coverprofile-file]\",\"fluid\":\"\",\"thumbnail\":\"\"}}),_c('figcaption',{attrs:{\"aria-hidden\":\"true\"}},[_vm._v(\"Coverprofile file\"),_c('span',{attrs:{\"id\":\"fig:Coverprofile-file\",\"label\":\"fig:Coverprofile-file\"}},[_vm._v(\"[fig:Coverprofile-file]\")])])],1),_c('p',[_vm._v(\"This file is not easily readable. From this file, you can generate a nice HTML file like in the figure \"),_c('a',{attrs:{\"href\":\"#fig:Coverprofile-HTML-generated\",\"data-reference-type\":\"ref\",\"data-reference\":\"fig:Coverprofile-HTML-generated\"}},[_vm._v(\"1\")]),_vm._v(\". To do this, type the following command :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go tool cover -html=profile\")])]),_c('p',[_vm._v(\"It will create an HTML page, store it (not in your project directory) and open it on a browser.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"increase-the-coverage\"}}),_c('h4',{attrs:{\"data-number\":\"14.1.0.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"14.1.0.2\")]),_vm._v(\" Increase the coverage \"),_c('a',{attrs:{\"href\":\"#increase-the-coverage\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"We have a total of three statements, and two are covered: the first if statement then the first return. It means that \"),_c('span',{staticClass:\"math inline\"},[_vm._v(\"\\\\frac{2}{3}\")]),_vm._v(\" (or 66.7%) of statements are covered.\")]),_c('p',[_vm._v(\"We can increase that percentage to 100% by integrating a test of the remaining statement (the else part of our condition) :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestBazBaz2(t *testing.T) {\\n expected := 25\\n actual := BazBaz(25)\\n if actual != expected {\\n t.Errorf(\\\"actual %d, expected %d\\\", actual, expected)\\n }\\n}\")])]),_c('p',[_vm._v(\"This will lead to a coverage of 100%. All the statements of our code are covered.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"cover-mode-count\"}}),_c('h2',{attrs:{\"data-number\":\"14.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"14.2\")]),_vm._v(\" Cover mode count \"),_c('a',{attrs:{\"href\":\"#cover-mode-count\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"The \"),_c('strong',[_vm._v(\"count\")]),_vm._v(\" mode is similar to the \"),_c('strong',[_vm._v(\"set\")]),_vm._v(\" mode. With this mode you can detect if some part of the code is covered by more tests than others.\")]),_c('p',[_vm._v(\"For instance, the function :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func BazBaz(number int) int {\\n if number < 10 {\\n return number\\n } else {\\n return number\\n }\\n}\")])]),_c('p',[_vm._v(\"is tested by two test cases :\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"One that will test an input less than 10\")])]),_c('li',[_c('p',[_vm._v(\"One that will test an input greater than 10.\")])])]),_c('p',[_vm._v(\"All statements are covered, but the first one (the conditional statement if) is tested twice. During the execution of the second test, the test \"),_c('strong',[_vm._v(\"number < 10\")]),_vm._v(\" is evaluated.\")]),_c('p',[_vm._v(\"The conditional statement is “more” tested than the other one.\")]),_c('p',[_vm._v(\"The coverprofile in count mode has not the same layout as you can see in figure \"),_c('a',{attrs:{\"href\":\"#fig:Coverprofile-Count-mode\",\"data-reference-type\":\"ref\",\"data-reference\":\"fig:Coverprofile-Count-mode\"}},[_vm._v(\"3\")]),_vm._v(\".\")]),_c('figure',[_c('b-img',{staticClass:\"img-book\",attrs:{\"src\":require('@/assets/images/coverprofile_count.png'),\"alt\":\"Coverprofile Count mode[fig:Coverprofile-Count-mode]\",\"fluid\":\"\",\"thumbnail\":\"\"}}),_c('figcaption',{attrs:{\"aria-hidden\":\"true\"}},[_vm._v(\"Coverprofile Count mode\"),_c('span',{attrs:{\"id\":\"fig:Coverprofile-Count-mode\",\"label\":\"fig:Coverprofile-Count-mode\"}},[_vm._v(\"[fig:Coverprofile-Count-mode]\")])])],1),_c('p',[_vm._v(\"The greener the statement is, the more it’s tested.\")]),_c('p',[_vm._v(\"The coverprofile has the same layout, but the last figure represents the number of time the statement is tested :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"mode: count\\nunit-test/coverage/testCoverage.go:3.29,4.17 1 2\\nunit-test/coverage/testCoverage.go:4.17,6.3 1 1\\nunit-test/coverage/testCoverage.go:6.8,8.3 1 1\")])]),_c('p',[_vm._v(\"On the second line of this profile, you can see that the first code block (starts at 3.29 and ends at 4.17) has 1 statement tested two times.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"cover-mode-atomic-advanced\"}}),_c('h2',{attrs:{\"data-number\":\"14.3\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"14.3\")]),_vm._v(\" Cover mode atomic (advanced) \"),_c('a',{attrs:{\"href\":\"#cover-mode-atomic-advanced\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"The last cover mode is count. It is useful when you build concurrent programs. Internally the system will use atomic counters (instead of simple counters). With those concurrent safe counters, the coverprofile will be \"),_c('strong',[_vm._v(\"more precise.\")])]),_c('p',[_vm._v(\"To demonstrate it, I have modified the \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"BazBaz\")])]),_vm._v(\" function to make it even more silly by adding useless goroutines :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/coverage/testCoverage.go\\npackage testCoverage\\n\\nimport (\\n \\\"fmt\\\"\\n \\\"sync\\\"\\n)\\n\\nfunc BazBaz(number int) int {\\n var waitGroup sync.WaitGroup\\n for i := 0; i < 100; i++ {\\n waitGroup.Add(1)\\n go concurrentTask(number, &waitGroup)\\n }\\n waitGroup.Wait()\\n return number\\n}\\n\\nfunc concurrentTask(number int, waitGroup *sync.WaitGroup) {\\n useless := number + 2\\n fmt.Println(useless)\\n waitGroup.Done()\\n}\")])]),_c('p',[_vm._v(\"We will launch 100 useless concurrent tasks that just make an assignment: set useless to the number + 2. We use waitgroups to ensure that all our concurrent tasks will execute before the program ends. We do not modify the unit tests.\")]),_c('p',[_vm._v(\"Let’s get the coverprofile in count mode :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test -coverprofile profileCount -covermode count\\n$ cat profileCount\\nmode: count\\ngo_book/testCoverage/testCoverage.go:8.29,10.27 2 2\\ngo_book/testCoverage/testCoverage.go:14.2,15.15 2 2\\ngo_book/testCoverage/testCoverage.go:10.27,13.3 2 200\\ngo_book/testCoverage/testCoverage.go:18.60,22.2 3 197\")])]),_c('p',[_vm._v(\"And in atomic mode :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test -coverprofile profileAtomic -covermode atomic\\n$ cat profileAtomic\\nmode: atomic\\ngo_book/testCoverage/testCoverage.go:8.29,10.27 2 2\\ngo_book/testCoverage/testCoverage.go:14.2,15.15 2 2\\ngo_book/testCoverage/testCoverage.go:10.27,13.3 2 200\\ngo_book/testCoverage/testCoverage.go:18.60,22.2 3 200\")])]),_c('p',[_vm._v(\"If we use the count mode, the result is not accurate. For the last block of code (from 18.60 to 22.2), the count mode has found that we have tested the statement 197 times. The atomic mode has found that we have tested it 200 times which is the correct value.\")]),_c('p',[_vm._v(\"Note that this cover mode will add overhead to the coverprofile creation.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"test-driven-development-tdd\"}}),_c('h1',{attrs:{\"data-number\":\"15\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"15\")]),_vm._v(\" Test-Driven Development (TDD) \"),_c('a',{attrs:{\"href\":\"#test-driven-development-tdd\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"Test-Driven Development (or TDD) is a \"),_c('strong',[_vm._v(\"development method\")]),_vm._v(\" where you design the tests before actually writing the software.\")]),_c('p',[_vm._v(\"Historically this method has emerged with the development of the XP methodology in the late nineties. This method has been widespread among the community, and authors like Robert C. Martin\"),_c('a',{staticClass:\"footnote-ref\",attrs:{\"href\":\"#fn1\",\"id\":\"fnref1\",\"role\":\"doc-noteref\"}},[_c('sup',[_vm._v(\"1\")])]),_vm._v(\" have contributed to its adoption.\")]),_c('p',[_vm._v(\"Let’s jump right away to an example in Go. Our objective is to build a function that will count the number of vowels in a string. We first begin by creating a test case (that will fail because we have not created the function :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/tdd/tdd_test.go\\npackage tdd\\n\\nimport \\\"testing\\\"\\n\\nfunc TestVowelCount(t *testing.T) {\\n expected := uint(5)\\n actual := VowelCount(\\\"I love you\\\")\\n if actual != expected {\\n t.Errorf(\\\"actual %d, expected %d\\\", actual, expected)\\n }\\n}\")])]),_c('p',[_vm._v(\"Here we are calling the function \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"VowelCount\")])]),_vm._v(\" with the sentence \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"\\\"I love you\\\"\")])]),_vm._v(\". In this sentence, we have five vowels; our expected result is the integer 4. As usual, we compare the actual number and the expected.\")]),_c('p',[_vm._v(\"Let’s run our test to see what happens :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\\n# go_book/tdd [go_book/tdd.test]\\n./tdd_test.go:7:12: undefined: VowelCount\\nFAIL go_book/tdd [build failed]\")])]),_c('p',[_vm._v(\"We cannot compile; the test fails.\")]),_c('p',[_vm._v(\"Now we can implement our function. We start by creating a map of vowels from the alphabet.\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/tdd/tdd.go\\npackage tdd\\n\\nvar vowels = map[string]bool{\\n \\\"a\\\": true,\\n \\\"e\\\": true,\\n \\\"i\\\": true,\\n \\\"o\\\": true,\\n \\\"u\\\": true}\")])]),_c('p',[_vm._v(\"Then we create the function. It will take each letter of the sentence iteratively and check if the vowel is on the map :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"// unit-test/tdd/tdd.go\\npackage tdd\\n\\n//...\\n\\nfunc VowelCount(sentence string) uint {\\n var count uint\\n for _, char := range sentence {\\n if vowels[string(char)] {\\n count++\\n }\\n }\\n return count\\n}\")])]),_c('p',[_vm._v(\"The char is the Unicode code point. That’s why we have to convert it to a string to make our script work. Let’s run the test again to see if our implementation works :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\\n--- FAIL: TestVowelCount (0.00s)\\n tdd_test.go:9: actual 4, expected 5\\nFAIL\\nexit status 1\\n\\nFAIL go_book/tdd 0.005s\")])]),_c('p',[_vm._v(\"It seems not to work. What could be wrong with our code? One letter seems to be skipped. There is something we missed, here our test string comes with the I capitalized, but we compare it to lowercase letters. That’s a bug. We want to count also capitalized vowels.\")]),_c('p',[_vm._v(\"What have to options :\")]),_c('ol',{attrs:{\"type\":\"1\"}},[_c('li',[_c('p',[_vm._v(\"Add the uppercase letters to our map.\")])]),_c('li',[_c('p',[_vm._v(\"Each letter should be converted to lowercase and then compared with the existing map.\")])])]),_c('p',[_vm._v(\"The second solution seems to be less efficient than the first :\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"In the first option, we have to spend precious time converting each letter,\")])]),_c('li',[_c('p',[_vm._v(\"Whereas in the second solution, we are just performing a map lookup which is really fast (O(1)\"),_c('a',{staticClass:\"footnote-ref\",attrs:{\"href\":\"#fn2\",\"id\":\"fnref2\",\"role\":\"doc-noteref\"}},[_c('sup',[_vm._v(\"2\")])]),_vm._v(\").\")])])]),_c('p',[_vm._v(\"Let’s add the capitalized vowels to our map :\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"var vowels = map[string]bool{\\n //...\\n \\\"A\\\": true,\\n \\\"E\\\": true,\\n \\\"I\\\": true,\\n \\\"O\\\": true,\\n \\\"U\\\": true}\")])]),_c('p',[_vm._v(\"Then we run our test again, and it works !\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"$ go test\\nPASS\\n\\nok go_book/tdd 0.005s\")])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"advantages\"}}),_c('h4',{attrs:{\"data-number\":\"15.0.0.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"15.0.0.1\")]),_vm._v(\" Advantages \"),_c('a',{attrs:{\"href\":\"#advantages\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ul',[_c('li',[_c('p',[_vm._v(\"The developer is forced to create a function that \"),_c('strong',[_vm._v(\"can be tested\")]),_vm._v(\".\")])]),_c('li',[_c('p',[_vm._v(\"When we wrote our test, we have chosen our function’s signature. This is an act of design focused on the use of our functionality. In a certain measure, we are designing our API in an \"),_c('strong',[_vm._v(\"user-centric approach\")]),_vm._v(\". We are using our API before actually implementing it forces us to keep things simple and usable.\")])]),_c('li',[_c('p',[_vm._v(\"With this method \"),_c('strong',[_vm._v(\"every single function of our source code is tested\")]),_vm._v(\".\")])])]),_c('p',[_vm._v(\"You might argue that this way of developing is not very natural. This feeling is normal. Many developers (especially young ones) that I have met are reluctant to do the tests and prefer to develop the functionality in a minimal amount of time.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"facts-and-figures\"}}),_c('h4',{attrs:{\"data-number\":\"15.0.0.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"15.0.0.2\")]),_vm._v(\" Facts and figures \"),_c('a',{attrs:{\"href\":\"#facts-and-figures\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('p',[_vm._v(\"To convince you of this approach, I will focus on the fact and on real studies that have been conducted about TDD. (Those results have been extracted from the very good article of David Janzen \"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"janzen2005test\",\"href\":\"#janzen2005test\"}},[_vm._v(\"[@janzen2005test]\")]),_vm._v(\" that was published in 2005) :\")],1),_c('ul',[_c('li',[_c('p',[_vm._v(\"Using TDD has generated a reduction of 50% of defect density for a company composed of 9 developers. With a minimal impact on productivity.\"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"maximilien2003assessing\",\"href\":\"#maximilien2003assessing\"}},[_vm._v(\"[@maximilien2003assessing]\")])],1)]),_c('li',[_c('p',[_vm._v(\"For another company, the reduction percentage was 40%, with no impact at all on the productivity of the team (9 developers) \"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"williams2003test\",\"href\":\"#williams2003test\"}},[_vm._v(\"[@williams2003test]\")]),_vm._v(\".\")],1)]),_c('li',[_c('p',[_vm._v(\"The use of unit test leads to a better information flow in the company \"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"kaufmann2003implications\",\"href\":\"#kaufmann2003implications\"}},[_vm._v(\"[@kaufmann2003implications]\")]),_vm._v(\".\")],1)]),_c('li',[_c('p',[_vm._v(\"Another study that was conducted in a class of undergraduate class of computer science has demonstrated a reduction of 45% of defects per thousand lines of code \"),_c('b-link',{staticClass:\"citation\",attrs:{\"data-cites\":\"edwards2003using\",\"href\":\"#edwards2003using\"}},[_vm._v(\"[@edwards2003using]\")]),_vm._v(\".\")],1)])]),_c('p',[_vm._v(\"I hope you are convinced.\")]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"test-yourself\"}}),_c('BuyCopyInvite'),_c('h1',{attrs:{\"data-number\":\"16\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"16\")]),_vm._v(\" Test yourself \"),_c('a',{attrs:{\"href\":\"#test-yourself\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"questions\"}}),_c('h2',{attrs:{\"data-number\":\"16.1\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"16.1\")]),_vm._v(\" Questions \"),_c('a',{attrs:{\"href\":\"#questions\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ol',{attrs:{\"type\":\"1\"}},[_c('li',[_c('p',[_vm._v(\"In a Go program where test files are stored?\")])]),_c('li',[_c('p',[_vm._v(\"You develop a function named \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"ShippingCost\")])]),_vm._v(\". What is the conventional signature of its test function?\")])]),_c('li',[_c('p',[_vm._v(\"In a test, you need to load data from a separate file; where can you store it?\")])]),_c('li',[_c('p',[_vm._v(\"What is an assertion? Give an example.\")])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"answers\"}}),_c('h2',{attrs:{\"data-number\":\"16.2\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"16.2\")]),_vm._v(\" Answers \"),_c('a',{attrs:{\"href\":\"#answers\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ol',{attrs:{\"type\":\"1\"}},[_c('li',[_c('p',[_vm._v(\"In a Go program where test files are stored?\")]),_c('ol',{attrs:{\"type\":\"1\"}},[_c('li',[_vm._v(\"Test files are stored in the same directory as the package source files.\")])])]),_c('li',[_c('p',[_vm._v(\"You develop a function named \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"ShippingCost\")])]),_vm._v(\". What is the conventional signature of its test function?\")]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"func TestShippingCost(t *testing.T)\")])]),_c('ol',{attrs:{\"type\":\"1\"}},[_c('li',[_c('p',[_vm._v(\"Note the string \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"\\\"Test\\\"\")])]),_vm._v(\" at the beginning of the function, this is mandatory\")])]),_c('li',[_c('p',[_vm._v(\"The characters after “Test” are free, but they must begin with a capitalized letter or an underscore (_)\")])])])]),_c('li',[_c('p',[_vm._v(\"In a test, you need to load data from a separate file; where can you store it?\")]),_c('ol',{attrs:{\"type\":\"1\"}},[_c('li',[_c('p',[_vm._v(\"You can create a directory named “\"),_c('strong',[_vm._v(\"testdata\")]),_vm._v(\"” in the directory containing the source files of the package.\")])]),_c('li',[_c('p',[_vm._v(\"You can put in this folder files loaded in your test cases.\")])])])]),_c('li',[_c('p',[_vm._v(\"What is an assertion? Give an example.\")]),_c('ol',{attrs:{\"type\":\"1\"}},[_c('li',[_c('p',[_vm._v(\"In the context of unit tests, an assertion is a boolean expression (i.e., An expression that will be evaluated to true or false).\")])]),_c('li',[_c('p',[_vm._v(\"A “traditional” example is :\")])])]),_c('pre',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\"}},[_vm._v(\"actual == expected\")])])])]),_c('div',{staticClass:\"anchor\",attrs:{\"id\":\"key-takeaways\"}}),_c('h1',{attrs:{\"data-number\":\"17\"}},[_c('span',{staticClass:\"header-section-number\"},[_vm._v(\"17\")]),_vm._v(\" Key Takeaways \"),_c('a',{attrs:{\"href\":\"#key-takeaways\"}},[_c('b-icon-link45deg',{staticClass:\"heading-link-icon\",attrs:{\"font-scale\":\"0.7\"}})],1)]),_c('ul',[_c('li',[_c('p',[_vm._v(\"Writing unit tests is a good practice :\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"It gives relative protection against regressions.\")])]),_c('li',[_c('p',[_vm._v(\"Unit tests may detect bugs before they appear in production.\")])]),_c('li',[_c('p',[_vm._v(\"Improve the design of your package’s API\")])])])]),_c('li',[_c('p',[_vm._v(\"Unit tests live inside packages.\")])]),_c('li',[_c('p',[_vm._v(\"Tests are written on test files.\")])]),_c('li',[_c('p',[_c('strong',[_vm._v(\"xxx_test.go\")]),_vm._v(\" is the conventional name of a test file.\")])]),_c('li',[_c('p',[_vm._v(\"Test files can contain multiple test functions\")])]),_c('li',[_c('p',[_vm._v(\"A test function can contain several test cases\")])]),_c('li',[_c('p',[_vm._v(\"The name of a test function should begin with \"),_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"Test\")])]),_vm._v(\", the next characters is either an underscore or a capitalized letter\")])]),_c('li',[_c('p',[_vm._v(\"The name of the function under test is generally contained in the test function name.\")])]),_c('li',[_c('p',[_vm._v(\"A test function has the following signature :\")]),_c('pre',{attrs:{\"data-float\":\"\"}},[_c('span',{directives:[{name:\"highlightjs\",rawName:\"v-highlightjs\"}]},[_c('code',{pre:true,attrs:{\"class\":\"go\",\"style\":\"display: inline\"}},[_vm._v(\"func TestShippingCost(t *testing.T)\")])])])]),_c('li',[_c('p',[_vm._v(\"Table tests are a convenient way to test several test cases in a single function.\")])]),_c('li',[_c('p',[_vm._v(\"Test-Driven Development is a method that can increase the quality of your code and reduce defects.\")]),_c('ul',[_c('li',[_c('p',[_vm._v(\"The unit test is written before the actual implementation\")])]),_c('li',[_c('p',[_vm._v(\"The unit test fails first; the aim is then to make it pass.\")])])])])]),_c('section',{staticClass:\"footnotes\",attrs:{\"role\":\"doc-endnotes\"}},[_c('hr'),_c('ol',[_c('li',{attrs:{\"id\":\"fn1\",\"role\":\"doc-endnote\"}},[_c('p',[_vm._v(\"Nickname: Uncle bob\"),_c('a',{staticClass:\"footnote-back\",attrs:{\"href\":\"#fnref1\",\"role\":\"doc-backlink\"}},[_vm._v(\"↩︎\")])])]),_c('li',{attrs:{\"id\":\"fn2\",\"role\":\"doc-endnote\"}},[_c('p',[_vm._v(\"This is the Big O notation\"),_c('a',{staticClass:\"footnote-back\",attrs:{\"href\":\"#fnref2\",\"role\":\"doc-backlink\"}},[_vm._v(\"↩︎\")])])])])]),_c('h1',[_vm._v(\"Bibliography\")]),_c('ChapterBibliography',{attrs:{\"chapter-id\":\"Chap19UnitTests\"}}),_c('b-row',{staticClass:\"ml-1 mr-1 \"},[_c('b-col',{staticClass:\"text-center border mr-1 p-2\"},[_c('router-link',{attrs:{\"to\":{name:'Chap18GoModuleProxies'}}},[_c('p',[_c('u',[_c('small',[_vm._v(\"Previous\")])])]),_c('p',[_c('small',[_vm._v(\"Go Module Proxies\")])])])],1),_c('b-col',{staticClass:\"text-center border p-1 \"},[_c('router-link',{attrs:{\"to\":{name:'Chap20Arrays'}}},[_c('p',[_c('u',[_c('small',[_vm._v(\"Next\")])])]),_c('p',[_c('small',[_vm._v(\"Arrays\")])])])],1)],1),_c('b-row',{staticClass:\"mt-1 ml-1 mr-1\"},[_c('b-col',{staticClass:\"text-center border p-1 \"},[_c('b-link',{attrs:{\"to\":{name:'Home'}}},[_vm._v(\"Table of contents\")])],1)],1),_c('FeedbackInvite'),_c('NewsletterInput'),_c('Footer')],1),_c('b-col')],1)],1)],1)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n","import mod from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Chap19UnitTests.vue?vue&type=script&lang=js&\"; export default mod; export * from \"-!../../node_modules/cache-loader/dist/cjs.js??ref--13-0!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/cache-loader/dist/cjs.js??ref--1-0!../../node_modules/vue-loader/lib/index.js??vue-loader-options!./Chap19UnitTests.vue?vue&type=script&lang=js&\"","import { render, staticRenderFns } from \"./Chap19UnitTests.vue?vue&type=template&id=1957270d&scoped=true&\"\nimport script from \"./Chap19UnitTests.vue?vue&type=script&lang=js&\"\nexport * from \"./Chap19UnitTests.vue?vue&type=script&lang=js&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"1957270d\",\n null\n \n)\n\nexport default component.exports","module.exports = __webpack_public_path__ + \"img/coverprofile_count.42abb5d1.png\";"],"sourceRoot":""}