Skip to content

Commit 41b13e6

Browse files
Big refresh (#49)
1 parent 1802090 commit 41b13e6

48 files changed

Lines changed: 1035 additions & 689 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/CI.yml

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ on:
55
push:
66
branches:
77
- main
8-
tags:
9-
- v*
108

119
concurrency:
12-
group: ${{ github.ref }}
10+
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
1311
cancel-in-progress: true
1412

15-
permissions: read-all
13+
permissions: {}
1614

1715
jobs:
1816
test:
1917
name: Test
2018
runs-on: ${{ matrix.os }}
19+
permissions:
20+
contents: read
2121
strategy:
2222
matrix:
2323
os:
@@ -36,10 +36,14 @@ jobs:
3636

3737
- name: Run Tests
3838
run: go test -race ./...
39+
env:
40+
NO_COLOR: true
3941

4042
cov:
4143
name: CodeCov
4244
runs-on: ubuntu-latest
45+
permissions:
46+
contents: read
4347

4448
steps:
4549
- name: Checkout Code
@@ -52,16 +56,19 @@ jobs:
5256

5357
- name: Run Tests
5458
run: go test -race -cover -covermode=atomic -coverprofile=./coverage.out ./...
59+
env:
60+
NO_COLOR: true
5561

5662
- name: Coverage
5763
uses: codecov/codecov-action@v5
5864
with:
5965
files: ./coverage.out
60-
token: ${{ secrets.CODECOV_TOKEN }}
6166

6267
lint:
6368
name: Lint
6469
runs-on: ubuntu-latest
70+
permissions:
71+
contents: read
6572

6673
steps:
6774
- name: Checkout Code
@@ -72,46 +79,41 @@ jobs:
7279
with:
7380
go-version-file: go.mod
7481

75-
- name: Clean Mod Cache # See https://github.com/golangci/golangci-lint-action/issues/135
76-
run: go clean -modcache
77-
7882
- name: Run Linting
7983
uses: golangci/golangci-lint-action@v6
8084
with:
8185
version: latest
8286

83-
release:
84-
name: Release
87+
vulncheck:
88+
name: Vulncheck
8589
runs-on: ubuntu-latest
8690
permissions:
87-
contents: write
88-
89-
needs:
90-
- test
91-
- cov
92-
- lint
93-
94-
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
91+
contents: read
9592

9693
steps:
9794
- name: Checkout Code
9895
uses: actions/checkout@v4
96+
97+
- name: Set up Go
98+
uses: actions/setup-go@v5
9999
with:
100-
fetch-depth: 0
100+
go-version-file: go.mod
101+
102+
- name: Install govulncheck
103+
run: go install golang.org/x/vuln/cmd/govulncheck@latest
101104

102-
- name: Fetch Existing Tags
103-
run: git fetch --force --tags
105+
- name: Run govulncheck
106+
run: govulncheck ./...
104107

105-
- name: Parse Release Version
106-
id: version
107-
run: |
108-
VERSION=${GITHUB_REF#refs/tags/v}
109-
echo "version=$VERSION" >> $GITHUB_OUTPUT
108+
typos:
109+
name: Typos
110+
runs-on: ubuntu-latest
111+
permissions:
112+
contents: read
110113

111-
- name: Publish Draft Release
112-
uses: release-drafter/release-drafter@v6
113-
with:
114-
version: ${{ steps.version.outputs.version }}
115-
publish: true
116-
env:
117-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
114+
steps:
115+
- name: Checkout Code
116+
uses: actions/checkout@v4
117+
118+
- name: Check for Typos
119+
uses: crate-ci/typos@v1.29.1

.github/workflows/release.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v[0-9]+.[0-9]+.[0-9]+'
7+
8+
permissions: {}
9+
10+
jobs:
11+
release:
12+
name: Release
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: write
16+
pull-requests: read
17+
18+
steps:
19+
- name: Checkout Code
20+
uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
24+
- name: Fetch Existing Tags
25+
run: git fetch --force --tags
26+
27+
- name: Parse Release Version
28+
id: version
29+
run: |
30+
VERSION=${GITHUB_REF#refs/tags/v}
31+
echo "version=$VERSION" >> $GITHUB_OUTPUT
32+
33+
- name: Publish Draft Release
34+
uses: release-drafter/release-drafter@v6
35+
with:
36+
version: ${{ steps.version.outputs.version }}
37+
publish: true
38+
env:
39+
GITHUB_TOKEN: ${{ github.token }}

.golangci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ linters:
3636
- unused
3737
- whitespace
3838

39+
issues:
40+
exclude-rules:
41+
- path: test_test.go
42+
linters:
43+
- thelper # The entire package is effectively a t.Helper
44+
- goconst # Lots of repetition in here
45+
3946
linters-settings:
4047
errcheck:
4148
check-type-assertions: true

README.md

Lines changed: 19 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -42,46 +42,38 @@ func TestSomething(t *testing.T) {
4242

4343
test.True(t, true) // Passes
4444
test.False(t, true) // Fails
45-
46-
// Get $CWD/testdata easily
47-
test.Data(t) // /Users/you/project/package/testdata
48-
49-
// Check against contents of a file including line ending normalisation
50-
file := filepath.Join(test.Data(t), "expected.txt")
51-
test.File(t, "hello\n", file)
52-
53-
// Just like the good old reflect.DeepEqual, but with a nicer format
54-
test.DeepEqual(t, []string{"hello"}, []string{"world"}) // Fails
5545
}
5646
```
5747

58-
### Self Documenting Tests
59-
60-
> [!TIP]
61-
> Line comments on the line you call most `test` functions on will be shown in failure messages as additional context
48+
### Add Additional Context
6249

63-
That means you can have additional context in the failure message, as well as helpful comments explaining the assertion to readers of your code
50+
`test` provides a number of options to decorate your test log with useful context:
6451

6552
```go
66-
func TestSomething(t *testing.T) {
67-
test.Equal(t, "apples", "oranges") // Fruits are not equal
53+
func TestDetail(t *testing.T) {
54+
test.Equal(t, "apples", "oranges", test.Title("Fruit scramble!"), test.Context("Apples are not oranges!"))
6855
}
6956
```
7057

71-
Will get you a failure message like:
58+
Will get you an error log in the test that looks like this...
7259

73-
```shell
74-
--- FAIL: TestSomething (0.00s)
75-
something_test.go:1:
76-
Not Equal // Fruits are not equal
77-
---------
60+
```plaintext
61+
--- FAIL: TestDemo (0.00s)
62+
test_test.go:501:
63+
Fruit scramble!
64+
---------------
65+
7866
Got: apples
7967
Wanted: oranges
68+
69+
(Apples are not oranges!)
70+
71+
FAIL
8072
```
8173

8274
### Non Comparable Types
8375

84-
`test` uses Go 1.18+ generics under the hood for most of the comparison, which is great, but what if your types don't satisfy `comparable`. We also provide
76+
`test` uses generics under the hood for most of the comparison, which is great, but what if your types don't satisfy `comparable`. We also provide
8577
`test.EqualFunc` and `test.NotEqualFunc` for those exact situations!
8678

8779
These allow you to pass in a custom comparator function for your type, if your comparator function returns true, the types are considered equal.
@@ -98,42 +90,15 @@ func TestNonComparableTypes(t *testing.T) {
9890

9991
test.EqualFunc(t, a, b, sliceEqual) // Passes
10092

101-
// Can also use e.g. the new slices package
102-
test.EqualFunc(t, a, b, slices.Equal[string]) // Also passes :)
93+
// Can also use any function here
94+
test.EqualFunc(t, a, b, slices.Equal) // Also passes :)
10395

104-
test.EqualFunc(t, a, c, slices.Equal[string]) // Fails
96+
test.EqualFunc(t, a, c, slices.Equal) // Fails
10597
}
10698
```
10799

108100
You can also use this same pattern for custom user defined types, structs etc.
109101

110-
### Rich Comparison
111-
112-
Large structs or long slices can often be difficult to compare using `reflect.DeepEqual`, you have to scan for the difference yourself. `test` provides a
113-
`test.Diff` function that produces a rich text diff for you on failure:
114-
115-
```go
116-
func TestDiff(t *testing.T) {
117-
// Pretend these are very long, or are large structs
118-
a := []string{"hello", "world"}
119-
b := []string{"hello", "there"}
120-
121-
test.Diff(t, a, b)
122-
}
123-
```
124-
125-
Will give you:
126-
127-
```plain
128-
--- FAIL: TestDiff (0.00s)
129-
main_test.go:14: Mismatch (-want, +got):
130-
[]string{
131-
"hello",
132-
- "there",
133-
+ "world",
134-
}
135-
```
136-
137102
### Table Driven Tests
138103

139104
Table driven tests are great! But when you test errors too it can get a bit awkward, you have to do the `if (err != nil) != tt.wantErr` thing and I personally
@@ -232,29 +197,6 @@ func TestOutput(t *testing.T) {
232197

233198
Under the hood `CaptureOutput` temporarily captures both streams, copies the data to a buffer and returns the output back to you, before cleaning everything back up again.
234199

235-
### Golden Files
236-
237-
`test` has great support for golden files:
238-
239-
```go
240-
func TestFile(t *testing.T) {
241-
got := "some contents\n"
242-
want := filepath.Join(test.Data(t), "golden.txt")
243-
244-
test.File(t, got, want)
245-
}
246-
```
247-
248-
This will read the file, normalise line endings and then generate an output almost like a git diff:
249-
250-
```patch
251-
--- want
252-
+++ got
253-
@@ -1 +1 @@
254-
-some file contents
255-
+some contents
256-
```
257-
258200
### Credits
259201

260202
This package was created with [copier] and the [FollowTheProcess/go_copier] project template.

0 commit comments

Comments
 (0)