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

Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
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
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
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
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
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
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 

Recently uploaded (20)

Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
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
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
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...
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
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
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 

Jaap Groeneveld - Go Unit Testing Workshop