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

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
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
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
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
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
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 

Recently uploaded (20)

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
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
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
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
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
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 

Jaap Groeneveld - Go Unit Testing Workshop