In the previous sections, we have completed the basic functions of a web serverver such as Login, Register, CRUD. The purpose of this article is to introduce basically how to deploy and write unit tests with Golang. The way to write more complex, more sophisticated test cases will not be introduced in this article. Hope to be introduced to you soon in a near post.
1. Introduction
Go provides 2 standard libraries for writing tests:
There are also quite a lot of libraries, framework tests developed by 3rd parties such as gocheck , ginkgo , etc.
Test files when using package testing
have a ending in the name _test.go
. For example, if we have the file hello.go
, the test file will be named hello_test.go
In addition, the test function name will be in the form
1 2 3 |
<span class="token comment">// Xxx không được bắt đầu bằng chữ thường</span> <span class="token keyword">func</span> <span class="token function">TestXxx</span> <span class="token punctuation">(</span> <span class="token operator">*</span> testing <span class="token punctuation">.</span> T <span class="token punctuation">)</span> |
The Test function passes a pointer type parameter T
of the testing library. type T
contains methods that support the management of the status of test cases as well as support the printing logs of test cases through the methods of Error
, Errorf
, Fail
, Log
, etc. Details of all methods of type T
and You can see the usage details here .
1 2 3 4 5 6 |
<span class="token keyword">type</span> T <span class="token keyword">struct</span> <span class="token punctuation">{</span> common isParallel <span class="token builtin">bool</span> context <span class="token operator">*</span> testContext <span class="token comment">// For running tests and subtests.</span> <span class="token punctuation">}</span> |
2. Write testcase with testing library
We have a simple example as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token comment">// hello.go</span> <span class="token keyword">package</span> main <span class="token keyword">import</span> <span class="token string">"fmt"</span> <span class="token keyword">func</span> <span class="token function">hello</span> <span class="token punctuation">(</span> name <span class="token builtin">string</span> <span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> name <span class="token operator">==</span> <span class="token string">""</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> fmt <span class="token punctuation">.</span> <span class="token function">Sprintf</span> <span class="token punctuation">(</span> <span class="token string">"What is your name ?"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> fmt <span class="token punctuation">.</span> <span class="token function">Sprintf</span> <span class="token punctuation">(</span> <span class="token string">"Hello %s"</span> <span class="token punctuation">,</span> name <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span class="token comment">// hello_test.go</span> <span class="token keyword">package</span> main <span class="token keyword">import</span> <span class="token string">"testing"</span> <span class="token keyword">func</span> <span class="token function">TestHello</span> <span class="token punctuation">(</span> t <span class="token operator">*</span> testing <span class="token punctuation">.</span> T <span class="token punctuation">)</span> <span class="token punctuation">{</span> emptyNameResult <span class="token operator">:=</span> <span class="token function">hello</span> <span class="token punctuation">(</span> <span class="token string">""</span> <span class="token punctuation">)</span> <span class="token keyword">if</span> emptyNameResult <span class="token operator">!=</span> <span class="token string">"What is your name ?"</span> <span class="token punctuation">{</span> t <span class="token punctuation">.</span> <span class="token function">Errorf</span> <span class="token punctuation">(</span> <span class="token string">"Output expect What is your name ? instead of %v"</span> <span class="token punctuation">,</span> emptyNameResult <span class="token punctuation">)</span> <span class="token punctuation">}</span> result <span class="token operator">:=</span> <span class="token function">hello</span> <span class="token punctuation">(</span> <span class="token string">"Gopher"</span> <span class="token punctuation">)</span> <span class="token keyword">if</span> result <span class="token operator">!=</span> <span class="token string">"Hello Gopher"</span> <span class="token punctuation">{</span> t <span class="token punctuation">.</span> <span class="token function">Errorf</span> <span class="token punctuation">(</span> <span class="token string">"Output expect Hello Gopher instead of %v"</span> <span class="token punctuation">,</span> result <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- The
hello
function performs the basic function of returning aHello
+tham số name
. Ifname
empty then returnsWhat is your name ?
stringWhat is your name ?
. - The
TestHello
function tests two outputs of thehello
function. If the return value is different from the expected output, the test will fail. - The
t.Errorf
method as well as thet.Error
function has the function to markfailed
tests if the output is not expected. After execution is complete, the code in theTestHello
function will continue to be executed.t.Errorf
different fromt.Error
likefmt.Printlnf
different fromfmt.Println
.
We run the test, test case pass because the return value matches the expectation.
We try to fix the hello
function a bit and keep the TestHello
function intact
1 2 3 4 5 6 7 8 |
<span class="token keyword">func</span> <span class="token function">hello</span> <span class="token punctuation">(</span> name <span class="token builtin">string</span> <span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> name <span class="token operator">==</span> <span class="token string">""</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> fmt <span class="token punctuation">.</span> <span class="token function">Sprintf</span> <span class="token punctuation">(</span> <span class="token string">"You do not have name !"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> fmt <span class="token punctuation">.</span> <span class="token function">Sprintf</span> <span class="token punctuation">(</span> <span class="token string">"Hello %s"</span> <span class="token punctuation">,</span> name <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Run test case:
The actual output is You do not have name !
instead of What is your name ?
as expected.
Check test coverage
100% coverage, great
3. Write testcase with httptest library
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<span class="token comment">// server.go</span> <span class="token keyword">package</span> main <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"fmt"</span> <span class="token boolean">_</span> <span class="token string">"encoding/json"</span> <span class="token string">"net/http"</span> <span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token function">welcome</span> <span class="token punctuation">(</span> w http <span class="token punctuation">.</span> ResponseWriter <span class="token punctuation">,</span> r <span class="token operator">*</span> http <span class="token punctuation">.</span> Request <span class="token punctuation">)</span> <span class="token punctuation">{</span> w <span class="token punctuation">.</span> <span class="token function">Header</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">Set</span> <span class="token punctuation">(</span> <span class="token string">"Content-Type"</span> <span class="token punctuation">,</span> <span class="token string">"application/json"</span> <span class="token punctuation">)</span> fmt <span class="token punctuation">.</span> <span class="token function">Fprintln</span> <span class="token punctuation">(</span> w <span class="token punctuation">,</span> <span class="token string">"Welcome to our website"</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">main</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> http <span class="token punctuation">.</span> <span class="token function">HandleFunc</span> <span class="token punctuation">(</span> <span class="token string">"/"</span> <span class="token punctuation">,</span> welcome <span class="token punctuation">)</span> http <span class="token punctuation">.</span> <span class="token function">ListenAndServe</span> <span class="token punctuation">(</span> <span class="token string">":3000"</span> <span class="token punctuation">,</span> <span class="token boolean">nil</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<span class="token comment">// server_test.go</span> <span class="token keyword">package</span> main <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"net/http"</span> <span class="token string">"net/http/httptest"</span> <span class="token string">"testing"</span> <span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token function">TestWelcome</span> <span class="token punctuation">(</span> t <span class="token operator">*</span> testing <span class="token punctuation">.</span> T <span class="token punctuation">)</span> <span class="token punctuation">{</span> mux <span class="token operator">:=</span> http <span class="token punctuation">.</span> <span class="token function">NewServeMux</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> mux <span class="token punctuation">.</span> <span class="token function">HandleFunc</span> <span class="token punctuation">(</span> <span class="token string">"/"</span> <span class="token punctuation">,</span> welcome <span class="token punctuation">)</span> writer <span class="token operator">:=</span> httptest <span class="token punctuation">.</span> <span class="token function">NewRecorder</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> request <span class="token punctuation">,</span> <span class="token boolean">_</span> <span class="token operator">:=</span> http <span class="token punctuation">.</span> <span class="token function">NewRequest</span> <span class="token punctuation">(</span> <span class="token string">"GET"</span> <span class="token punctuation">,</span> <span class="token string">"/"</span> <span class="token punctuation">,</span> <span class="token boolean">nil</span> <span class="token punctuation">)</span> mux <span class="token punctuation">.</span> <span class="token function">ServeHTTP</span> <span class="token punctuation">(</span> writer <span class="token punctuation">,</span> request <span class="token punctuation">)</span> <span class="token keyword">if</span> writer <span class="token punctuation">.</span> Code <span class="token operator">!=</span> <span class="token number">200</span> <span class="token punctuation">{</span> t <span class="token punctuation">.</span> <span class="token function">Errorf</span> <span class="token punctuation">(</span> <span class="token string">"Response code is %v"</span> <span class="token punctuation">,</span> writer <span class="token punctuation">.</span> Code <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- The simple
Welcome
function returns theclient
theWelcome to our website
message when the user visitshttp//localhost:3000
. - The
TestWelcome
function will need to create a separate webserver (with the default multiplexer of the net / http library). The result status code returned is checked, if it is different from200
then the test will fail.
3. Write testcase using a 3rd party library
Libraries officially supported by Go Team such as testing
or httptesting
are simple, easy to learn, and easy to use. However, for medium to large applications, the need for more test cases or the use of more advanced writing methods such as double tests , they show a certain limitation. It’s time to get more powerful tools from 3rd parties.
Gocheck
Install :
1 2 |
go get -u gopkg.in/check.v1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
<span class="token comment">// person_test.go</span> <span class="token keyword">package</span> demo_test <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"testing"</span> <span class="token punctuation">.</span> <span class="token string">"gopkg.in/check.v1"</span> <span class="token punctuation">)</span> <span class="token comment">// Hook up gocheck into the "go test" runner.</span> <span class="token keyword">func</span> <span class="token function">Test</span> <span class="token punctuation">(</span> t <span class="token operator">*</span> testing <span class="token punctuation">.</span> T <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">TestingT</span> <span class="token punctuation">(</span> t <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">type</span> Person <span class="token keyword">struct</span> <span class="token punctuation">{</span> name <span class="token builtin">string</span> age <span class="token builtin">uint64</span> country <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> p <span class="token operator">*</span> Person <span class="token punctuation">)</span> <span class="token function">IsAdult</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> p <span class="token punctuation">.</span> age <span class="token operator"><</span> <span class="token number">18</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> p <span class="token operator">*</span> Person <span class="token punctuation">)</span> <span class="token function">IsVietNamese</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> p <span class="token punctuation">.</span> country <span class="token operator">==</span> <span class="token string">"VietNam"</span> <span class="token operator">||</span> p <span class="token punctuation">.</span> country <span class="token operator">==</span> <span class="token string">"VN"</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token keyword">var</span> <span class="token boolean">_</span> <span class="token operator">=</span> <span class="token function">Suite</span> <span class="token punctuation">(</span> <span class="token operator">&</span> Person <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> s <span class="token operator">*</span> Person <span class="token punctuation">)</span> <span class="token function">TestIsAdult</span> <span class="token punctuation">(</span> c <span class="token operator">*</span> C <span class="token punctuation">)</span> <span class="token punctuation">{</span> conglt <span class="token operator">:=</span> Person <span class="token punctuation">{</span> <span class="token string">"conglt"</span> <span class="token punctuation">,</span> <span class="token number">20</span> <span class="token punctuation">,</span> <span class="token string">"VietNam"</span> <span class="token punctuation">}</span> c <span class="token punctuation">.</span> <span class="token function">Assert</span> <span class="token punctuation">(</span> conglt <span class="token punctuation">.</span> <span class="token function">IsAdult</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> Equals <span class="token punctuation">,</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> s <span class="token operator">*</span> Person <span class="token punctuation">)</span> <span class="token function">TestIsVietNamese</span> <span class="token punctuation">(</span> c <span class="token operator">*</span> C <span class="token punctuation">)</span> <span class="token punctuation">{</span> conglt <span class="token operator">:=</span> Person <span class="token punctuation">{</span> <span class="token string">"conglt"</span> <span class="token punctuation">,</span> <span class="token number">20</span> <span class="token punctuation">,</span> <span class="token string">"DaiViet"</span> <span class="token punctuation">}</span> c <span class="token punctuation">.</span> <span class="token function">Assert</span> <span class="token punctuation">(</span> conglt <span class="token punctuation">.</span> <span class="token function">IsVietNamese</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> Equals <span class="token punctuation">,</span> <span class="token boolean">false</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
1 2 |
<span class="token keyword">func</span> <span class="token function">Suite</span> <span class="token punctuation">(</span> suite <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token keyword">interface</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
Suite
function is responsible for registering the object to be tested, in the above code implies that we need to test methods of structPerson
. Any method starting with the Test prefix will be considered a test method.- The function
func TestingT(testingT *testing.T)
will be responsible for running the test cases for the object registered in theSuite
function. - Suppose we create a new struct as
Personal
and replace the statementvar _ = Suite(&Person{})
withvar _ = Suite(&Personal{})
Run test go:
As we can see, no test cases are run because we didn’t write any functions to test Personal
. Returning to the same and running go test
, we will have 2 testcase of Person
as follows.
Ginkgo
Ginkgo is a framework that supports testing in Go. Compared to Gocheck , Ginkgo is strong, as well as supports more features. If you have ever written tests for Javascript, you will probably be familiar with Ginkgo.
Install :
1 2 3 |
go get github.com/onsi/ginkgo/ginkgo go get github.com/onsi/gomega/ <span class="token punctuation">..</span> . |
Along with Ginko , we install Gomega as a matcher / assertion library, similar to the Chai library in Javascript. It helps to check that the return values are as expected.
Demo
In this example, we define a struct
Book containing three information and a CategoryByLength
method to sort books by page number. Larger than 300 pages is of the NOVEL
format, less than 300 pages return SHORT STORY
.
1 2 3 4 |
<span class="token function">mkdir</span> ginkgo <span class="token function">cd</span> ginkgo go mod int github.com/conglt10/test-ginkgo <span class="token comment"># Tên package bạn có thể đặt tên bất kỳ</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<span class="token comment">// book.go</span> <span class="token keyword">package</span> book <span class="token keyword">type</span> Book <span class="token keyword">struct</span> <span class="token punctuation">{</span> Title <span class="token builtin">string</span> Author <span class="token builtin">string</span> Pages <span class="token builtin">uint64</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> b <span class="token operator">*</span> Book <span class="token punctuation">)</span> <span class="token function">CategoryByLength</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> b <span class="token punctuation">.</span> Pages <span class="token operator">>=</span> <span class="token number">300</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">"NOVEL"</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token string">"SHORT STORY"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<span class="token comment">// book_test.go</span> <span class="token keyword">package</span> book_test <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token punctuation">.</span> <span class="token string">"github.com/conglt10/test-ginkgo"</span> <span class="token punctuation">.</span> <span class="token string">"github.com/onsi/ginkgo"</span> <span class="token punctuation">.</span> <span class="token string">"github.com/onsi/gomega"</span> <span class="token punctuation">)</span> <span class="token keyword">var</span> <span class="token boolean">_</span> <span class="token operator">=</span> <span class="token function">Describe</span> <span class="token punctuation">(</span> <span class="token string">"Book"</span> <span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> <span class="token punctuation">(</span> longBook Book shortBook Book <span class="token punctuation">)</span> <span class="token function">BeforeEach</span> <span class="token punctuation">(</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> longBook <span class="token operator">=</span> Book <span class="token punctuation">{</span> Title <span class="token punctuation">:</span> <span class="token string">"Les Miserables"</span> <span class="token punctuation">,</span> Author <span class="token punctuation">:</span> <span class="token string">"Victor Hugo"</span> <span class="token punctuation">,</span> Pages <span class="token punctuation">:</span> <span class="token number">1488</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> shortBook <span class="token operator">=</span> Book <span class="token punctuation">{</span> Title <span class="token punctuation">:</span> <span class="token string">"Fox In Socks"</span> <span class="token punctuation">,</span> Author <span class="token punctuation">:</span> <span class="token string">"Dr. Seuss"</span> <span class="token punctuation">,</span> Pages <span class="token punctuation">:</span> <span class="token number">24</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token function">Describe</span> <span class="token punctuation">(</span> <span class="token string">"Categorizing book length"</span> <span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">Context</span> <span class="token punctuation">(</span> <span class="token string">"With more than 300 pages"</span> <span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">It</span> <span class="token punctuation">(</span> <span class="token string">"should be a novel"</span> <span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">Expect</span> <span class="token punctuation">(</span> longBook <span class="token punctuation">.</span> <span class="token function">CategoryByLength</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">To</span> <span class="token punctuation">(</span> <span class="token function">Equal</span> <span class="token punctuation">(</span> <span class="token string">"NOVEL"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token function">Context</span> <span class="token punctuation">(</span> <span class="token string">"With fewer than 300 pages"</span> <span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">It</span> <span class="token punctuation">(</span> <span class="token string">"should be a short story"</span> <span class="token punctuation">,</span> <span class="token keyword">func</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">Expect</span> <span class="token punctuation">(</span> shortBook <span class="token punctuation">.</span> <span class="token function">CategoryByLength</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">To</span> <span class="token punctuation">(</span> <span class="token function">Equal</span> <span class="token punctuation">(</span> <span class="token string">"SHORT STORY"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> |
- File
book_test.go
we write test to test theCategoryByLength
method - We fake 2 variables wild data for 2 types of books
- When calling the
CategoryByLength
method with thelongBook
variable, we use the functions of the Gomega library to check if the expected return value isNOVEL
or not? Same with theshortBook
variable.
Just run the test
References
https://www.manning.com/books/go-web-programming
https://medium.com/rungo/unit-testing-made-easy-in-go-25077669318