Ruth wins
. The intention is to eventually be a tool for helping users play poker.main.go
file that launches an HTTP server. The HTTP server won't be interesting to us for this exercise but the abstraction it uses will. It depends on a PlayerStore
.FileSystemPlayerStore
which implements that interface. We should be able to re-use some of this for our new application.$GOPATH/src/github.com/your-name/my-app
main
function inside a package main
. So far all of our "domain" code has lived inside package main
and our func main
can reference everything.cmd
directory with a webserver
directory inside that (e.g mkdir -p cmd/webserver
).main.go
inside there.tree
installed you should run it and your structure should look like thismain
.poker
.main.go
so we can use it to create our web server. Then we can use our library code by using poker.FunctionName
.go get
.go test
and check they're still passingcmd/webserver
and do go run main.go
http://localhost:5000/league
and you should see it's still workingcmd
called cli
(command line interface) and add a main.go
with the following{PlayerName} wins
.CLI
which will allow us to Play
poker. It'll need to read user input and then record wins to a PlayerStore
.PlayerStore
how we'd like.CLI_test.go
(in the root of the project, not inside cmd
)StubPlayerStore
from other testsCLI
typePlayPoker
methodCLI
struct with the respective field for our dependency and add a method.Stdin
(the input from the user) so that we can record wins for specific players.os.Stdin
is what we'll use in main
to capture the user's input. It is a *File
under the hood which means it implements io.Reader
which as we know by now is a handy way of capturing text.io.Reader
in our test using the handy strings.NewReader
, filling it with what we expect the user to type../CLI_test.go:12:32: too many values in struct initializer
CLI
.server_test
we earlier did checks to see if wins are recorded as we have here. Let's DRY that assertion up into a helperserver_test.go
and CLI_test.go
.Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer) that also implements the interface but provides buffering and some help for textual I/O.
Scanner.Scan()
will read up to a newline.Scanner.Text()
to return the string
the scanner read to.main
. Remember we should always strive to have fully-integrated working software as quickly as we can.main.go
add the following and run it. (you may have to adjust the path of the second dependency to match what's on your computer)playerStore
and in
in CLI
. These are unexported (private) fields. We could do this in our test code because our test is in the same package as CLI
(poker
). But our main
is in package main
so it does not have access.CLI
private (because we don't want them exposed to users of CLI
s) but haven't made a way for users to construct it.package mypackage_test
main
does)?_test
at the end. When you do this you will only be able to have access to the public types in your package. This would help with this specific case but also helps enforce the discipline of only testing public APIs. If you still wish to test internals you can make a separate test with the package you want to test.package foo_test
will help with this by forcing you to test your code as if you are importing it like users of your package will.main
let's change the package of our test inside CLI_test.go
to poker_test
.CLI_test
because the helpers are defined in the _test.go
files in the poker
package.poker
package won't have to create their own stub PlayerStore
if they wish to work with our code.testing.go
and add our stub and our helpers.CLI
test you'll need to call the code as if you were using it within a different package.main
CLI
so it stores a bufio.Scanner
instead of the reader as it's now automatically wrapped at construction time.main.go
and use the constructor we just madefile_system_store
from its contents. This feels like a slight weakness in our package's design so we should make a function in it to encapsulate opening a file from a path and returning you the PlayerStore
.FileSystemPlayerStoreFromFile
returns a closing function, so we can close the underlying file once we are done using the Store.main
s.mypackage_test
helps us create a testing environment which is the same experience for other packages integrating with your code, to help you catch integration problems and see how easy (or not!) your code is to work with.os.Stdin
is very easy for us to work with as it implements io.Reader
. We used bufio.Scanner
to easily read line by line user input.PlayerStore
into our new application (once we had made the package adjustments) and subsequently testing was very easy too because we decided to expose our stub version too.