{"id":5882,"date":"2015-07-27T16:15:48","date_gmt":"2015-07-27T13:15:48","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=5882"},"modified":"2015-12-16T11:30:58","modified_gmt":"2015-12-16T09:30:58","slug":"testing-in-go","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/","title":{"rendered":"Testing in Go"},"content":{"rendered":"<p>This post is based on a presentation I gave for the Boston Go group in May. You can <a href=\"https:\/\/youtu.be\/v_wz6E3uFRg\">watch the video here<\/a><\/p>\n<p>For me, Go is like coming back to formal programming after the crazy world of Ruby for a little while. It reminds me of C with all the sharp corners sanded off; Go is such a simple language.<\/p>\n<p>Some of my favorite things in the programming world are tests, web applications, and databases. Half of all my talks are about tests, in fact. So let\u2019s talk about testing in Go.<br \/>\n&nbsp;<\/p>\n<h2>Testing Basics<\/h2>\n<p>The most basic example of testing in Go just needs whatever package you\u2019re working in \u2014 you don\u2019t change it \u2014 you import \u201ctesting,\u201d and then any function that you start with Test is going to get run by Go\u2019s testing harness. It\u2019ll take one parameter (a testing T), and you can use that to call the different testing functions in Go.<\/p>\n<pre class=\" brush:php\">package basics\r\n\r\nimport (\r\n    \"encoding\/hex\"\r\n    \"testing\"\r\n)\r\n\r\nfunc TestTruth(t *testing.T) {\r\n    if true != true {\r\n        t.Error(\"everything I know is wrong\")\r\n    }\r\n}<\/pre>\n<p>So here, I\u2019m just making sure that <strong>true<\/strong> is equal to <strong>true<\/strong>. Instead of doing something in the affirmative and saying \u201c<strong>true<\/strong> is equal to <strong>true<\/strong>, or we should crash,\u201d I\u2019m saying \u201cIf <strong>true<\/strong> isn\u2019t <strong>true<\/strong> then there\u2019s an error.\u201d Generally, you talk about things in the worst case with Go, which I think flows with the way you write Go: calling methods and checking errors and doing something if something goes wrong.<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/07\/type-T.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-5885\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/07\/type-T.jpg\" alt=\"type-T\" width=\"860\" height=\"385\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/07\/type-T.jpg 885w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/07\/type-T-300x134.jpg 300w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<p>Let\u2019s talk about some of <a href=\"http:\/\/godoc.org\/testing\">the testing functions on T<\/a>. You can call errors, you can fail the tests, you can see if it failed. <strong>Fatal<\/strong> will make an error message, but it will also stop the test right where it is. You can also just log debugging stuff, so when you turn your verbosity up, you can see all your messages. You can leave them in there for yourself if you ever have to debug a test.<\/p>\n<pre class=\" brush:php\">func TestBroken(t *testing.T) {\r\n    if true != false {\r\n        t.Error(\"expected\", true, \"got\", false)\r\n    }\r\n\r\n    if 1+1 != 4 {\r\n        t.Fatal(\"Can't proceed!\", 1+1, 4)\r\n    }\r\n}<\/pre>\n<p>But 99 percent of the time, the only ones you\u2019ll care about are <strong>Error<\/strong> and <strong>Fatal<\/strong>. <strong>Fatal<\/strong> is just an error plus a fail. So <strong>Error<\/strong> is like you\u2019re making a big list of everything that\u2019s going wrong on this test; you can have a whole ton of errors, and this will list them all. But with <strong>Fatal<\/strong>, it will stop. You can\u2019t even do your other checks, so you have to pretty much bail out of the test at this point.<\/p>\n<table border=\"1\">\n<tbody>\n<tr>\n<td><a href=\"https:\/\/twitter.com\/share?text=%22Generally%2C+you+talk+about+things+in+the+worst+case+with+%23Golang%22+%E2%80%93+%40ngauthier&amp;url=http:\/\/blog.codeship.com\/testing-in-go\/\" target=\"_blank\">\u201cGenerally, you talk about things in the worst case with #Golang\u201d \u2013 @ngauthier<\/a><a href=\"https:\/\/twitter.com\/share?text=%22Generally%2C+you+talk+about+things+in+the+worst+case+with+%23Golang%22+%E2%80%93+%40ngauthier&amp;url=http:\/\/blog.codeship.com\/testing-in-go\/\" target=\"_blank\">Click To Tweet<\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Often, I\u2019ll just use <strong>Fatal<\/strong> because the tests depend on the pieces you\u2019ve created as you go along. But sometimes, if you have a big object with a ton of fields, it\u2019s nice to be able to do a lot of error statements and see exactly which ones worked and which ones didn\u2019t while you\u2019re trying to work on some database persistence, for example.<\/p>\n<pre class=\" brush:php\">$ go test -v .\/basics\/\r\n=== RUN TestBroken\r\n--- FAIL: TestBroken (0.00s)\r\n    package_test.go:13: expected true got false\r\n    package_test.go:17: Can\u2019t proceed! 2 4\r\nFAIL\r\nexit status 1\r\nFAIL github\/com\/ngauthier\/testing-go-presentation\/basics    0.006s<\/pre>\n<p>So when you run this, the error will say <strong>expected true got false<\/strong>, and then it will continue on to the fatal that says <strong>Can\u2019t proceed! 2 4<\/strong><\/p>\n<p>The neat thing here is that you can put as many arguments as you want into <strong>Error<\/strong> and <strong>Fatal<\/strong>, and it\u2019ll stringify them nicely. It\u2019s a really nice interface.<\/p>\n<pre class=\" brush:php\">func TestError(t *testing.T) {\r\n    dest := make([]byte, 0)\r\n    if _, err := hex.Decode(dest, []byte{8}); err != nil {\r\n        t.Error(err)\r\n    }\r\n}<\/pre>\n<pre class=\" brush:php\">$ go test -v -run Error .\/basics\/\r\n=== RUN TestError\r\n--- FAIL: TestError (0.00s)\r\n    package_test.go:27: encoding\/hex: odd length hex string\r\nFAIL\r\nexit status 1\r\nFAIL github\/com\/ngauthier\/testing-go-presentation\/basics    0.004s<\/pre>\n<p>A really common pattern in Go (and therefore in tests) is errors. In this case, I\u2019m going to decode some hex, and I put in some invalid bytes that aren\u2019t going to decode into hex. So when we run this, we get an error. You\u2019ll do the same thing as you do with a normal error check in Go, but then you just give that error directly to <strong>Error<\/strong>. It\u2019ll print your error out with a nice little line number where the error came out.<\/p>\n<pre class=\" brush:php\">$ go test -v -run Error .\/basics\/\r\n\r\n    -run regexp\r\n        Run only those tests and examples matching the regular expression.\r\n\r\n    -v\r\n        Verbose output: log all tests as they are run. Also print all text from Log and Logf calls even if the test succeeds.<\/pre>\n<p>You can give it a run with a regex, which can just be a string if you want to just run an individual test. That can help when you\u2019re refactoring, and you make a little change, and it breaks everything, and you have to go hunt down individual pieces and just want to focus on a piece of the puzzle.<\/p>\n<h2>Testing HTTP<\/h2>\n<p>To level up our example, let\u2019s talk about what a lot of people do with Go, which is HTTP servers.<\/p>\n<pre class=\" brush:php\">type App struct {\r\n    Message string\r\n}\r\n\r\nfunc (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {\r\n    w.Write([]byte(a.Message))\r\n}<\/pre>\n<p>Here\u2019s an app that stores a message. I\u2019m going to implement <strong>ServeHTTP<\/strong> on my app. That means that this app is going to function as an <strong>http.handler<\/strong>, so Go\u2019s HTTP server will be able to accept the app. All the app does is write the message out, no matter the parameters you give it. Pretty dumb server.<\/p>\n<pre class=\" brush:php\">func TestHello(t *testing.T) {\r\n    app := &amp;App{Message: \"hello\"}\r\n    s := httptest.NewServer(app) \/\/ http provides its own test objects\r\n    defer s.Close()\r\n\r\n    resp, err := http.Get(s.URL) \/\/ test from the outside\r\n    if err != nil {\r\n        t.Error(err)\r\n    }\r\n    if body, err := ioutil.ReadAll(resp.Body); err != nil {\r\n        t.Error(err)\r\n    } else if string(body) != \"hello\" {\r\n        t.Error(\"expected\", \"hello\", \"got\", body)\r\n    }\r\n}<\/pre>\n<p>I\u2019m going to test this by creating the app, then I\u2019m going to use the HTTP test package\u2019s <strong>NewServer<\/strong>, which is a lot like <strong>http.server<\/strong>. However, they\u2019ve done a couple of nice things for you \u2014 you don\u2019t have to specify the port that you want to run it on, for example. If there\u2019s a collision, they\u2019ll re-randomize the port for you. So you get your own little server that\u2019s going to work well in a test scenario.<\/p>\n<p>Then I\u2019m going to get on that server\u2019s URL; we\u2019re really testing from the outside. If you were to boot up a server, serving my app, and somebody hit it as an HTTP client and actually connected to that socket and made that request, what are you going to get? This is very different than if I had said <strong>app.servehttp<\/strong> and then given it a response writer and a request object.<\/p>\n<p>Now I\u2019m going to convert the body to a string and compare that to <strong>hello<\/strong>, which is what I initialized the message with. If that wasn\u2019t <strong>hello<\/strong>, I\u2019m going to do my error with <strong>expected<\/strong> and <strong>got<\/strong>. You\u2019ll notice that I still made <strong>expected<\/strong>, <strong>hello<\/strong>, and <strong>got<\/strong> as three separate strings with commas. It\u2019s nice to keep that format.<\/p>\n<pre class=\" brush:php\">func fakeApp(msg string) *httptest.Server {\r\n    app := &amp;App{Message: msg}\r\n    return httptest.NewServer(app)\r\n}\r\n\r\nfunc get(t *testing.T, s *httptest.Server, path string) string {\r\n    resp, err := http.Get(s.URL + path)\r\n    if err != nil {\r\n        t.Error(err)\r\n    }\r\n    body, err := ioutil.ReadAll(resp.Body)\r\n    if err != nil {\r\n        t.Error(err)\r\n    }\r\n    return string(body)\r\n}<\/pre>\n<p>Let\u2019s talk about factories and helpers. Tests are code too; they\u2019re not just scripts that run alongside your code. It helps to treat your tests like real code, and you\u2019ll see this in the standard library tests too.<\/p>\n<p>In this case, I wrote two helpers to make this easier on me. This is my fake app, which is going to run an HTTP test server. I\u2019ll initialize the app with whatever message I passed to the server, and I\u2019ll return an HTTP test version of the server.<\/p>\n<p>The second one I wrote is <strong>get<\/strong>. You give it your testing instance and a server and a path, and it makes a get request to that server and path, checks for error. It reads the body and checks for an error and returns the string version of that body. So this is going to do the whole get for me and send it back for any path on my server.<\/p>\n<pre class=\" brush:php\">func TestHelpedHello(t *testing.T) {\r\n    s := fakeApp(\"hello\")\r\n    defer s.Close()\r\n    if body := get(t, s, \"\/\"); body != \"hello\" {\r\n        t.Error(\"expected\", \"hello\", \"got\", body)\r\n    }\r\n}<\/pre>\n<p>Once I have these two, my test gets a lot easier to read. In this case, my <strong>get<\/strong> is doing some error checks for me. I don\u2019t just have a lot of little helpers that don\u2019t do anything. I\u2019ve made <strong>get<\/strong> do some assertions to make sure that when I got something back from <strong>get<\/strong>, it was going to work.<\/p>\n<h2>Testing Interactions<\/h2>\n<p>So that was all about testing individual components. Let\u2019s walk through an example of testing interactions between components \u2014 that\u2019s usually where all the interesting testing stuff comes from. When you have two big, complicated pieces working together, that\u2019s when everything becomes difficult.<\/p>\n<p>In this case, I\u2019m using a simple example of a train and an engine.<\/p>\n<pre class=\" brush:php\">type Engine struct {\r\n    speed int\r\n}\r\n\r\nfunc NewEngine() *Engine {\r\n    return &amp;Engine{}\r\n}\r\n\r\nfunc (e *Engine) Speed() int {\r\n    return e.speed\r\n}\r\n\r\nfunc (e *Engine) Accel() {\r\n    e.speed += 10\r\n}\r\n\r\nfunc (e *Engine) Decel() {\r\n    e.speed -= 10\r\n}<\/pre>\n<p>The engine is going to store private speed. It\u2019ll have a constructor that\u2019s going to return a pointer to an engine struct; <strong>Accel<\/strong> is going to increment speed by 10; <strong>Decel<\/strong> is going to decrement speed by 10.<\/p>\n<pre class=\" brush:php\">func TestEngine(t *testing.T) {\r\n    e := NewEngine()\r\n    expectSpeed(t, e, 0)\r\n    e.Accel()\r\n    expectSpeed(t, e, 10)\r\n    e.Decel()\r\n    expectSpeed(t, e, 0)\r\n}<\/pre>\n<p>To test the engine, we make a new engine. I expect speed to be 0. I\u2019ll accelerate it, expect my speed to be 10; I\u2019ll decelerate it and expect to be back at 0.<\/p>\n<pre class=\" brush:php\">func expectSpeed(t *testing.T, e *Engine, s int) {\r\n    actual := e.Speed()\r\n    if actual != s {\r\n        t.Fatal(\"expected\", s, \"got\", actual)\r\n    }\r\n}<\/pre>\n<p><strong>expectSpeed<\/strong> will compare the actual to the speed you gave it and give a fatal if the speed was not equal to what was expected. This is another example of having a helper, so you don\u2019t have to repeat these four lines every single time.<\/p>\n<p>Note: As your software gets more complicated, you\u2019re probably going to want some helpers to set things up. But it should also alert you \u2014 if you have a lot of helpers, it means your code is hard to use because it requires a lot of set up. So at that point, it may be time to break things into packages.<\/p>\n<pre class=\" brush:php\">type Train struct {\r\n    engine *Engine\r\n}\r\n\r\nfunc NewTrain() *Train {\r\n    return &amp;Train{\r\n        engine: NewEngine(),\r\n    }\r\n}\r\n\r\nfunc (t *Train) Go() {\r\n    t.engine.Accel()\r\n    t.engine.Accel()\r\n}\r\n\r\nfunc (t *Train) Stop() {\r\n    t.engine.Decel()\r\n    t.engine.Decel()\r\n}\r\n\r\nfunc (t *Train) Speed() int {\r\n    return t.engine.Speed()\r\n}<\/pre>\n<p>Now I\u2019ve got a private engine on the train. My constructor that returns a train is going to call the engine constructor to give us a new engine. <strong>Go<\/strong> just accelerates twice, <strong>Stop<\/strong> is going to decelerate twice, and <strong>Speed<\/strong> will return the speed.<\/p>\n<p>The thing that I really care about is how <strong>Train<\/strong> and <strong>Engine<\/strong> are going to work together and how they\u2019re constructed.<\/p>\n<pre class=\" brush:php\">func expectTrainSpeed(t *testing.T, tr *Train, s int) {\r\n    actual := tr.Speed()\r\n    if actual != s {\r\n        t.Fatal(\"expected\", s, \"got\", actual)\r\n    }\r\n}\r\n\r\nfunc TestTrain(t *testing.T) {\r\n    tr := NewTrain()\r\n    tr.Go()\r\n    expectTrainSpeed(t, tr, 20)\r\n    tr.Stop()\r\n    expectTrainSpeed(t, tr, 0)\r\n}<\/pre>\n<p>The train test is going to be pretty simple \u2014 looks pretty similar to what we had before.<\/p>\n<h3>\u201cIntegration\u201d test<\/h3>\n<p>The train actually has to have a real engine, and it actually does stuff to the engine. That\u2019s the only way our test is going to pass \u2014 they are integrated together. We\u2019re testing acceleration by inspecting speed.<\/p>\n<p>However, we\u2019re not looking at how the train and the engine are interacting with each other. If we really unit tested the train, we\u2019d give it a fake engine that it was going to play around with. We\u2019d tell the train to go, and then we\u2019d see what the train tried to do to the engine. Notice that such a test would only test <strong>Go<\/strong>. It\u2019s not testing <strong>Go<\/strong> and <strong>Stop<\/strong> and <strong>Speed<\/strong> like the integration test was.<\/p>\n<p>Obviously this example is really contrived. If your code\u2019s that simple, there\u2019s no reason to go to those lengths. But what if <strong>Engine<\/strong> was some remote resource that you had to call over a JSON API through your own <strong>Train<\/strong>, and it was hard to set up and requires a bunch of authentication keys and has to be running on a port and all that junk? Then you\u2019d really want to start faking out your engine. After all, we don\u2019t really care about the engine, we just want to make sure the train does the right thing with the engine.<\/p>\n<pre class=\" brush:php\">type Speeder interface {\r\n    Speed() int\r\n}\r\n\r\ntype Engine interface {\r\n    Speeder\r\n    Accel()\r\n    Decel()\r\n}\r\n\r\ntype engine struct {\r\n    speed int\r\n}\r\n\r\nfunc NewEngine() Engine {\r\n    return \u014bine{}\r\n}\r\n\r\nfunc (e *engine) Speed() int {\r\n    return e.speed\r\n}\r\n\r\nfunc (e *engine) Accel() {\r\n    e.speed += 10\r\n}\r\n\r\nfunc (e *engine) Decel() {\r\n    e.speed -= 10\r\n}<\/pre>\n<p>To be able to work with a fake engine, we have to refactor our engine behind an interface. To do that, I tossed in the <strong>Speeder<\/strong> interface. The big change is that instead of being a struct, <strong>Engine<\/strong> is now an interface type. It\u2019s a speeder, and it will provide acceleration and deceleration.<\/p>\n<p>Our actual engine is going to become a private struct engine. People outside of the engine package will not be able to access our engine struct. They\u2019re only going to be able to see the interface. Our constructor is going to make an instance of the private struct engine and then return it as an engine interface. So we\u2019re making an <strong>engine<\/strong> and returning it as an <strong>Engine<\/strong>, and Go is going to cast it over for us. It\u2019ll allow it if our <strong>engine<\/strong> implements the <strong>Engine<\/strong> interface.<\/p>\n<p>To implement that interface, we have to implement <strong>Speed<\/strong>, and we have to implement <strong>Accel<\/strong> and <strong>Decel<\/strong>.<\/p>\n<p>So we never expose any struct attributes in our public interface. We\u2019re pretty safe, and this refactor will be pretty easy. So now we can pass the engine around.<\/p>\n<pre class=\" brush:php\">func expectSpeed(t *testing.T, speeder Speeder, speed int) {\r\n    actual := speeder.Speed()\r\n    if actual != speed {\r\n        t.Fatal(\"expected\", speed, \"got\", actual)\r\n    }\r\n}\r\n\r\nfunc TestEngine(t *testing.T) {\r\n    e := NewEngine()\r\n    expectSpeed(t, e, 0)\r\n    e.Accel()\r\n    expectSpeed(t, e, 10)\r\n    e.Decel()\r\n    expectSpeed(t, e, 0)\r\n}<\/pre>\n<p>Now, we have a totally public-facing interface for <strong>Engine<\/strong>. This test is pretty much the same as when <strong>Engine<\/strong> was a struct. It\u2019s just now with an interface, which means all we can do is access methods on it.<\/p>\n<pre class=\" brush:php\">type FakeEngine struct {\r\n    AccelCalls int\r\n    DecelCalls int\r\n}\r\n\r\nfunc NewFakeEngine() *FakeEngine {\r\n    return &amp;FakeEngine{}\r\n}\r\n\r\nfunc (e *FakeEngine) Accel() {\r\n    e.AccelCalls += 1\r\n}\r\n\r\nfunc (e *FakeEngine) Decel() {\r\n    e.DecelCalls += 1\r\n}\r\n\r\nfunc (e *FakeEngine) Speed() int {\r\n    return 0\r\n}<\/pre>\n<p>Now let\u2019s make a fake engine. We want to implement the engine interface with it. This is pretty much the dumbest fake I could make \u2014 there are way more interesting ways to do these, but the goal here isn\u2019t so much to implement an engine as it is to keep track of what the interactions were like. The real goal here is to test <strong>Train<\/strong>\u2019s behavior and test it without needing a real engine.<\/p>\n<pre class=\" brush:php\">type Train struct {\r\n    engine Engine\r\n}\r\n\r\nfunc NewTrain() *Train {\r\n    return &amp;Train{\r\n        engine: NewEngine(),\r\n    }\r\n}<\/pre>\n<p>We have to do a little refactoring on <strong>Train<\/strong>. The only thing that changes is <strong>Engine<\/strong>. Since it\u2019s an interface, you don\u2019t want to pass pointers to interfaces around. It gets very confusing very fast. So you always just pass the interface around. You won\u2019t actually know if it\u2019s a pointer or not, which is a really fun thing about Go.<\/p>\n<p>So our engine is now just an instance of the <strong>Engine<\/strong> interface. We also call the constructor as we normally would, so no big changes there.<\/p>\n<pre class=\" brush:php\">func trainWithFakeEngine() (*Train, *FakeEngine) {\r\n    t := NewTrain()\r\n    e := NewFakeEngine()\r\n    t.engine = e\r\n    return t, e\r\n}\r\n\r\nfunc TestTrainGo(t *testing.T) {\r\n    tr, e := trainWithFakeEngine()\r\n    tr.Go()\r\n    if e.AccelCalls != 2 {\r\n        t.Error(\"expected\", 2, \"got\", e.AccelCalls)\r\n    }\r\n}<\/pre>\n<p>Notice that my test\u2019s name has changed. It used to be <strong>TestTrain<\/strong>, and now we\u2019re testing <strong>TrainGo<\/strong>. We\u2019re going to call my constructor that gives us a train and a fake engine, we\u2019re going to call <strong>TrainGo<\/strong>, and then we\u2019re expecting that the engine had <strong>Accel<\/strong> called twice. It\u2019s like if you took a train, set it up in a warehouse, plugged something else into the port that controls the engine, and just made sure it said \u201cacceleration\u201d twice. As opposed to, you know, putting an actual train on an actual track and seeing if it runs into anything.<\/p>\n<p>Next, I\u2019m going to do what\u2019s called setter injection. I take the engine, and I inject that dependency into <strong>Train<\/strong>. I can do this because I\u2019m in the same package. Because this test is in the same package along with Train, I can access private methods. I can screw around with objects in ways that our users aren\u2019t allowed to do.<\/p>\n<pre class=\" brush:php\">func trainWithFakeEngine() (*Train, *FakeEngine) {\r\n    t := NewTrain()\r\n    e := NewFakeEngine()\r\n    t.engine = e\r\n    return t, e\r\n}\r\n\r\nfunc TestTrainStop(t *testing.T) {\r\n    tr, e := trainWithFakeEngine()\r\n    tr.Stop()\r\n    if e.DecelCalls != 2 {\r\n        t.Error(\"expected\", 2, \"got\", e.DecelCalls)\r\n    }\r\n}<\/pre>\n<h3>Interface public stuff<\/h3>\n<p>It\u2019s usually a good idea to use an interface for anything you\u2019re going to be exposing publicly. The only time you wouldn\u2019t want to do that is when you have, for example, data objects that are often going to be value objects. Such as anything that represents a request payload. People are just going to interact with its fields, not really call methods on it.<\/p>\n<p>But usually interfaces are the way to go, for a few reasons:<\/p>\n<ul>\n<li>Future flexibility. If you make a really big package based on structs and calling structs and refactoring all that, it is a huge pain to refactor it over to an interface. But if you do an interface from the start, all you have to do is keep track of the methods on that interface. It forces you to keep it clean too.<\/li>\n<li>You have to expose functionality with methods. You can\u2019t let people just access struct fields by making them public. This is due to the uniform access principle, which says that you should work with data the same way no matter how it\u2019s stored or implemented. By forcing yourself to use methods like getters and setters, you don\u2019t have to refactor all the code that uses what you\u2019ve written down the road.<\/li>\n<li>Easy to fake. It\u2019s super easy to swap in a fake, and the library doesn\u2019t have a clue.<\/li>\n<li>A user can write their own versions of something and use your code.<\/li>\n<\/ul>\n<h2>Testing Concurrent Code<\/h2>\n<p>With concurrent tests, we have to first test for coordination. We\u2019re going to have at least two pieces of code \u2014 two Go routines \u2014 moving at the same time, and we need to see how they coordinate with each other.<\/p>\n<pre class=\" brush:php\">type Engine interface {\r\n    Speeder\r\n    Accel()\r\n    Decel()\r\n    Stop()\r\n    Run()\r\n}<\/pre>\n<p>We\u2019re going to add run and stop to our engine. Like turning a key, it\u2019s sort of running off to the side while we\u2019re sending our <strong>Accel<\/strong> and <strong>Decel<\/strong> instructions to it. When we\u2019re done, we\u2019ll stop it, or turn it off.<\/p>\n<pre class=\" brush:php\">type accelCommand struct {\r\n    done chan bool\r\n}\r\n\r\nfunc newAccelCommand() *accelCommand {\r\n    return \u223ecelCommand{done: make(chan bool)}\r\n}\r\n\r\ntype engine struct {\r\n    speed    int\r\n    stop     chan bool\r\n    done     chan bool\r\n    accelcmd chan *accelCommand\r\n}\r\n\r\nfunc newEngine() *engine {\r\n    return \u014bine{\r\n        accelcmd: make(chan *accelCommand),\r\n        stop:     make(chan bool),\r\n        done:     make(chan bool),\r\n    }\r\n}\r\n\r\nfunc NewEngine() Engine {\r\n    return newEngine()\r\n}<\/pre>\n<p>We\u2019re going to create a new version of <strong>Accel<\/strong>, a blocking version. To do that, we\u2019re going to use a channel. My engine will now have a stop channel, a done channel (to say that it has successfully stopped), and an acceleration command channel.<\/p>\n<p>The first thing you\u2019ll do is instantiate an acceleration command. Then you\u2019ll send that command down the acceleration command channel. Then you\u2019ll wait on the command\u2019s done channel.<\/p>\n<pre class=\" brush:php\">func (e *engine) Run() {\r\n    for {\r\n        select {\r\n        case c := &lt;-e.accelcmd:\r\n            e.speed += 10\r\n            time.Sleep(100 * time.Millisecond)\r\n            close(c.done)\r\n        case &lt;-e.stop:\r\n            close(e.done)\r\n            return\r\n        }\r\n    }\r\n}<\/pre>\n<p>To go along with the block <strong>Accel<\/strong>, we have to have an engine runloop. Our engine\u2019s run is going to be selecting in two channels. If we get a stop, we\u2019ll close the done channel and return out of my runloop. If we get an acceleration command, we\u2019re going to increment our speed, and then I\u2019ll close my command\u2019s done channel to say we\u2019ve successfully accelerated, and I\u2019ll go back into my loop.<\/p>\n<p>So if we want to accelerate, we have to have <strong>Run<\/strong> running at the same time. If we try to call <strong>Accel<\/strong>, and we\u2019re not running our engine somewhere, it\u2019s going to deadlock immediately.<\/p>\n<pre class=\" brush:php\">func (e *engine) Stop() {\r\n    e.stop &lt;- true\r\n    &lt;-e.done\r\n}<\/pre>\n<p>All that <strong>stop<\/strong> does is send a <strong>true<\/strong> down the stop channel and waits for <strong>done<\/strong>. It needs to make sure you\u2019re not in the middle of acceleration. If you are, it waits for acceleration to finish, then it needs to go back into the <strong>select<\/strong>, and then it will grab the <strong>stop<\/strong> and receive that. This ensures you don\u2019t get cut off in the middle of something.<\/p>\n<pre class=\" brush:php\">func TestEngineAccel(t *testing.T) {\r\n    e := newEngine()\r\n\r\n    done := make(chan bool)\r\n    go func() {\r\n        e.Accel()\r\n        close(done)\r\n    }()\r\n\r\n    c, ok := &lt;-e.accelcmd\r\n    if c == nil || !ok {\r\n        t.Fatal(\"expected acceleration command\")\r\n    }\r\n\r\n    close(c.done)\r\n    &lt;-done\r\n}<\/pre>\n<p>This is what concurrent tests look like for me. I\u2019ll do my setup \u2014 instantiate my engine. Then I\u2019ll have my own done channel. I\u2019m going to background <strong>Accel<\/strong> but have my foreground code be doing the testing.<\/p>\n<p>When <strong>Accel<\/strong> returns, I\u2019ll close my <strong>done<\/strong>. In this case, I\u2019m unit testing <strong>Accel<\/strong>; I\u2019m not even testing the train\u2019s own acceleration with the train\u2019s own runloop here. I\u2019m just making sure my accelerator sends the right command. Now if this were a more complicated command, like something that\u2019s going off to an API, you\u2019d want a unit test like this to make sure that the message sent by <strong>Accel<\/strong> was appropriate.<\/p>\n<p>We\u2019re unit testing only private implementation here, and that comes with its own tradeoffs. This test will be very brittle, along with the code it\u2019s testing. If you want to change any of the private implementations, you have to change the test to go with it. These tests are useful for development, less useful for regression, and not useful at all for refactoring.<\/p>\n<pre class=\" brush:php\">func TestEngine(t *testing.T) {\r\n    e := NewEngine()\r\n    go e.Run()\r\n    defer e.Stop()\r\n    expectSpeed(t, e, 0)\r\n    e.Accel()\r\n    expectSpeed(t, e, 10)\r\n    e.Decel()\r\n    expectSpeed(t, e, 0)\r\n}<\/pre>\n<p>This is the kind of test that you really want to keep around. It\u2019ll work off a public interface without concerning itself with private implementation. So this is testing concurrent code, but you barely even know it because you\u2019re going to call <strong>Run<\/strong> and <strong>Stop<\/strong>. It\u2019s super easy to run, and it tests a whole bunch of code.<\/p>\n<h2>How to Make a Fake that Can Deal with Concurrency<\/h2>\n<p>So, how do we combine the fake engine idea with the concurrent code idea?<\/p>\n<p>We could mark some timestamps, or to go a little further, we could have log of events that we had. For concurrency tools in Go, we have Go routines, channels, and sync. We could use locks.<\/p>\n<p>For our example, the accelerator could wait on lock, like the <strong>Accel<\/strong> of my fake could wait on a lock. My <strong>doAccel<\/strong> private method could then unlock that lock. That way, my engine could block on <strong>Accel<\/strong> until exactly when my test decided to unlock <strong>Accel<\/strong> and let my code proceed.<\/p>\n<p>The other one was the channel. So, <strong>Accel<\/strong> could wait on some performing acceleration channel, and then my <strong>doAccel<\/strong> could send a message saying to go ahead and perform the acceleration.<\/p>\n<h2>Conclusion<\/h2>\n<p>There really isn\u2019t a trick to any of this. The same code, the same libraries you have with Go are available in tests. Remember that tests are also code. You can use all your tricks, all your design patterns, all of your strategies in your tests the same way you can in your code.<\/p>\n<p>If you want to dig a little further, check out my post <a href=\"http:\/\/blog.codeship.com\/creating-fakes-in-go-with-channels\/\">\u201cCreating Fakes in Go with Channels.\u201d<\/a><\/p>\n<h2>Resources<\/h2>\n<ul>\n<li><a href=\"https:\/\/docs.google.com\/presentation\/d\/1YNdOuNeZbih0oIG-s-tYUxXxel78E5S1QvR-ncrQa0M\/edit#slide=id.p\"><strong>Slides<\/strong><\/a><\/li>\n<li><a href=\"https:\/\/github.com\/ngauthier\/testing-go-presentation\"><strong>Code<\/strong><\/a><\/li>\n<li><strong>Video<\/strong><\/li>\n<\/ul>\n<h2><\/h2>\n<p><iframe title=\"Boston Golang - Testing\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/v_wz6E3uFRg?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/blog.codeship.com\/testing-in-go\/\">Testing in Go<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/wcg\/\">WCG partner<\/a> Florian Motlik at the <a href=\"http:\/\/blog.codeship.com\/\">Codeship Blog<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This post is based on a presentation I gave for the Boston Go group in May. You can watch the video here For me, Go is like coming back to formal programming after the crazy world of Ruby for a little while. It reminds me of C with all the sharp corners sanded off; Go &hellip;<\/p>\n","protected":false},"author":126,"featured_media":927,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[213],"class_list":["post-5882","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-web-development","tag-go"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Testing in Go - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"This post is based on a presentation I gave for the Boston Go group in May. You can watch the video here For me, Go is like coming back to formal\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Testing in Go - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"This post is based on a presentation I gave for the Boston Go group in May. You can watch the video here For me, Go is like coming back to formal\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-07-27T13:15:48+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2015-12-16T09:30:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Nick Gauthier\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@ngauthier\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nick Gauthier\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/\"},\"author\":{\"name\":\"Nick Gauthier\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/ffb33c8e15388f289769fc32359c685b\"},\"headline\":\"Testing in Go\",\"datePublished\":\"2015-07-27T13:15:48+00:00\",\"dateModified\":\"2015-12-16T09:30:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/\"},\"wordCount\":3450,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"keywords\":[\"Go\"],\"articleSection\":[\"Web Dev\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/\",\"name\":\"Testing in Go - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"datePublished\":\"2015-07-27T13:15:48+00:00\",\"dateModified\":\"2015-12-16T09:30:58+00:00\",\"description\":\"This post is based on a presentation I gave for the Boston Go group in May. You can watch the video here For me, Go is like coming back to formal\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Web Dev\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/web-development\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Testing in Go\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/ffb33c8e15388f289769fc32359c685b\",\"name\":\"Nick Gauthier\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f83b49479457522ceeff8fcf2f39ceafc570c5562b5573da9a5a47d177f4f0bf?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f83b49479457522ceeff8fcf2f39ceafc570c5562b5573da9a5a47d177f4f0bf?s=96&d=mm&r=g\",\"caption\":\"Nick Gauthier\"},\"description\":\"Nick likes creating for the web, making things fast, and playing strategy games.\",\"sameAs\":[\"http:\/\/blog.codeship.com\/\",\"https:\/\/x.com\/ngauthier\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/nick-gauthier\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Testing in Go - Web Code Geeks - 2026","description":"This post is based on a presentation I gave for the Boston Go group in May. You can watch the video here For me, Go is like coming back to formal","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/","og_locale":"en_US","og_type":"article","og_title":"Testing in Go - Web Code Geeks - 2026","og_description":"This post is based on a presentation I gave for the Boston Go group in May. You can watch the video here For me, Go is like coming back to formal","og_url":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2015-07-27T13:15:48+00:00","article_modified_time":"2015-12-16T09:30:58+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","type":"image\/jpeg"}],"author":"Nick Gauthier","twitter_card":"summary_large_image","twitter_creator":"@ngauthier","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Nick Gauthier","Est. reading time":"21 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/"},"author":{"name":"Nick Gauthier","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/ffb33c8e15388f289769fc32359c685b"},"headline":"Testing in Go","datePublished":"2015-07-27T13:15:48+00:00","dateModified":"2015-12-16T09:30:58+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/"},"wordCount":3450,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","keywords":["Go"],"articleSection":["Web Dev"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/","url":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/","name":"Testing in Go - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","datePublished":"2015-07-27T13:15:48+00:00","dateModified":"2015-12-16T09:30:58+00:00","description":"This post is based on a presentation I gave for the Boston Go group in May. You can watch the video here For me, Go is like coming back to formal","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/web-dev-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/web-development\/testing-in-go\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Web Dev","item":"https:\/\/www.webcodegeeks.com\/category\/web-development\/"},{"@type":"ListItem","position":3,"name":"Testing in Go"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/ffb33c8e15388f289769fc32359c685b","name":"Nick Gauthier","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/f83b49479457522ceeff8fcf2f39ceafc570c5562b5573da9a5a47d177f4f0bf?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f83b49479457522ceeff8fcf2f39ceafc570c5562b5573da9a5a47d177f4f0bf?s=96&d=mm&r=g","caption":"Nick Gauthier"},"description":"Nick likes creating for the web, making things fast, and playing strategy games.","sameAs":["http:\/\/blog.codeship.com\/","https:\/\/x.com\/ngauthier"],"url":"https:\/\/www.webcodegeeks.com\/author\/nick-gauthier\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/5882","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/126"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=5882"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/5882\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/927"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=5882"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=5882"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=5882"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}