Standard package for Go unit testing: package testing
Package testing has in standard library since 2009. Convention of writing unit test in Go lang is: In file foo.go
, will have file foo_test.go
in same directory/folder. In file foo.go
has method BlaBla()
, and in foo_test.go
has method TestBlaBla()
accordingly.
I have file div.go
has content
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">package</span> table <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"errors"</span> <span class="token string">"fmt"</span> <span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token function">Divide</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y <span class="token builtin">int8</span><span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span><span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> y <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"cannot divide by 0"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> r <span class="token operator">:=</span> <span class="token function">float64</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token function">float64</span><span class="token punctuation">(</span>y<span class="token punctuation">)</span> result <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"%.2f"</span><span class="token punctuation">,</span> r<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator">&</span>result<span class="token punctuation">,</span> <span class="token boolean">nil</span> <span class="token punctuation">}</span> |
For unit testing, has file div_test.go
has content
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 | <span class="token keyword">package</span> table_test <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"errors"</span> <span class="token string">"testing"</span> <span class="token string">"github.com/donhuvy/Test-Driven-Development-in-Go/chapter04/table"</span> <span class="token string">"github.com/stretchr/testify/assert"</span> <span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token function">TestDivide</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> tests <span class="token operator">:=</span> <span class="token keyword">map</span><span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">]</span><span class="token keyword">struct</span> <span class="token punctuation">{</span> x<span class="token punctuation">,</span> y <span class="token builtin">int</span> wantErr <span class="token builtin">error</span> want <span class="token builtin">string</span> <span class="token punctuation">}</span><span class="token punctuation">{</span> <span class="token string">"pos x, pos y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">8</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">4</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"2.00"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"neg x, neg y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token operator">-</span><span class="token number">4</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token operator">-</span><span class="token number">8</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"0.50"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"equal x, y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">4</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">4</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"1.00"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"max x, pos y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">127</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"63.50"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"min x, pos y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token operator">-</span><span class="token number">128</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"-64.00"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"zero x, pos y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">2</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"0.00"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"pos x, zero y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">10</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> wantErr<span class="token punctuation">:</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"cannot divide by 0"</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"zero x, zero y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">,</span> wantErr<span class="token punctuation">:</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"cannot divide by 0"</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"max x, max y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token number">127</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token number">127</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"1.00"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"min x, min y"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>x<span class="token punctuation">:</span> <span class="token operator">-</span><span class="token number">128</span><span class="token punctuation">,</span> y<span class="token punctuation">:</span> <span class="token operator">-</span><span class="token number">128</span><span class="token punctuation">,</span> want<span class="token punctuation">:</span> <span class="token string">"1.00"</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token keyword">for</span> name<span class="token punctuation">,</span> rtc <span class="token operator">:=</span> <span class="token keyword">range</span> tests <span class="token punctuation">{</span> tc <span class="token operator">:=</span> rtc t<span class="token punctuation">.</span><span class="token function">Run</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span> <span class="token keyword">func</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> t<span class="token punctuation">.</span><span class="token function">Parallel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> x<span class="token punctuation">,</span> y <span class="token operator">:=</span> <span class="token function">int8</span><span class="token punctuation">(</span>tc<span class="token punctuation">.</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">int8</span><span class="token punctuation">(</span>tc<span class="token punctuation">.</span>y<span class="token punctuation">)</span> r<span class="token punctuation">,</span> err <span class="token operator">:=</span> table<span class="token punctuation">.</span><span class="token function">Divide</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span> <span class="token keyword">if</span> tc<span class="token punctuation">.</span>wantErr <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> tc<span class="token punctuation">.</span>wantErr<span class="token punctuation">,</span> err<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> assert<span class="token punctuation">.</span><span class="token function">Nil</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span> assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> tc<span class="token punctuation">.</span>want<span class="token punctuation">,</span> <span class="token operator">*</span>r<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> |
In this example, I used only Go standard library (supported by package testing
).
Run unit testing with verbose information
Command for unit test running
1 2 | firerose@firerose-desktop:~/Documents/github/Test-Driven-Development-in-Go$ go <span class="token builtin class-name">test</span> -run TestDivide ./chapter04/table/ -v |
Result
1 2 3 4 5 6 7 8 9 10 11 | <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>max_x<span class="token punctuation">,</span>_pos_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>pos_x<span class="token punctuation">,</span>_pos_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>pos_x<span class="token punctuation">,</span>_zero_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>zero_x<span class="token punctuation">,</span>_zero_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>zero_x<span class="token punctuation">,</span>_pos_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>max_x<span class="token punctuation">,</span>_max_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>neg_x<span class="token punctuation">,</span>_neg_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> <span class="token operator">--</span><span class="token operator">-</span> PASS<span class="token punctuation">:</span> TestDivide<span class="token operator">/</span>equal_x<span class="token punctuation">,</span>_y <span class="token punctuation">(</span><span class="token number">0.00</span>s<span class="token punctuation">)</span> PASS ok github<span class="token punctuation">.</span>com<span class="token operator">/</span>donhuvy<span class="token operator">/</span>Test<span class="token operator">-</span>Driven<span class="token operator">-</span>Development<span class="token operator">-</span>in<span class="token operator">-</span>Go<span class="token operator">/</span>chapter04<span class="token operator">/</span>table <span class="token number">0.002</span>s |
*testing.Parallel()
create parallel flows for unit testing in concurrency.
Third-party library support Go lang unit testing
With supporting from package github.com/strectchr/testify
, *assert.Nil()
for assertion Nil
value. *assert.Equal()
for assertion of equalitation.
assert.Equal
receive 3 parameters likes this, one and first parameter is *testing
, 2 next parameters are variable and value of variable:
1 2 | assert<span class="token punctuation">.</span><span class="token function">Equal</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> tc<span class="token punctuation">.</span>wantErr<span class="token punctuation">,</span> err<span class="token punctuation">)</span> |
assert.Nil()
receive 2 parameters likes this
1 2 | assert<span class="token punctuation">.</span><span class="token function">Nil</span><span class="token punctuation">(</span>t<span class="token punctuation">,</span> err<span class="token punctuation">)</span> |
Third-party libraries support Go lang unit testing
- Testify: https://github.com/stretchr/testify (as mentioned above)
- Mockery https://github.com/vektra/mockery Generate skeleton/simple source code for Go lang unit testing. On top of generated files, has comment header
1 2 | <span class="token comment">// Code generated by mockery v2.26.1. DO NOT EDIT.</span> |
In source code, you don’t see declaring mockery in go.mod
, it is tool installed to host machine.
Comand set Go to path
1 2 3 4 5 6 7 8 9 | firerose@firerose-desktop:~/Downloads/go/bin$ <span class="token builtin class-name">pwd</span> /home/firerose/Downloads/go/bin firerose@firerose-desktop:~/Downloads/go/bin$ <span class="token builtin class-name">export</span> <span class="token assign-left variable"><span class="token environment constant">PATH</span></span><span class="token operator">=</span>/home/firerose/Downloads/go/bin:<span class="token environment constant">$PATH</span> firerose@firerose-desktop:~/Downloads/go/bin$ <span class="token builtin class-name">echo</span> <span class="token environment constant">$PATH</span> /home/firerose/Downloads/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin firerose@firerose-desktop:~/Downloads/go/bin$ go version go version go1.20.4 linux/amd64 firerose@firerose-desktop:~/Downloads/go/bin$ |
Install Mockery by command
1 | <span class="token keyword">go</span> install github<span class="token punctuation">.</span>com<span class="token operator">/</span>vektra<span class="token operator">/</span>mockery<span class="token operator">/</span>v2@v2<span class="token punctuation">.</span><span class="token number">26.1</span> |