How exercises work here
You've passed a few exercises already, so you know the drill: write some Go, click Submit, get ticks or crosses. This last Orientation stop opens the hood. What happens to your code, what the tests look like, and how to read a failure quickly, because from Unit 1 onwards the tests get pickier.
What happens when you click Submit
Your code isn't run in your browser, and it isn't faked. It goes to a sandbox that runs the real Go toolchain:
flowchart TB
accTitle: What happens when you click Submit
accDescr: The editor sends only your files to the web app, which forwards them to the runner. The runner adds the hidden test files, starts a brand-new container with no network access, and runs go test. Results for each test come back to the page.
you([Your code in the editor]) --> app[gobyphp web app]
app --> runner[Runner service]
runner --> add[Adds the hidden _test.go files]
add --> box[Brand-new container: no network, time and memory limits]
box --> test{{go test}}
test --> results([Ticks and crosses, per test])
A few things follow from that:
- Run does
go run .and shows what your program prints. Submit doesgo testagainst the hidden tests. Neither touches your machine. - Each run gets a fresh container, so nothing carries over between submissions. No network means
http.Getto the outside world will fail, by design. - Your code autosaves in your browser, so a refresh won't lose it.
- Hints unlock one at a time. After three failed submits you can reveal the solution: the exercise still counts, but your certificate will say how many you peeked at. No judgement. Everyone peeks.
| You, 23:47 | "It works on my machine." |
|---|---|
| The runner, 23:47 | Fresh container. No network. No leftovers from last time. |
| You, 23:48 | "Ah. It works on a machine." |
Go tests, for PHPUnit people
The exercise below shows you its tests (most don't). Here's what you'll see:
- Tests live next to the code, in files ending in
_test.go. There's notests/directory and nophpunit.xml. - A test is any function named
TestSomething(t *testing.T). No classes, noextends TestCase. - There's no assertion library. No
assertSame, noassertCount. A test is an ordinaryifthat callst.Errorfwhen something's wrong. (t.Fatalfdoes the same but stops the test right there.) - Table-driven tests are Go's data providers: a slice of cases, looped over, each run as a named subtest with
t.Run. That's why the results show names likeTestMinutes/partial_minutes_round_up.
Reading a failure
Every failure follows the same shape:
// --- FAIL: TestMinutes/partial_minutes_round_up // main_test.go:22: Minutes(90) = 1, want 2
From left to right: which test and case failed, the file and line in the test where it was spotted, what was called, what you returned, and what was wanted. The subtest name usually tells you the rule you broke. Here, part-minutes should round up.
Mind the gap
Go's convention is got, then want: Minutes(90) = 1, want 2 means your code returned 1. PHPUnit puts things the other way round, assertSame($expected, $actual), and its output says "Failed asserting that 1 is identical to 2". After years of PHPUnit, it's easy to read Go's message backwards. The value next to the function call is yours.
Recap
- Submit runs
go testwith hidden tests in a fresh, network-less container. Run runsgo run .. - Go tests are plain functions in
_test.gofiles: anif, thent.Errorf("got …, want …"). Table-driven subtests replace data providers. - Read failures as test/case → file:line → call = got, want …. The subtest name tells you the rule.