Hello world!
Procrastination is real and I've been putting off starting a "blog" for far too long. Why not use this opportunity and go over the fairly new codingchallenges.fyi.
In this series, I will be using Go and Test-Driven-Development while walking through the challenges and explaining my thoughts process. So without further ado, let's get going.
1. Tools
- go - I will be coding in golang, so https://go.dev/doc/install is essential.
- cobra-cli I will also be using cobra go package as most of the challenges are cli oriented. Cobra provides a CLI tool that can help you produce boilerplate code to save you some time.
- [OPTIONAL] gotestsum - this is an excellent go testing tool that has many features over the standard
go test
command. I hihgly recommend! - [OPTIONAL] Unix environment - this is not a requirement, but a nice to have. Most of the tools we will be creating are only available in unix, so having a system that runs unix or WSL for windows will be handy when you need to do a parity check.
2. Repository Setup
To get started, I have created an empty git repository on github and cloned it to my computer.
Now we need to initialize our go module, I will cd
into the newly cloned directory and run the following command:
go mod init github.com/berkeli/coding-challenges
I have given my module the path to my git repository, as that makes it easy to import & reference things.
3. Creating hello world
Now we will initialize our CLI application and write simple Hello World!
to the terminal.
I will run cobra-cli init .
which creates the basic boilerplate for our application. Once done, you should be able to run the application and it will display the description for our root
command
go run .
A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.
Let's update the handler function for the rootCmd
(located in cmd/root.go
) so we have our hello world:
from:
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
to:
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("hello world!")
},
and voila! we have our hello world:
go run .
hello world!
But we won't be attaching a handler to the rootCmd
, so we can undo our change and the cleanup comments and descriptions so it matches what we are trying to do.
A few notes on project structure
For this project I will be following the follwowing structure
├── cmd <-- most of our work will live here
│ ├── go-wc <-- subdirectory for each command/challenge, e.g. wc command
│ │ ├── main.go <-- logic for wc command
│ │ ├── main_test.go <-- tests for wc command
│ │ └── test.txt <-- any additional fixtures needed for testing
│ └── root.go <-- our root command, this will only register child commands
├── go.mod
├── go.sum
└── main.go
cobra-cli
has a useful command for adding new commands cobra-cli add <new-command>
, but I won't be using that much as it won't be following the folder structure I've chosen. It creates files directly in cmd
folder without subdirectories which could get very busy in this series.
Tests & CI
Of course, you can't have TDD without proper CI (continuous integration) setup. So let's get that out of the way and introduce a github action that will test our code.
We can create a YAML file in .github/workflows/
directory, I named mine go-test.yaml
and place the following inside of it:
name: Go Test
on: [push]
jobs:
example:
name: run tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: ./go.mod
id: go
- name: Run Go tests
run: go run gotest.tools/gotestsum@latest --junitfile unit-tests.xml
- name: Test Summary
uses: test-summary/action@v2
with:
paths: "unit-tests.xml"
if: always()
The action about has 3 steps:
- Checkout the repository (get the latest commit)
- Install gotestsum
- Run go tests with gotestsum
- Create a summary from the output of gotestsum
That's it for the setup, let's go implement wc
command next!
The code for this series is available at https://github.com/berkeli/coding-challenges
The code for this post is on this Pull Request
UPDATE [18/02/24] - I realized that this series will contain other types of applications that CLI, so I have made a small re-org of the repo to make it a GO monorepo.
The new structure is as follows:
.
├── cmd
│ └── cli <-- these will be individual applications
│ └── main.go
├── go.mod
├── go.sum
└── pkg <-- this will contain individual challenges as importable packages
└── wc <-- wc package, which is the next challenge
├── main.go
├── main_test.go
└── test.txt
So from the example above, we will have a cli package which is our gocc
(go coding challenges) app that will register subcommands like wc, ls, etc.
These changes are recording in 2nd Pull request
To run our cli tool, we will now be running go run ./cmd/cli
Top comments (0)