Skip to content
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
16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
- [Screenshots](#screenshots)
- [Examples](#examples)
- [Basic](#basic)
- [Using existing test file](#using-existing-test-file)
- [Using existing test files](#using-existing-test-files)
- [Omitting elements](#omitting-elements)

GitHub Action for running `go test ./...` and getting rich summary and annotations as output.
Expand All @@ -33,13 +33,9 @@ Powered by [Job Summaries](https://github.blog/2022-05-09-supercharging-github-a
# Optional. Default is './...'
testArguments:

# Parse an exisiting [test2json](https://pkg.go.dev/cmd/test2json) file, instead of executing go test.
# Will always exit(0) on successful test file parse.
# Optional. No default
fromJSONFile:

# Parse multiple [test2json](https://pkg.go.dev/cmd/test2json) files (newline-separated) and generate a combined summary.
# Parse one or more [test2json](https://pkg.go.dev/cmd/test2json) files (newline-separated) and generate a combined summary.
# Will always exit(0) on successful test file parse.
# fromJSONFile is accepted as an alias for a single file.
# Optional. No default
fromJSONFiles:

Expand Down Expand Up @@ -93,13 +89,15 @@ jobs:
uses: robherley/go-test-action@v0
```

### Using existing test file
### Using existing test files

```yaml
- name: Test
uses: robherley/go-test-action@v0
with:
fromJSONFile: /path/to/test2json.json
fromJSONFiles: |
/path/to/pkg1-test2json.json
/path/to/pkg2-test2json.json
```

### Omitting elements
Expand Down
24 changes: 24 additions & 0 deletions __tests__/fixtures/gotestoutput-part1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{"Time":"2022-07-10T22:42:11.92576-04:00","Action":"output","Package":"github.com/robherley/go-test-example","Output":"? \tgithub.com/robherley/go-test-example\t[no test files]\n"}
{"Time":"2022-07-10T22:42:11.926603-04:00","Action":"skip","Package":"github.com/robherley/go-test-example","Elapsed":0.001}
{"Time":"2022-07-10T22:42:11.931066-04:00","Action":"run","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess"}
{"Time":"2022-07-10T22:42:11.931141-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess","Output":"=== RUN TestSuccess\n"}
{"Time":"2022-07-10T22:42:11.931166-04:00","Action":"run","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(1)"}
{"Time":"2022-07-10T22:42:11.931185-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(1)","Output":"=== RUN TestSuccess/Subtest(1)\n"}
{"Time":"2022-07-10T22:42:11.931204-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(1)","Output":" success_test.go:19: hello from subtest #1\n"}
{"Time":"2022-07-10T22:42:11.931239-04:00","Action":"run","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(2)"}
{"Time":"2022-07-10T22:42:11.931284-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(2)","Output":"=== RUN TestSuccess/Subtest(2)\n"}
{"Time":"2022-07-10T22:42:11.9313-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(2)","Output":" success_test.go:19: hello from subtest #2\n"}
{"Time":"2022-07-10T22:42:11.931315-04:00","Action":"run","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(3)"}
{"Time":"2022-07-10T22:42:11.931332-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(3)","Output":"=== RUN TestSuccess/Subtest(3)\n"}
{"Time":"2022-07-10T22:42:11.931347-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(3)","Output":" success_test.go:19: hello from subtest #3\n"}
{"Time":"2022-07-10T22:42:11.931366-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess","Output":"--- PASS: TestSuccess (0.00s)\n"}
{"Time":"2022-07-10T22:42:11.931383-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(1)","Output":" --- PASS: TestSuccess/Subtest(1) (0.00s)\n"}
{"Time":"2022-07-10T22:42:11.93144-04:00","Action":"pass","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(1)","Elapsed":0}
{"Time":"2022-07-10T22:42:11.931461-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(2)","Output":" --- PASS: TestSuccess/Subtest(2) (0.00s)\n"}
{"Time":"2022-07-10T22:42:11.931477-04:00","Action":"pass","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(2)","Elapsed":0}
{"Time":"2022-07-10T22:42:11.931492-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(3)","Output":" --- PASS: TestSuccess/Subtest(3) (0.00s)\n"}
{"Time":"2022-07-10T22:42:11.931506-04:00","Action":"pass","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess/Subtest(3)","Elapsed":0}
{"Time":"2022-07-10T22:42:11.931521-04:00","Action":"pass","Package":"github.com/robherley/go-test-example/success","Test":"TestSuccess","Elapsed":0}
{"Time":"2022-07-10T22:42:11.931536-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Output":"PASS\n"}
{"Time":"2022-07-10T22:42:11.931552-04:00","Action":"output","Package":"github.com/robherley/go-test-example/success","Output":"ok \tgithub.com/robherley/go-test-example/success\t(cached)\n"}
{"Time":"2022-07-10T22:42:11.931572-04:00","Action":"pass","Package":"github.com/robherley/go-test-example/success","Elapsed":0.001}
8 changes: 8 additions & 0 deletions __tests__/fixtures/gotestoutput-part2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{"Time":"2022-07-10T22:42:11.933412-04:00","Action":"run","Package":"github.com/robherley/go-test-example/skipme","Test":"TestSkip"}
{"Time":"2022-07-10T22:42:11.933502-04:00","Action":"output","Package":"github.com/robherley/go-test-example/skipme","Test":"TestSkip","Output":"=== RUN TestSkip\n"}
{"Time":"2022-07-10T22:42:11.933535-04:00","Action":"output","Package":"github.com/robherley/go-test-example/skipme","Test":"TestSkip","Output":" skipme_test.go:6: skip me\n"}
{"Time":"2022-07-10T22:42:11.933551-04:00","Action":"output","Package":"github.com/robherley/go-test-example/skipme","Test":"TestSkip","Output":"--- SKIP: TestSkip (0.00s)\n"}
{"Time":"2022-07-10T22:42:11.933563-04:00","Action":"skip","Package":"github.com/robherley/go-test-example/skipme","Test":"TestSkip","Elapsed":0}
{"Time":"2022-07-10T22:42:11.933575-04:00","Action":"output","Package":"github.com/robherley/go-test-example/skipme","Output":"PASS\n"}
{"Time":"2022-07-10T22:42:11.933587-04:00","Action":"output","Package":"github.com/robherley/go-test-example/skipme","Output":"ok \tgithub.com/robherley/go-test-example/skipme\t(cached)\n"}
{"Time":"2022-07-10T22:42:11.9336-04:00","Action":"pass","Package":"github.com/robherley/go-test-example/skipme","Elapsed":0}
20 changes: 17 additions & 3 deletions __tests__/inputs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const mockInput = (name: string, value: string) => {
mockGetInput.mockImplementation((n: string) => (n === name ? value : ''))
}

const mockInputs = (inputs: Record<string, string>) => {
mockGetInput.mockImplementation((n: string) => inputs[n] ?? '')
}

describe('renderer', () => {
beforeEach(() => {
jest.resetAllMocks()
Expand All @@ -24,7 +28,6 @@ describe('renderer', () => {
expect(inputs).toEqual({
moduleDirectory: '.',
testArguments: ['./...'],
fromJSONFile: null,
fromJSONFiles: null,
omit: new Set(),
})
Expand All @@ -44,11 +47,11 @@ describe('renderer', () => {
expect(inputs.testArguments).toEqual(['foo', 'bar'])
})

it('parses fromJSONFile', () => {
it('parses fromJSONFile as alias for fromJSONFiles', () => {
mockInput('fromJSONFile', 'foo.json')
const inputs = getInputs()

expect(inputs.fromJSONFile).toEqual('foo.json')
expect(inputs.fromJSONFiles).toEqual(['foo.json'])
})

it('parses fromJSONFiles', () => {
Expand All @@ -65,6 +68,17 @@ describe('renderer', () => {
expect(inputs.fromJSONFiles).toEqual(['foo.json', 'bar.json'])
})

it('throws when both fromJSONFile and fromJSONFiles are set', () => {
mockInputs({
fromJSONFile: 'foo.json',
fromJSONFiles: 'bar.json\nbaz.json',
})

expect(() => getInputs()).toThrow(
'Cannot specify both fromJSONFile and fromJSONFiles'
)
})

it('parses omit', () => {
mockInput(
'omit',
Expand Down
48 changes: 48 additions & 0 deletions __tests__/runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
setupActionsInputs,
testOutputDirectory,
testModuleDirectory,
testFixturesDirectory,
mockProcessExit,
createFakeGoModule,
mockActionsCoreLogging,
Expand All @@ -21,6 +22,8 @@ describe('runner', () => {
beforeEach(() => {
mockActionsCoreLogging()
setupActionsInputs()
delete process.env['INPUT_FROMJSONFILE']
delete process.env['INPUT_FROMJSONFILES']
})

it('resolves module name from go.mod', async () => {
Expand Down Expand Up @@ -82,4 +85,49 @@ describe('runner', () => {

expect(spyExit).toHaveBeenCalledWith(2)
})

it('reads from a single JSON file via fromJSONFile', async () => {
const spyExit = mockProcessExit()
const spyWrite = jest
.spyOn(Renderer.prototype, 'writeSummary')
.mockImplementationOnce(async () => {})

process.env['INPUT_FROMJSONFILE'] = path.join(
testFixturesDirectory,
'gotestoutput-part1.txt'
)

const runner = new Runner()
await runner.run()

expect(spyWrite).toHaveBeenCalled()
expect(spyExit).toHaveBeenCalledWith(0)
})

it('reads and combines multiple JSON files via fromJSONFiles', async () => {
const spyExit = mockProcessExit()
const spyWrite = jest
.spyOn(Renderer.prototype, 'writeSummary')
.mockImplementationOnce(async () => {})

const part1 = path.join(testFixturesDirectory, 'gotestoutput-part1.txt')
const part2 = path.join(testFixturesDirectory, 'gotestoutput-part2.txt')
process.env['INPUT_FROMJSONFILES'] = `${part1}\n${part2}`

const runner = new Runner()
await runner.run()

expect(spyWrite).toHaveBeenCalled()
expect(spyExit).toHaveBeenCalledWith(0)
})

it('throws when a file in fromJSONFiles does not exist', async () => {
process.env['INPUT_FROMJSONFILES'] = `${path.join(
testFixturesDirectory,
'gotestoutput-part1.txt'
)}\n/nonexistent/file.json`

const runner = new Runner()
await expect(runner.run()).rejects.toThrow()
})
})
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ inputs:
required: false
default: './...'
fromJSONFile:
description: 'Parse the specified JSON file, instead of executing go test'
description: 'Alias for fromJSONFiles with a single file'
required: false
fromJSONFiles:
description: 'Parse multiple JSON files (newline-separated) and generate a combined summary'
description: 'Parse one or more JSON files (newline-separated) and generate a combined summary'
required: false
omit:
description: 'Whitespace separated list of renderable items to omit. See README.md for details.'
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "go-test-action",
"version": "0.5.1",
"version": "0.5.0",
"description": "GitHub Action to run go tests with rich summary output and annotations.",
"main": "dist/index.js",
"scripts": {
"local": ". script/localenv && ts-node src/index.ts",
"build": "ncc build -m -o dist src/index.ts",
"test": "jest"
},
"author": "Rob Herley <robherley13@gmail.com> (https://reb.gg)",
"author": "Rob Herley <me@reb.gg> (https://reb.gg)",
"license": "MIT",
"dependencies": {
"@actions/core": "^2.0.0",
Expand Down
13 changes: 9 additions & 4 deletions src/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import * as core from '@actions/core'
export interface Inputs {
moduleDirectory: string
testArguments: string[]
fromJSONFile: string | null
fromJSONFiles: string[] | null
omit: Set<OmitOption>
}
Expand All @@ -26,7 +25,6 @@ export enum OmitOption {
export const defaultInputs = (): Inputs => ({
moduleDirectory: '.',
testArguments: ['./...'],
fromJSONFile: null,
fromJSONFiles: null,
omit: new Set(),
})
Expand All @@ -53,11 +51,18 @@ export function getInputs(): Inputs {
}

const fromJSONFile = core.getInput('fromJSONFile')
const fromJSONFiles = core.getInput('fromJSONFiles')

if (fromJSONFile && fromJSONFiles) {
throw new Error(
'Cannot specify both fromJSONFile and fromJSONFiles. Use fromJSONFiles for multiple files.'
)
}

if (fromJSONFile) {
inputs.fromJSONFile = fromJSONFile
inputs.fromJSONFiles = [fromJSONFile]
}

const fromJSONFiles = core.getInput('fromJSONFiles')
if (fromJSONFiles) {
inputs.fromJSONFiles = fromJSONFiles
.split('\n')
Expand Down
13 changes: 0 additions & 13 deletions src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,6 @@ class Runner {
this.inputs.omit
)

await renderer.writeSummary()
process.exit(0)
} else if (this.inputs.fromJSONFile) {
const stdout = await readFile(this.inputs.fromJSONFile)
const testEvents = parseTestEvents(stdout.toString())

const renderer = new Renderer(
moduleName,
testEvents,
'',
this.inputs.omit
)

await renderer.writeSummary()
process.exit(0)
} else {
Expand Down