SlideShare a Scribd company logo
1 of 24
Download to read offline
Golang dot testing
Trip down the rabbit hole
Richa’rd Kova’cs
October 2020
Me, myself and I
● Kubernetes Network Engineer
● @ IBM Cloud
● 6 years in Go space
● Many years of DevOps background
● Open Source activist
● Known as mhmxs
○ Twitter
○ Linkedin
Agenda
● Built-in framework
○ The basics
○ Table driven tests
○ Code coverage
○ Race detection
● Mocks and fakes
● Monkey patching
● Helpers
● Dependency Injection
Built-in framework
func plus(a, b int) int {
return a + b
}
func TestPlus(t *testing.T) {
res := plus(1, 1)
if 2 != res {
t.Errorf( "Result not match: %d" , res)
}
}
# go test
PASS
ok mhmxs/golang-dot-testing 0.006s
Built-in framework - The basics
func TestPlusTable(t *testing.T) {
tests := []struct {
a int
b int
out int
}{
{1, 1, 2},
{1, 2, 3},
}
for i, s := range tests {
res := plus(s.a, s.b)
if s.out != res {
t.Errorf( "Result not match: %d at %d" , res,
i)
}
}
# go test
PASS
ok mhmxs/golang-dot-testing 0.006s
Built-in framework - Table driven tests
# go test -cover -coverprofile=cover.out
PASS
coverage: 100.0% of statements
ok mhmxs/golang-dot-testing 0.006s
# go tool cover -html=cover.out
Built-in framework - Code coverage
func racer() {
m := map[int]string{}
go func() {
m[1] = "a"
}()
m[2] = "b"
}
func TestRacer(t *testing.T) {
racer()
}
# go test -race
==================
WARNING: DATA RACE
Write at 0x00c4200da000 by goroutine 9:
runtime.mapassign_fast64()
/usr/local/Cellar/go/1.9.2/libexec/src/runtime/hashmap_fast.go:510 +0x0
mhmxs/golang-dot-testing/basics.racer.func1()
/Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics.go:10 +0x51
Previous write at 0x00c4200da000 by goroutine 8:
runtime.mapassign_fast64()
/usr/local/Cellar/go/1.9.2/libexec/src/runtime/hashmap_fast.go:510 +0x0
mhmxs/golang-dot-testing/basics.racer()
/Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics.go:12 +0xa3
mhmxs/golang-dot-testing/basics.TestRacer()
/Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics_test.go:32 +0x2f
testing.tRunner()
/usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:746 +0x16c
Goroutine 9 (running) created at:
mhmxs/golang-dot-testing/basics.racer()
/Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics.go:9 +0x80
mhmxs/golang-dot-testing/basics.TestRacer()
/Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics_test.go:32 +0x2f
testing.tRunner()
/usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:746 +0x16c
Goroutine 8 (finished) created at:
testing.(*T).Run()
/usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:789 +0x568
testing.runTests.func1()
/usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:1004 +0xa7
testing.tRunner()
/usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:746 +0x16c
testing.runTests()
/usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:1002 +0x521
testing.(*M).Run()
/usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:921 +0x206
main.main()
mhmxs/golang-dot-testing/basics/_test/_testmain.go:48 +0x1d3
==================
FAIL
exit status 1
FAIL mhmxs/golang-dot-testing/basics 0.011s
Built-in framework - Race detection
Mock and fakes
Mocks and fakes
● Has many mocking framework
○ GoMock
○ Pegomock
○ Counterfeiter
○ Hel
○ Mockery
○ Testify
● Good integration with built-in framework
● All* based on code generation
● Some of them are supporting compiler directives a.k.a. //go:generate
* What i discovered
Monkey patching
func main() {
monkey.Patch(fmt.Println, func(a ...interface{}) (n int, err error) {
s := make([]interface{}, len(a))
for i, v := range a {
s[i] = strings.Replace(fmt.Sprint(v), "hell", "*heck*", -1)
}
return fmt.Fprintln(os.Stdout, s ...)
})
fmt.Println( "what the hell?" ) // what the *heck*?
}
Monkey patching
● Rewriting the running executable at runtime
● Useful because Go’s procedural design concept
● Bouk’s monkey is one of the favorites
Monkey patching - Problems
● Happens at runtime, so issues will occur on first run
● Doesn’t test production code, it tests something which never runs in prod
● Easy to forget dependencies and create cross module test instead of unit
● Only single thread test execution is possible
● Out of control, last override wins
Helpers
● Easy assertions
● Mocking framework
● Test suits
type MyMock struct{
mock.Mock
}
func TestTestify(t *testing.T) {
assert.Equal(t, 1, 1, "Not match. WTH?")
mock := new(MyMock)
mock.On("DoSomething", "input").Return("output")
funcUnderTest(mock)
mock.AssertExpectations(t)
}
type ExampleTestSuite struct {
suite.Suite
VariableThatShouldStartAtFive int
}
func (suite *ExampleTestSuite) SetupTest() {
suite.VariableThatShouldStartAtFive = 5
}
func (suite *ExampleTestSuite) TestExample() {
assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive)
}
func TestExampleTestSuite(t *testing.T) {
suite.Run(t, new(ExampleTestSuite))
}
Helpers - Testify
Helpers - Gopwt
⬢ Structure your BDD-style tests expressively
○ Describe, Context and When container blocks
○ BeforeEach and AfterEach blocks for setup and tear down
○ BeforeSuite and AfterSuite blocks to prep for and cleanup
after a suite
⬢ A comprehensive test runner that lets you
○ Mark specs as pending
○ Run your tests in random order, and then reuse random seeds
to replicate the same order
○ Break up your test suite into parallel processes for
straightforward test parallelization
⬢ Watches packages for changes, then reruns tests. Run tests
immediately as you develop
func TestCalc(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Calculator Suite")
}
var _ = Describe("Calculator", func() {
Describe("Add numbers", func() {
Context("1 and 2", func() {
It("should be 3", func() {
Expect(Add(1, 2)).To(Equal(3))
})
})
})
Describe("Subtract numbers", func() {
Context("3 from 5", func() {
It("should be 2", func() {
Expect(Subtract(5, 3)).To(Equal(2))
})
})
})
})
Helpres - Ginkgo ‘n Gomega
Dependency Injection
God helps those who help themselves
func DescribeCredential (c *cli.Context) {
client := NewOAuth2HTTPClient("localhost", "user", "password")
params := credentials.NewGetCredentialParams().WithName( c.String(FlName.Name))
resp, err := client.Credentials.GetCredential(params)
if err != nil {
panic(err.Error())
}
println(resp.Payload.ID)
}
Dependency Injection
func DescribeCredential (c *cli.Context) {
client := NewOAuth2HTTPClient("localhost", "user", "password")
println(describeCredentialImpl(c.String, client.Credentials))
}
type credentialClient interface {
GetCredential( *credentials.GetCredentialParams) ( *credentials.GetCredentialOK, error)
}
func describeCredentialImpl (nameFinder func(string) string, client credentialClient) int64 {
params := credentials.NewGetCredentialParams().WithName( nameFinder(FlName.Name))
resp, err := client.GetCredential(params)
if err != nil {
panic(err.Error())
}
return resp.Payload.ID
}
Dependency Injection
type mockClient struct{}
func (mc mockClient) GetCredential(params *credentials.GetCredentialParams) ( *credentials.GetCredentialOK, error) {
return &credentials.GetCredentialOK{Payload: &models.CredentialResponse{ID: 0}}, nil
}
func TestDesribeCredential (t *testing.T) {
nameFinder := func(in string) string {
return "name"
}
if 0 != describeCredentialImpl(nameFinder, mockClient{}) {
t.Error( "ID not match" )
}
}
Dependency Injection
type mockClient struct {
names chan (string)
}
func (mc mockClient) GetCredential(params *credentials.GetCredentialParams) ( *credentials.GetCredentialOK, error) {
mc.names <- params.Name
defer close(mc.names)
return &credentials.GetCredentialOK{Payload: &models.CredentialResponse{ID: 0}}, nil
}
func TestDesribeCredentialParams (t *testing.T) {
...
mc := mockClient{make( chan string)}
go describeCredentialImpl(nameFinder, mc)
if "name" != <-mc.names {
t.Error( "Name not match" )
}
}
Advanced techniques - Side effect
Dependency Injection
● Easier to avoid tight code coupling
● Enforces to use SOLID design pattern
● Enforces to mock all dependencies
● Full control over side effects
● Supports parallel test execution
Any question?

More Related Content

What's hot

An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test frameworkAbner Chih Yi Huang
 
Pattern printing programs
Pattern printing programsPattern printing programs
Pattern printing programsMukesh Tekwani
 
Going On with the Check of Geant4
Going On with the Check of Geant4Going On with the Check of Geant4
Going On with the Check of Geant4Andrey Karpov
 
Print Testing
Print TestingPrint Testing
Print Testingdonwelch
 
An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAndrey Karpov
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsClare Macrae
 
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017Andrey Karpov
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioAndrey Karpov
 
MUTANTS KILLER - PIT: state of the art of mutation testing system
MUTANTS KILLER - PIT: state of the art of mutation testing system MUTANTS KILLER - PIT: state of the art of mutation testing system
MUTANTS KILLER - PIT: state of the art of mutation testing system Tarin Gamberini
 
Machine Learning on Code - SF meetup
Machine Learning on Code - SF meetupMachine Learning on Code - SF meetup
Machine Learning on Code - SF meetupsource{d}
 
Checking the Qt 5 Framework
Checking the Qt 5 FrameworkChecking the Qt 5 Framework
Checking the Qt 5 FrameworkAndrey Karpov
 
Unit Testing with Python
Unit Testing with PythonUnit Testing with Python
Unit Testing with PythonMicroPyramid .
 
Dublin ALT.NET session Thu Oct 24 2013
Dublin ALT.NET session Thu Oct 24 2013Dublin ALT.NET session Thu Oct 24 2013
Dublin ALT.NET session Thu Oct 24 2013Ruben Bartelink
 
The real beginner's guide to android testing
The real beginner's guide to android testingThe real beginner's guide to android testing
The real beginner's guide to android testingEric (Trung Dung) Nguyen
 
C# console programms
C# console programmsC# console programms
C# console programmsYasir Khan
 
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system Tarin Gamberini
 

What's hot (20)

An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test framework
 
Python unit testing
Python unit testingPython unit testing
Python unit testing
 
Pattern printing programs
Pattern printing programsPattern printing programs
Pattern printing programs
 
Going On with the Check of Geant4
Going On with the Check of Geant4Going On with the Check of Geant4
Going On with the Check of Geant4
 
Print Testing
Print TestingPrint Testing
Print Testing
 
C# labprograms
C# labprogramsC# labprograms
C# labprograms
 
An Experiment with Checking the glibc Library
An Experiment with Checking the glibc LibraryAn Experiment with Checking the glibc Library
An Experiment with Checking the glibc Library
 
Mutation testing in Java
Mutation testing in JavaMutation testing in Java
Mutation testing in Java
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop Applications
 
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
PVS-Studio. Static code analyzer. Windows/Linux, C/C++/C#. 2017
 
Checking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-StudioChecking Clang 11 with PVS-Studio
Checking Clang 11 with PVS-Studio
 
MUTANTS KILLER - PIT: state of the art of mutation testing system
MUTANTS KILLER - PIT: state of the art of mutation testing system MUTANTS KILLER - PIT: state of the art of mutation testing system
MUTANTS KILLER - PIT: state of the art of mutation testing system
 
Machine Learning on Code - SF meetup
Machine Learning on Code - SF meetupMachine Learning on Code - SF meetup
Machine Learning on Code - SF meetup
 
Checking the Qt 5 Framework
Checking the Qt 5 FrameworkChecking the Qt 5 Framework
Checking the Qt 5 Framework
 
Unit Testing with Python
Unit Testing with PythonUnit Testing with Python
Unit Testing with Python
 
delegates
delegatesdelegates
delegates
 
Dublin ALT.NET session Thu Oct 24 2013
Dublin ALT.NET session Thu Oct 24 2013Dublin ALT.NET session Thu Oct 24 2013
Dublin ALT.NET session Thu Oct 24 2013
 
The real beginner's guide to android testing
The real beginner's guide to android testingThe real beginner's guide to android testing
The real beginner's guide to android testing
 
C# console programms
C# console programmsC# console programms
C# console programms
 
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system
 

Similar to Golang dot-testing-lite

Test strategies for data processing pipelines, v2.0
Test strategies for data processing pipelines, v2.0Test strategies for data processing pipelines, v2.0
Test strategies for data processing pipelines, v2.0Lars Albertsson
 
Robust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time ChecksRobust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time ChecksStoyan Nikolov
 
Go 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoGo 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoRodolfo Carvalho
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockRobot Media
 
Unit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon GaliciaUnit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon GaliciaRobot Media
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot NetNeeraj Kaushik
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Howsatesgoral
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
10 reasons to be excited about go
10 reasons to be excited about go10 reasons to be excited about go
10 reasons to be excited about goDvir Volk
 
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDTEclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDTElena Laskavaia
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
Jaap Groeneveld - Go Unit Testing Workshop
Jaap Groeneveld - Go Unit Testing WorkshopJaap Groeneveld - Go Unit Testing Workshop
Jaap Groeneveld - Go Unit Testing WorkshopJaapGroeneveld2
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoinknight1128
 
maXbox Starter 36 Software Testing
maXbox Starter 36 Software TestingmaXbox Starter 36 Software Testing
maXbox Starter 36 Software TestingMax Kleiner
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Gianluca Padovani
 
Adam Sitnik "State of the .NET Performance"
Adam Sitnik "State of the .NET Performance"Adam Sitnik "State of the .NET Performance"
Adam Sitnik "State of the .NET Performance"Yulia Tsisyk
 
State of the .Net Performance
State of the .Net PerformanceState of the .Net Performance
State of the .Net PerformanceCUSTIS
 

Similar to Golang dot-testing-lite (20)

Test strategies for data processing pipelines, v2.0
Test strategies for data processing pipelines, v2.0Test strategies for data processing pipelines, v2.0
Test strategies for data processing pipelines, v2.0
 
Robust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time ChecksRobust C++ Task Systems Through Compile-time Checks
Robust C++ Task Systems Through Compile-time Checks
 
RxJava on Android
RxJava on AndroidRxJava on Android
RxJava on Android
 
Go 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX GoGo 1.10 Release Party - PDX Go
Go 1.10 Release Party - PDX Go
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
 
Unit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon GaliciaUnit testing en iOS @ MobileCon Galicia
Unit testing en iOS @ MobileCon Galicia
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
Parallel Programming With Dot Net
Parallel Programming With Dot NetParallel Programming With Dot Net
Parallel Programming With Dot Net
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Hows
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
10 reasons to be excited about go
10 reasons to be excited about go10 reasons to be excited about go
10 reasons to be excited about go
 
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDTEclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
Eclipse Con 2015: Codan - a C/C++ Code Analysis Framework for CDT
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
Jaap Groeneveld - Go Unit Testing Workshop
Jaap Groeneveld - Go Unit Testing WorkshopJaap Groeneveld - Go Unit Testing Workshop
Jaap Groeneveld - Go Unit Testing Workshop
 
Golang
GolangGolang
Golang
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 
maXbox Starter 36 Software Testing
maXbox Starter 36 Software TestingmaXbox Starter 36 Software Testing
maXbox Starter 36 Software Testing
 
Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)
 
Adam Sitnik "State of the .NET Performance"
Adam Sitnik "State of the .NET Performance"Adam Sitnik "State of the .NET Performance"
Adam Sitnik "State of the .NET Performance"
 
State of the .Net Performance
State of the .Net PerformanceState of the .Net Performance
State of the .Net Performance
 

More from Richárd Kovács

Crossplane and a story about scaling Kubernetes custom resources.pdf
Crossplane and a story about scaling Kubernetes custom resources.pdfCrossplane and a story about scaling Kubernetes custom resources.pdf
Crossplane and a story about scaling Kubernetes custom resources.pdfRichárd Kovács
 
eBPF in the view of a storage developer
eBPF in the view of a storage developereBPF in the view of a storage developer
eBPF in the view of a storage developerRichárd Kovács
 
I wanna talk about nsenter
I wanna talk about nsenterI wanna talk about nsenter
I wanna talk about nsenterRichárd Kovács
 
First impression of the new cloud native programming language ballerina
First impression of the new cloud native programming language ballerinaFirst impression of the new cloud native programming language ballerina
First impression of the new cloud native programming language ballerinaRichárd Kovács
 

More from Richárd Kovács (6)

Crossplane and a story about scaling Kubernetes custom resources.pdf
Crossplane and a story about scaling Kubernetes custom resources.pdfCrossplane and a story about scaling Kubernetes custom resources.pdf
Crossplane and a story about scaling Kubernetes custom resources.pdf
 
Discoblocks.pptx.pdf
Discoblocks.pptx.pdfDiscoblocks.pptx.pdf
Discoblocks.pptx.pdf
 
eBPF in the view of a storage developer
eBPF in the view of a storage developereBPF in the view of a storage developer
eBPF in the view of a storage developer
 
I wanna talk about nsenter
I wanna talk about nsenterI wanna talk about nsenter
I wanna talk about nsenter
 
First impression of the new cloud native programming language ballerina
First impression of the new cloud native programming language ballerinaFirst impression of the new cloud native programming language ballerina
First impression of the new cloud native programming language ballerina
 
Golang dot-testing
Golang dot-testingGolang dot-testing
Golang dot-testing
 

Recently uploaded

UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URLRuncy Oommen
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarPrecisely
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Brian Pichman
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 

Recently uploaded (20)

20150722 - AGV
20150722 - AGV20150722 - AGV
20150722 - AGV
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URL
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
AI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity WebinarAI You Can Trust - Ensuring Success with Data Integrity Webinar
AI You Can Trust - Ensuring Success with Data Integrity Webinar
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 

Golang dot-testing-lite

  • 1. Golang dot testing Trip down the rabbit hole Richa’rd Kova’cs October 2020
  • 2. Me, myself and I ● Kubernetes Network Engineer ● @ IBM Cloud ● 6 years in Go space ● Many years of DevOps background ● Open Source activist ● Known as mhmxs ○ Twitter ○ Linkedin
  • 3. Agenda ● Built-in framework ○ The basics ○ Table driven tests ○ Code coverage ○ Race detection ● Mocks and fakes ● Monkey patching ● Helpers ● Dependency Injection
  • 5. func plus(a, b int) int { return a + b } func TestPlus(t *testing.T) { res := plus(1, 1) if 2 != res { t.Errorf( "Result not match: %d" , res) } } # go test PASS ok mhmxs/golang-dot-testing 0.006s Built-in framework - The basics
  • 6. func TestPlusTable(t *testing.T) { tests := []struct { a int b int out int }{ {1, 1, 2}, {1, 2, 3}, } for i, s := range tests { res := plus(s.a, s.b) if s.out != res { t.Errorf( "Result not match: %d at %d" , res, i) } } # go test PASS ok mhmxs/golang-dot-testing 0.006s Built-in framework - Table driven tests
  • 7. # go test -cover -coverprofile=cover.out PASS coverage: 100.0% of statements ok mhmxs/golang-dot-testing 0.006s # go tool cover -html=cover.out Built-in framework - Code coverage
  • 8. func racer() { m := map[int]string{} go func() { m[1] = "a" }() m[2] = "b" } func TestRacer(t *testing.T) { racer() } # go test -race ================== WARNING: DATA RACE Write at 0x00c4200da000 by goroutine 9: runtime.mapassign_fast64() /usr/local/Cellar/go/1.9.2/libexec/src/runtime/hashmap_fast.go:510 +0x0 mhmxs/golang-dot-testing/basics.racer.func1() /Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics.go:10 +0x51 Previous write at 0x00c4200da000 by goroutine 8: runtime.mapassign_fast64() /usr/local/Cellar/go/1.9.2/libexec/src/runtime/hashmap_fast.go:510 +0x0 mhmxs/golang-dot-testing/basics.racer() /Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics.go:12 +0xa3 mhmxs/golang-dot-testing/basics.TestRacer() /Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics_test.go:32 +0x2f testing.tRunner() /usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:746 +0x16c Goroutine 9 (running) created at: mhmxs/golang-dot-testing/basics.racer() /Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics.go:9 +0x80 mhmxs/golang-dot-testing/basics.TestRacer() /Users/rkovacs/GitHub/src/mhmxs/golang-dot-testing/basics/basics_test.go:32 +0x2f testing.tRunner() /usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:746 +0x16c Goroutine 8 (finished) created at: testing.(*T).Run() /usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:789 +0x568 testing.runTests.func1() /usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:1004 +0xa7 testing.tRunner() /usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:746 +0x16c testing.runTests() /usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:1002 +0x521 testing.(*M).Run() /usr/local/Cellar/go/1.9.2/libexec/src/testing/testing.go:921 +0x206 main.main() mhmxs/golang-dot-testing/basics/_test/_testmain.go:48 +0x1d3 ================== FAIL exit status 1 FAIL mhmxs/golang-dot-testing/basics 0.011s Built-in framework - Race detection
  • 10. Mocks and fakes ● Has many mocking framework ○ GoMock ○ Pegomock ○ Counterfeiter ○ Hel ○ Mockery ○ Testify ● Good integration with built-in framework ● All* based on code generation ● Some of them are supporting compiler directives a.k.a. //go:generate * What i discovered
  • 12. func main() { monkey.Patch(fmt.Println, func(a ...interface{}) (n int, err error) { s := make([]interface{}, len(a)) for i, v := range a { s[i] = strings.Replace(fmt.Sprint(v), "hell", "*heck*", -1) } return fmt.Fprintln(os.Stdout, s ...) }) fmt.Println( "what the hell?" ) // what the *heck*? } Monkey patching ● Rewriting the running executable at runtime ● Useful because Go’s procedural design concept ● Bouk’s monkey is one of the favorites
  • 13. Monkey patching - Problems ● Happens at runtime, so issues will occur on first run ● Doesn’t test production code, it tests something which never runs in prod ● Easy to forget dependencies and create cross module test instead of unit ● Only single thread test execution is possible ● Out of control, last override wins
  • 15. ● Easy assertions ● Mocking framework ● Test suits type MyMock struct{ mock.Mock } func TestTestify(t *testing.T) { assert.Equal(t, 1, 1, "Not match. WTH?") mock := new(MyMock) mock.On("DoSomething", "input").Return("output") funcUnderTest(mock) mock.AssertExpectations(t) } type ExampleTestSuite struct { suite.Suite VariableThatShouldStartAtFive int } func (suite *ExampleTestSuite) SetupTest() { suite.VariableThatShouldStartAtFive = 5 } func (suite *ExampleTestSuite) TestExample() { assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) } func TestExampleTestSuite(t *testing.T) { suite.Run(t, new(ExampleTestSuite)) } Helpers - Testify
  • 17. ⬢ Structure your BDD-style tests expressively ○ Describe, Context and When container blocks ○ BeforeEach and AfterEach blocks for setup and tear down ○ BeforeSuite and AfterSuite blocks to prep for and cleanup after a suite ⬢ A comprehensive test runner that lets you ○ Mark specs as pending ○ Run your tests in random order, and then reuse random seeds to replicate the same order ○ Break up your test suite into parallel processes for straightforward test parallelization ⬢ Watches packages for changes, then reruns tests. Run tests immediately as you develop func TestCalc(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Calculator Suite") } var _ = Describe("Calculator", func() { Describe("Add numbers", func() { Context("1 and 2", func() { It("should be 3", func() { Expect(Add(1, 2)).To(Equal(3)) }) }) }) Describe("Subtract numbers", func() { Context("3 from 5", func() { It("should be 2", func() { Expect(Subtract(5, 3)).To(Equal(2)) }) }) }) }) Helpres - Ginkgo ‘n Gomega
  • 18. Dependency Injection God helps those who help themselves
  • 19. func DescribeCredential (c *cli.Context) { client := NewOAuth2HTTPClient("localhost", "user", "password") params := credentials.NewGetCredentialParams().WithName( c.String(FlName.Name)) resp, err := client.Credentials.GetCredential(params) if err != nil { panic(err.Error()) } println(resp.Payload.ID) } Dependency Injection
  • 20. func DescribeCredential (c *cli.Context) { client := NewOAuth2HTTPClient("localhost", "user", "password") println(describeCredentialImpl(c.String, client.Credentials)) } type credentialClient interface { GetCredential( *credentials.GetCredentialParams) ( *credentials.GetCredentialOK, error) } func describeCredentialImpl (nameFinder func(string) string, client credentialClient) int64 { params := credentials.NewGetCredentialParams().WithName( nameFinder(FlName.Name)) resp, err := client.GetCredential(params) if err != nil { panic(err.Error()) } return resp.Payload.ID } Dependency Injection
  • 21. type mockClient struct{} func (mc mockClient) GetCredential(params *credentials.GetCredentialParams) ( *credentials.GetCredentialOK, error) { return &credentials.GetCredentialOK{Payload: &models.CredentialResponse{ID: 0}}, nil } func TestDesribeCredential (t *testing.T) { nameFinder := func(in string) string { return "name" } if 0 != describeCredentialImpl(nameFinder, mockClient{}) { t.Error( "ID not match" ) } } Dependency Injection
  • 22. type mockClient struct { names chan (string) } func (mc mockClient) GetCredential(params *credentials.GetCredentialParams) ( *credentials.GetCredentialOK, error) { mc.names <- params.Name defer close(mc.names) return &credentials.GetCredentialOK{Payload: &models.CredentialResponse{ID: 0}}, nil } func TestDesribeCredentialParams (t *testing.T) { ... mc := mockClient{make( chan string)} go describeCredentialImpl(nameFinder, mc) if "name" != <-mc.names { t.Error( "Name not match" ) } } Advanced techniques - Side effect
  • 23. Dependency Injection ● Easier to avoid tight code coupling ● Enforces to use SOLID design pattern ● Enforces to mock all dependencies ● Full control over side effects ● Supports parallel test execution