Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big refresh #49

Merged
merged 1 commit into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 35 additions & 33 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ on:
push:
branches:
- main
tags:
- v*

concurrency:
group: ${{ github.ref }}
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true

permissions: read-all
permissions: {}

jobs:
test:
name: Test
runs-on: ${{ matrix.os }}
permissions:
contents: read
strategy:
matrix:
os:
Expand All @@ -36,10 +36,14 @@ jobs:

- name: Run Tests
run: go test -race ./...
env:
NO_COLOR: true

cov:
name: CodeCov
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout Code
Expand All @@ -52,16 +56,19 @@ jobs:

- name: Run Tests
run: go test -race -cover -covermode=atomic -coverprofile=./coverage.out ./...
env:
NO_COLOR: true

- name: Coverage
uses: codecov/codecov-action@v5
with:
files: ./coverage.out
token: ${{ secrets.CODECOV_TOKEN }}

lint:
name: Lint
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout Code
Expand All @@ -72,46 +79,41 @@ jobs:
with:
go-version-file: go.mod

- name: Clean Mod Cache # See https://github.com/golangci/golangci-lint-action/issues/135
run: go clean -modcache

- name: Run Linting
uses: golangci/golangci-lint-action@v6
with:
version: latest

release:
name: Release
vulncheck:
name: Vulncheck
runs-on: ubuntu-latest
permissions:
contents: write

needs:
- test
- cov
- lint

if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
contents: read

steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
fetch-depth: 0
go-version-file: go.mod

- name: Install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@latest

- name: Fetch Existing Tags
run: git fetch --force --tags
- name: Run govulncheck
run: govulncheck ./...

- name: Parse Release Version
id: version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
typos:
name: Typos
runs-on: ubuntu-latest
permissions:
contents: read

- name: Publish Draft Release
uses: release-drafter/release-drafter@v6
with:
version: ${{ steps.version.outputs.version }}
publish: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Check for Typos
uses: crate-ci/typos@v1.29.1
39 changes: 39 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Release

on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'

permissions: {}

jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read

steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Fetch Existing Tags
run: git fetch --force --tags

- name: Parse Release Version
id: version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Publish Draft Release
uses: release-drafter/release-drafter@v6
with:
version: ${{ steps.version.outputs.version }}
publish: true
env:
GITHUB_TOKEN: ${{ github.token }}
7 changes: 7 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ linters:
- unused
- whitespace

issues:
exclude-rules:
- path: test_test.go
linters:
- thelper # The entire package is effectively a t.Helper
- goconst # Lots of repetition in here

linters-settings:
errcheck:
check-type-assertions: true
Expand Down
96 changes: 19 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,46 +42,38 @@ func TestSomething(t *testing.T) {

test.True(t, true) // Passes
test.False(t, true) // Fails

// Get $CWD/testdata easily
test.Data(t) // /Users/you/project/package/testdata

// Check against contents of a file including line ending normalisation
file := filepath.Join(test.Data(t), "expected.txt")
test.File(t, "hello\n", file)

// Just like the good old reflect.DeepEqual, but with a nicer format
test.DeepEqual(t, []string{"hello"}, []string{"world"}) // Fails
}
```

### Self Documenting Tests

> [!TIP]
> Line comments on the line you call most `test` functions on will be shown in failure messages as additional context
### Add Additional Context

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

```go
func TestSomething(t *testing.T) {
test.Equal(t, "apples", "oranges") // Fruits are not equal
func TestDetail(t *testing.T) {
test.Equal(t, "apples", "oranges", test.Title("Fruit scramble!"), test.Context("Apples are not oranges!"))
}
```

Will get you a failure message like:
Will get you an error log in the test that looks like this...

```shell
--- FAIL: TestSomething (0.00s)
something_test.go:1:
Not Equal // Fruits are not equal
---------
```plaintext
--- FAIL: TestDemo (0.00s)
test_test.go:501:
Fruit scramble!
---------------

Got: apples
Wanted: oranges

(Apples are not oranges!)

FAIL
```

### Non Comparable Types

`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
`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
`test.EqualFunc` and `test.NotEqualFunc` for those exact situations!

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

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

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

test.EqualFunc(t, a, c, slices.Equal[string]) // Fails
test.EqualFunc(t, a, c, slices.Equal) // Fails
}
```

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

### Rich Comparison

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
`test.Diff` function that produces a rich text diff for you on failure:

```go
func TestDiff(t *testing.T) {
// Pretend these are very long, or are large structs
a := []string{"hello", "world"}
b := []string{"hello", "there"}

test.Diff(t, a, b)
}
```

Will give you:

```plain
--- FAIL: TestDiff (0.00s)
main_test.go:14: Mismatch (-want, +got):
[]string{
"hello",
- "there",
+ "world",
}
```

### Table Driven Tests

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
Expand Down Expand Up @@ -232,29 +197,6 @@ func TestOutput(t *testing.T) {

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.

### Golden Files

`test` has great support for golden files:

```go
func TestFile(t *testing.T) {
got := "some contents\n"
want := filepath.Join(test.Data(t), "golden.txt")

test.File(t, got, want)
}
```

This will read the file, normalise line endings and then generate an output almost like a git diff:

```patch
--- want
+++ got
@@ -1 +1 @@
-some file contents
+some contents
```

### Credits

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