SlideShare a Scribd company logo
1 of 43
Download to read offline
TestinginGo
JaapGroeneveld-jGroeneveld.de
Agenda
Whydowetest
Typesoftests
Testdrivendevelopment
TestinginGo
2
Whydowetest
Savetime
Confidentinyourchanges
Fasterfeedback
Increasequality
Preventregressions
Communicateanddocument
=>makeyourselfhappier
3
Typesoftests
UnitTests(fast)
IntegrationTests
End-to-EndTests(comprehensive)
SmokeTests
ConsumerDrivenContractTests
...
4
UnitTests
Focusonsmallparts
Reallyfast
Extensivetestcases
Runbydeveloper
Example:Sum(a,b)
https://martinfowler.com/bliki/UnitTest.html 5
Integrationtests
Dounitsworkcorrectlytogether?
Lessextensivetestcases
Runbydeveloper
Example:Webhandler->logic->DB.
6
UnitTestvsintegrationtests
https://martinfowler.com/bliki/UnitTest.html 7
End-To-Endtests
Fullstacktestagainstrealsystem
Externalboundariesmightbemocked(e.g.
WireMock)
Slow
RunbyCIsystem
Dependingonthesystem,youmightnot
needthem.
https://www.guru99.com/end-to-end-testing.html 8
TestPyramid
9
Testdrivendevelopment
Red,Green,Refactor
Onlyrefactorwhengreen
Benefits
Nountestedcode
Confidentrefactoring
Betterdesign(...othertalk)
Learngowithtests
10
11
GoTestBasics
Agenda
GeneralTesting
Whattotest
Subtests
Tabletests
Mocks
13
Go'stestfunctionalities
go test ./... picksuptestsdefinedin X_test.go files
Xisusuallythenameofthecodefile sum.go => sum_test.go
Testshavethesignature func TestX(t *testing.T)
Xisusuallythenameoftheunit(functionorstruct)
Testfailuresarereportedwith t.Error and t.Fatal
Youcanalsorunbenchmarkswith func Benchmark*(b *testing.B) appendix
YoucanalsorundefineExamplesfordocumentation func Example*() appendix
14
Asimpletest
func Sum(elements []int) int
func TestSum(t *testing.T) {
input := []int{1, 2, 3}
expected := 6
actual := Sum(input)
if actual != expected {
t.Errorf("expected %v but was %v", expected, actual)
}
}
15
CleanCode-Tests
Oneassertpertest.
Readable.
Fast.
Independent.
Repeatable.
(...othertalk)
16
1.Arrange
2.Act
3.Assert
17
Acleanersimpletest
func TestSum(t *testing.T) {
// Arrange
input := []int{1, 2, 3}
expected := 6
// Act
actual := Sum(input)
// Assert
if actual != expected {
t.Errorf("expected %v but was %v", expected, actual)
}
}
18
Yourturn!
Startanewproject,writesimpletestandletthetestguideyoutoimplementthe
method.
19
TestFrameworks
gotest
expected := "bar"
actual, err := Foo()
if err != nil {
t.Fatalf("got error %v", err)
}
if expected != actual {
t.Errorf("expected %v but got %v", expected, actual)
}
testify
actual, err := Foo()
require.Nil(t, err)
assert.Equal(t, "bar", actual)
20
TestFrameworks
Comparisonofgotestingframeworks(Testify,gocheck,gopwt,Ginkgo...)
https://github.com/bmuschko/go-testing-frameworks
21
Whattotest
Commoncase(Happypath)
Edgecases
Errorcases
22
Subtests
Letyouorganizeyourteststocommunicatetheintentionmoreclearly
func TestSum(t *testing.T) {
t.Run("returns the summed up elements", func(t *testing.T) {
// []...]
})
t.Run("returns zero for empty array", func(t *testing.T) {
// []...]
})
}
23
Tablebasedtests
Inaperfectworld,functionsjustrelyoninputandoutput.Thisiseasytotest.
func TestSum(t *testing.T) {
testCases := []struct {
Name string
Input []int
Expected int
}{
{
Name: "returns the summed up elements",
Input: []int{1, 2, 3},
Expected: 6,
},
{
Name: "returns zero for empty array",
Input: []int{}.
Expected: 0,
},
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
assert.Equal(t, tc.Expected, Sum(tc.input))
})
}
} 24
generateNodeName
CodeReview
25
TestDoubles
26
Testdoubles
Fakes:Workingimplementation
Stubs:Holdpredefineddata
Mocks:Registercallstheyreceiveanddonothing
Spies:Registercallstorealobjects
27
Whyusedoubles
Toreallytest"units"andnotthedependencies
Performance-Databases,Network...
Collaboration-Implementcodeagainstdependenciesthatdonotexist,yet.
28
SimpleMocks:Code
Wehaveafunction SendMail thatformatsamessageandusesthe MailSender to
senditout.
Sendingmailsisslowandwejustwanttoknowthatitwouldhappenwiththecorrect
message.
func SendMail(sender MailSender, recipient string) {
sender.Send("Good morning, " + recipient)
}
type MailSender interface {
Send(message string)
}
29
SimpleMocks:Test
func TestSendMail(t *testing.T) {
calledWith := ""
sender := MockMailSender{
SendFunc: func(message string) {
calledWith = message
},
}
SendMail(sender, "Tyrion")
if calledWith != "Good morning, Tyrion" {
t.Errorf("Was called with %q", calledWith)
}
}
30
SimpleMocks:Mock
type MockMailSender struct {
SendFunc func(message string)
}
func (s MockMailSender) Send(message string) {
s.SendFunc(message)
}
31
MockingFrameworks
gomockusescodegenerationtoprovidemocks
mockgen -source=mail_sender.go
func TestFoo(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
sender := NewMockMailSender(ctrl)
sender.
EXPECT().
Send("Good morning, Tyrion")
SendMail(sender, "Tyrion")
}
32
33
Randomthings
34
Writinghelpers
func equals(t *testing.T, a string, b string) {
t.Helper()
if a != b {
t.Errorf("%q is not %q", a, b)
}
}
35
httptest.NewRecorder
func TestGetPlayers(t *testing.T) {
playerStore := &StubPlayerStore{map[string]int{
"Pepper": 20,
}}
server := PlayerServer{playerStore}
request, _ := http.NewRequest(http.MethodGet, "/scores/pepper", nil)
response := httptest.NewRecorder()
server.ServeHTTP(response, request)
assert.Equal(t, http.StatusOK, response.Code)
assert.Equal(t, "20", response.Body.String())
}
Useashttp.ResponseWritertotestyourownhandlers
36
httptest.NewServer
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
// pass server.URL somewhere
Greattofakerealapisforintegrationtesting.
AlsoseeWireMockmockservertoconfigurearealserverifyouwanttotestthe
infrastructure.
37
TestingJSONresponses(schema)
func TestJSON(t *testing.T) {
reader := getJSONResponse()
err := schema.MatchJSON(
schema.Map{
"id": schema.IsInteger,
"name": "Max Mustermann",
"age": 42,
"height": schema.IsFloat,
"footsize": schema.IsPresent,
"address": schema.Map{
"street": schema.IsString,
"zip": schema.IsString,
},
"tags": schema.ArrayIncluding("red"),
},
reader,
)
}
https://github.com/jgroeneveld/schema 38
Examples
package stringutil_test
import (
"fmt"
"github.com/golang/example/stringutil"
)
func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
// Output: olleh
}
Examplesrunliketests,soweknow
theyarecorrect,andgenerate
documentation.
39
Benchmarks
func BenchmarkFib10(b *testing.B) {
// run the Fib function b.N times
for n := 0; n < b.N; n++ {
Fib(10)
}
}
% go test -bench=.
PASS
BenchmarkFib10 5000000 509 ns/op
ok github.com/davecheney/fib 3.084s
40
Setup/Teardown
func TestFoo() {
var teardown = setup()
defer teardown()
// ...
}
func setup() func() {
fmt.Println("this runs before test")
return func() {
fmt.Println("this runs after test")
}
}
Greatifyouneedtodosomethingbeforetestsrunandalsocleanupafterwards
e.g.disablelogging,prepare&cleandatabase,set/resetENV.
41
Globalhooks
Youcanplacea func init() inthepackage_testtorunbeforethetestsrun.
Better:InGo1.14wehavetheTestMain
func TestMain(m *testing.M) {
// call flag.Parse() here if TestMain uses flags
fmt.Println("this runs before test")
exitCode := m.Run()
fmt.Println("this runs after test")
os.Exit(exitCode)
}
42
quick.Checkforpropertytesting
Usethequickpackagetotestpropertieswithrandominputs
func TestPropertiesOfConversion(t *testing.T) {
t.Run("Conversion to roman and back to arabic yields initial input", func(t *testing.T) {
assertion := func(arabic int) bool {
roman := ConvertToRoman(arabic)
fromRoman := ConvertToArabic(roman)
return fromRoman == arabic
}
if err := quick.Check(assertion, nil); err != nil {
t.Error("failed checks", err)
}
})
}
43

More Related Content

Similar to Jaap Groeneveld - Go Unit Testing Workshop

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
 
单元测试必知必会
单元测试必知必会单元测试必知必会
单元测试必知必会智杰 付
 
The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180Mahmoud Samir Fayed
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
The Ring programming language version 1.3 book - Part 7 of 88
The Ring programming language version 1.3 book - Part 7 of 88The Ring programming language version 1.3 book - Part 7 of 88
The Ring programming language version 1.3 book - Part 7 of 88Mahmoud Samir Fayed
 
Tdd with python unittest for embedded c
Tdd with python unittest for embedded cTdd with python unittest for embedded c
Tdd with python unittest for embedded cBenux Wei
 
A Test Automation Framework
A Test Automation FrameworkA Test Automation Framework
A Test Automation FrameworkGregory Solovey
 
Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"LogeekNightUkraine
 
Mutation Testing: Start Hunting The Bugs
Mutation Testing: Start Hunting The BugsMutation Testing: Start Hunting The Bugs
Mutation Testing: Start Hunting The BugsAri Waller
 
Martin Gijsen - Effective Test Automation a la Carte
Martin Gijsen -  Effective Test Automation a la Carte Martin Gijsen -  Effective Test Automation a la Carte
Martin Gijsen - Effective Test Automation a la Carte TEST Huddle
 
Mutation Testing: Testing your tests
Mutation Testing: Testing your testsMutation Testing: Testing your tests
Mutation Testing: Testing your testsStephen Leigh
 
RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG Greg.Helton
 
Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytestSuraj Deshmukh
 
Xp Day 080506 Unit Tests And Mocks
Xp Day 080506 Unit Tests And MocksXp Day 080506 Unit Tests And Mocks
Xp Day 080506 Unit Tests And Mocksguillaumecarre
 
Generating characterization tests for legacy code
Generating characterization tests for legacy codeGenerating characterization tests for legacy code
Generating characterization tests for legacy codeJonas Follesø
 
Generatingcharacterizationtestsforlegacycode
GeneratingcharacterizationtestsforlegacycodeGeneratingcharacterizationtestsforlegacycode
GeneratingcharacterizationtestsforlegacycodeCarl Schrammel
 
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
 

Similar to Jaap Groeneveld - Go Unit Testing Workshop (20)

Tdd is not about testing (OOP)
Tdd is not about testing (OOP)Tdd is not about testing (OOP)
Tdd is not about testing (OOP)
 
单元测试必知必会
单元测试必知必会单元测试必知必会
单元测试必知必会
 
The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180The Ring programming language version 1.5.1 book - Part 12 of 180
The Ring programming language version 1.5.1 book - Part 12 of 180
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
The Ring programming language version 1.3 book - Part 7 of 88
The Ring programming language version 1.3 book - Part 7 of 88The Ring programming language version 1.3 book - Part 7 of 88
The Ring programming language version 1.3 book - Part 7 of 88
 
Testing Spring Applications
Testing Spring ApplicationsTesting Spring Applications
Testing Spring Applications
 
Tdd with python unittest for embedded c
Tdd with python unittest for embedded cTdd with python unittest for embedded c
Tdd with python unittest for embedded c
 
report
reportreport
report
 
A Test Automation Framework
A Test Automation FrameworkA Test Automation Framework
A Test Automation Framework
 
Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"Yevhen Tatarynov "From POC to High-Performance .NET applications"
Yevhen Tatarynov "From POC to High-Performance .NET applications"
 
Mutation Testing: Start Hunting The Bugs
Mutation Testing: Start Hunting The BugsMutation Testing: Start Hunting The Bugs
Mutation Testing: Start Hunting The Bugs
 
Martin Gijsen - Effective Test Automation a la Carte
Martin Gijsen -  Effective Test Automation a la Carte Martin Gijsen -  Effective Test Automation a la Carte
Martin Gijsen - Effective Test Automation a la Carte
 
Mutation Testing: Testing your tests
Mutation Testing: Testing your testsMutation Testing: Testing your tests
Mutation Testing: Testing your tests
 
RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG RPG Program for Unit Testing RPG
RPG Program for Unit Testing RPG
 
Python testing using mock and pytest
Python testing using mock and pytestPython testing using mock and pytest
Python testing using mock and pytest
 
Xp Day 080506 Unit Tests And Mocks
Xp Day 080506 Unit Tests And MocksXp Day 080506 Unit Tests And Mocks
Xp Day 080506 Unit Tests And Mocks
 
Generating characterization tests for legacy code
Generating characterization tests for legacy codeGenerating characterization tests for legacy code
Generating characterization tests for legacy code
 
Generatingcharacterizationtestsforlegacycode
GeneratingcharacterizationtestsforlegacycodeGeneratingcharacterizationtestsforlegacycode
Generatingcharacterizationtestsforlegacycode
 
Rhino Mocks
Rhino MocksRhino Mocks
Rhino Mocks
 
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
 

Recently uploaded

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 

Recently uploaded (20)

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 

Jaap Groeneveld - Go Unit Testing Workshop