Compare commits

...

102 Commits

Author SHA1 Message Date
Webber Takken
1fcc491cbe Accept PascalCase for testmodes EditMode and PlayMode (#115)
* Accept PascalCase for testmodes EditMode and PlayMode

* update index
2021-05-09 18:35:40 +02:00
dependabot-preview[bot]
73c6b8aa34 Upgrade to GitHub-native Dependabot (#114)
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2021-04-30 01:37:49 +02:00
Txema Martinez
694c315276 Run license activation in an empty directory (#109)
* Run license activation in an empty directory

* Create license directory in entrypoint.sh
2021-03-22 16:14:11 +01:00
David Finol
fffbf11b2a Small results-check refactor for debugging (#104)
* Small results-check refactor for debugging

* Fix #103
2021-03-06 00:55:03 -06:00
David Finol
a195213baa Update versioning.yml (#101) 2021-02-28 10:33:02 -06:00
David Finol
8033066291 Create versioning.yml (#100) 2021-02-28 10:02:56 -06:00
David Finol
215f660c06 Check GitHub token (#99)
* Reeplace createCheck option with check for githubToken

* Fix index.js
2021-02-28 00:44:56 -06:00
David Finol
43d90c252f Feature/create check (#97) 2021-02-27 12:13:19 -06:00
mob-sakai
345f4c64bd Security (#94)
* fix(test): embed unity license

* fix(test): checkout head

* fix(test): use `pull_request` event instead of `pull_request_target` event
2021-02-08 15:23:31 +01:00
Gabriel Le Breton
d45ca4403f Merge pull request #93 from game-ci/fix/readme
Update README.md
2021-02-06 20:04:03 -05:00
David Finol
7dd059111b Update README.md 2021-02-06 16:14:34 -06:00
David Finol
5edc17bb8a Fix Actions badge 2021-01-26 05:50:40 -06:00
Webber
23b6b8f5f3 Fix typo 2021-01-23 11:27:16 +01:00
Webber Takken
6e30d4827d secure license (#92)
* secure license

* Ignore runs for changes in github workflow...

... as it can become rather confusing if you try to change a workflow, but it doesn't trigger on the PR itself, but on main only.
2021-01-23 11:10:40 +01:00
Webber Takken
50e6471ee4 Expire artifacts faster (#91) 2021-01-23 10:44:31 +01:00
Webber
6a039cc828 Add cats 2021-01-23 10:39:27 +01:00
Vladimir Kryukov
2656f4e108 Cherry pick try-catch block to output results if build is failing (#90) 2021-01-17 21:55:27 +01:00
Vladimir Kryukov
e1be8325cd Add some component tests to reference unity project (#86)
* Add some component tests to reference unity project

* Use action/setup-node@v2 to avoid problems with build
2021-01-11 01:05:44 +01:00
Vladimir Kryukov
26807aaf05 Dependency bump (#88)
* Bump all dependencies to the latest versions

* Fix prettifier configuration after bump; Fix issues found by new versions of prettifier & eslint;

* Add information about yarn lint & test into CONTRIBUTING.md; Add better description of `yarn build` step in the pipeline
2021-01-11 01:05:18 +01:00
Webber Takken
a9d07b742d update deprecated (#87) 2021-01-07 23:16:29 +01:00
David Finol
0c3e710069 Get unityVersion from ProjectVersion.txt (#84) 2020-12-28 12:02:31 +01:00
mob-sakai
a067c3d5ab fix: parameter 'customImage' is not working (#83) 2020-12-17 14:30:51 +01:00
Webber Takken
3fca186a7b Fix typo 2020-12-06 18:12:42 +01:00
Webber Takken
a8b9742ecd remove anything recognizable as Unity (#82) 2020-12-06 17:45:57 +01:00
Devashish Lal
31cd755121 docker repo migrated (#77) 2020-11-26 18:19:17 +01:00
mob-sakai
679222c549 Update action.yml
Co-authored-by: Webber Takken <webber@takken.io>
2020-11-26 14:15:18 +01:00
mob-sakai
29899d84e8 feat: support custom image 2020-11-26 14:15:18 +01:00
Webber Takken
7d26e264b9 Switch to British english. 2020-11-10 18:18:18 +01:00
David LeGare
bac0f97d2f Add all parameters to action.yml
The added parameters were already supported but weren't listed, resulting in warnings for projects that use those parameters.
2020-11-10 18:18:18 +01:00
Webber
c4e44617e2 Add intructions for debugging 2020-09-27 21:37:15 +02:00
dependabot-preview[bot]
25e14f52b8 [Security] Bump node-fetch from 2.6.0 to 2.6.1
Bumps [node-fetch](https://github.com/bitinn/node-fetch) from 2.6.0 to 2.6.1. **This update includes a security fix.**
- [Release notes](https://github.com/bitinn/node-fetch/releases)
- [Changelog](https://github.com/node-fetch/node-fetch/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/bitinn/node-fetch/compare/v2.6.0...v2.6.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-12 05:30:38 +00:00
dependabot[bot]
3a40ffcf5f Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-25 22:51:46 +02:00
Webber
3277792c11 👷 add pull request template 2020-07-12 19:04:30 +02:00
Webber
ac2e8a74d0 Fix broken babel compat data 2020-07-11 21:18:47 +02:00
Webber
8107d46ab7 Move docs to unity-ci.com 2020-07-11 21:18:47 +02:00
Collin Dauphinee
a4e8475a2f Adding useHostNetwork option 2020-04-02 12:29:34 +02:00
dependabot-preview[bot]
f02586c1c9 [Security] Bump acorn from 6.4.0 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.4.0 to 6.4.1. **This update includes a security fix.**
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.4.0...6.4.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-13 22:29:38 +00:00
Webber
31ae95179d fix dist file and improve automation 2020-03-09 23:58:40 +01:00
litefeel
cd86c7302b Apply merge request suggestions 2020-03-09 23:57:17 +01:00
litefeel
21831e61ad Fixed compatibility 2020-03-09 23:57:17 +01:00
litefeel
7c1cba9a39 Change UNITY_LICENSE_PATH to UNITY_LICENSE_FILE 2020-03-09 23:57:17 +01:00
litefeel
29e179f50b Add UNITY_LICENSE_PATH 2020-03-09 23:57:17 +01:00
dependabot-preview[bot]
2fa69494ad Bump eslint-plugin-react from 7.18.3 to 7.19.0
Bumps [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react) from 7.18.3 to 7.19.0.
- [Release notes](https://github.com/yannickcr/eslint-plugin-react/releases)
- [Changelog](https://github.com/yannickcr/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yannickcr/eslint-plugin-react/compare/v7.18.3...v7.19.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-09 22:50:45 +00:00
dependabot-preview[bot]
4e717f6c82 Bump @babel/core from 7.8.6 to 7.8.7
Bumps [@babel/core](https://github.com/babel/babel) from 7.8.6 to 7.8.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.8.6...v7.8.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-05 09:08:43 +00:00
dependabot-preview[bot]
173716a8a9 Bump @babel/preset-env from 7.8.6 to 7.8.7
Bumps [@babel/preset-env](https://github.com/babel/babel) from 7.8.6 to 7.8.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.8.6...v7.8.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-05 09:00:03 +00:00
dependabot-preview[bot]
3c915726f4 Bump @babel/preset-env from 7.8.4 to 7.8.6
Bumps [@babel/preset-env](https://github.com/babel/babel) from 7.8.4 to 7.8.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.8.4...v7.8.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-28 09:08:30 +00:00
dependabot-preview[bot]
5cfdb7ee17 Bump @babel/core from 7.8.4 to 7.8.6
Bumps [@babel/core](https://github.com/babel/babel) from 7.8.4 to 7.8.6.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.8.4...v7.8.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-28 09:00:06 +00:00
dependabot-preview[bot]
51648a5093 Bump babel-eslint from 10.0.3 to 10.1.0
Bumps [babel-eslint](https://github.com/babel/babel-eslint) from 10.0.3 to 10.1.0.
- [Release notes](https://github.com/babel/babel-eslint/releases)
- [Commits](https://github.com/babel/babel-eslint/compare/v10.0.3...v10.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-27 23:05:12 +00:00
dependabot-preview[bot]
2297daa673 Bump lint-staged from 10.0.7 to 10.0.8
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 10.0.7 to 10.0.8.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v10.0.7...v10.0.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-26 09:00:20 +00:00
dependabot-preview[bot]
7711f454ba Bump @actions/github from 2.1.0 to 2.1.1
Bumps [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/master/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-21 08:41:39 +00:00
Webber
b518514f36 add dist build 2020-02-14 23:44:54 +01:00
dependabot-preview[bot]
7e50ed34dd Bump @zeit/ncc from 0.21.0 to 0.21.1
Bumps [@zeit/ncc](https://github.com/zeit/ncc) from 0.21.0 to 0.21.1.
- [Release notes](https://github.com/zeit/ncc/releases)
- [Commits](https://github.com/zeit/ncc/compare/0.21.0...0.21.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-14 23:44:54 +01:00
Alex Evgrashin
c85e37ca1f Fixed always passing action 2020-02-14 23:25:40 +01:00
Alex Evgrashin
58f580c801 Editor log now saves to artifacts folder 2020-02-13 21:58:50 +01:00
dependabot-preview[bot]
4ba71aefa9 Bump husky from 4.2.2 to 4.2.3
Bumps [husky](https://github.com/typicode/husky) from 4.2.2 to 4.2.3.
- [Release notes](https://github.com/typicode/husky/releases)
- [Changelog](https://github.com/typicode/husky/blob/master/CHANGELOG.md)
- [Commits](https://github.com/typicode/husky/compare/v4.2.2...v4.2.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-13 08:25:48 +00:00
dependabot-preview[bot]
bed834cb73 Bump eslint-plugin-unicorn from 16.0.0 to 16.1.1
Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 16.0.0 to 16.1.1.
- [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases)
- [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v16.0.0...v16.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-12 09:50:49 +01:00
dependabot-preview[bot]
eb51009c09 Bump husky from 4.2.1 to 4.2.2
Bumps [husky](https://github.com/typicode/husky) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/typicode/husky/releases)
- [Changelog](https://github.com/typicode/husky/blob/master/CHANGELOG.md)
- [Commits](https://github.com/typicode/husky/compare/v4.2.1...v4.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-12 09:36:01 +01:00
qwe321qwe321qwe321
da74d9ff8c Add Custom Parameters in PlayMode Testing 2020-02-12 00:40:29 +01:00
Webber
c8a0e2865a Update readme to reflect v1.4 2020-02-11 20:48:19 +01:00
Webber
627cf8f914 Add customParameters to test workflow 2020-02-11 20:46:27 +01:00
Webber
e9b4db003e Separate custom parameters 2020-02-11 20:46:27 +01:00
dependabot-preview[bot]
45a1728dfb Bump @babel/cli from 7.7.5 to 7.8.4
Bumps [@babel/cli](https://github.com/babel/babel) from 7.7.5 to 7.8.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.7.5...v7.8.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-11 10:28:03 +01:00
dependabot-preview[bot]
f854b54cb0 Bump eslint from 6.7.2 to 6.8.0
Bumps [eslint](https://github.com/eslint/eslint) from 6.7.2 to 6.8.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v6.7.2...v6.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-11 10:27:53 +01:00
dependabot-preview[bot]
6948da8f6a Bump eslint-config-prettier from 6.7.0 to 6.10.0
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 6.7.0 to 6.10.0.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/master/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/commits/v6.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-11 10:27:41 +01:00
dependabot-preview[bot]
922dcd8b1a Bump @babel/preset-env from 7.7.7 to 7.8.4
Bumps [@babel/preset-env](https://github.com/babel/babel) from 7.7.7 to 7.8.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.7.7...v7.8.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 16:50:31 +01:00
dependabot-preview[bot]
c8909e4d5e Bump lint-staged from 9.5.0 to 10.0.7
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 9.5.0 to 10.0.7.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v9.5.0...v10.0.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 16:25:24 +01:00
dependabot-preview[bot]
060d1856e7 Bump eslint-plugin-unicorn from 14.0.1 to 16.0.0
Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 14.0.1 to 16.0.0.
- [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases)
- [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v14.0.1...v16.0.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 16:25:10 +01:00
dependabot-preview[bot]
6bacc4484e Bump @zeit/ncc from 0.20.5 to 0.21.0
Bumps [@zeit/ncc](https://github.com/zeit/ncc) from 0.20.5 to 0.21.0.
- [Release notes](https://github.com/zeit/ncc/releases)
- [Commits](https://github.com/zeit/ncc/compare/0.20.5...0.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 14:16:18 +01:00
dependabot-preview[bot]
892b3b8279 Bump jest from 24.9.0 to 25.1.0
Bumps [jest](https://github.com/facebook/jest) from 24.9.0 to 25.1.0.
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/compare/v24.9.0...v25.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-10 14:16:03 +01:00
snyk-bot
00afc45f14 fix: upgrade @actions/exec from 1.0.2 to 1.0.3
Snyk has created this PR to upgrade @actions/exec from 1.0.2 to 1.0.3.

See this package in NPM:
https://www.npmjs.com/package/@actions/exec

See this project in Snyk:
https://app.snyk.io/org/webbertakken/project/89dd41e1-8254-4c72-ab5d-3b28b3093f1b?utm_source=github&utm_medium=upgrade-pr
2020-02-10 00:37:07 +01:00
snyk-bot
868c383d7f fix: upgrade @actions/github from 2.0.0 to 2.0.1
Snyk has created this PR to upgrade @actions/github from 2.0.0 to 2.0.1.

See this package in NPM:
https://www.npmjs.com/package/@actions/github

See this project in Snyk:
https://app.snyk.io/org/webbertakken/project/89dd41e1-8254-4c72-ab5d-3b28b3093f1b?utm_source=github&utm_medium=upgrade-pr
2020-02-10 00:19:07 +01:00
Webber
54d8d414ea Add updated dist file 2020-02-10 00:18:52 +01:00
snyk-bot
057deedeb0 fix: upgrade @actions/core from 1.2.0 to 1.2.1
Snyk has created this PR to upgrade @actions/core from 1.2.0 to 1.2.1.

See this package in NPM:
https://www.npmjs.com/package/@actions/core

See this project in Snyk:
https://app.snyk.io/org/webbertakken/project/89dd41e1-8254-4c72-ab5d-3b28b3093f1b?utm_source=github&utm_medium=upgrade-pr
2020-02-10 00:18:52 +01:00
dependabot-preview[bot]
d64e5a8b19 Bump eslint-plugin-import from 2.19.1 to 2.20.1
Bumps [eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) from 2.19.1 to 2.20.1.
- [Release notes](https://github.com/benmosher/eslint-plugin-import/releases)
- [Changelog](https://github.com/benmosher/eslint-plugin-import/blob/master/CHANGELOG.md)
- [Commits](https://github.com/benmosher/eslint-plugin-import/compare/v2.19.1...v2.20.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-08 19:09:25 +01:00
dependabot-preview[bot]
711a3ee644 Bump @babel/core from 7.7.5 to 7.8.4
Bumps [@babel/core](https://github.com/babel/babel) from 7.7.5 to 7.8.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/compare/v7.7.5...v7.8.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-08 19:09:16 +01:00
dependabot-preview[bot]
39da97ffa3 Bump eslint-plugin-react from 7.17.0 to 7.18.3
Bumps [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react) from 7.17.0 to 7.18.3.
- [Release notes](https://github.com/yannickcr/eslint-plugin-react/releases)
- [Changelog](https://github.com/yannickcr/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yannickcr/eslint-plugin-react/compare/v7.17.0...v7.18.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-08 18:50:51 +01:00
dependabot-preview[bot]
1473c8f431 Bump eslint-plugin-flowtype from 4.5.2 to 4.6.0
Bumps [eslint-plugin-flowtype](https://github.com/gajus/eslint-plugin-flowtype) from 4.5.2 to 4.6.0.
- [Release notes](https://github.com/gajus/eslint-plugin-flowtype/releases)
- [Commits](https://github.com/gajus/eslint-plugin-flowtype/compare/v4.5.2...v4.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-08 17:33:51 +01:00
dependabot-preview[bot]
c210544758 Bump husky from 4.0.0-beta.5 to 4.2.1
Bumps [husky](https://github.com/typicode/husky) from 4.0.0-beta.5 to 4.2.1.
- [Release notes](https://github.com/typicode/husky/releases)
- [Changelog](https://github.com/typicode/husky/blob/master/CHANGELOG.md)
- [Commits](https://github.com/typicode/husky/compare/v4.0.0-beta.5...v4.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-08 15:16:29 +01:00
Webber Takken
f863c717a4 Update README.md 2020-02-01 21:14:04 +01:00
Webber
5423e61ad7 fix custom parameters 2020-02-01 20:45:21 +01:00
Webber
377244a880 badge now only reflects status of upstream master 2020-02-01 19:41:52 +01:00
Webber
6f1c3ded0c Fix bug in readme 2020-01-31 01:15:59 +01:00
Webber
b181c9cdbe Add missing env 2020-01-31 01:15:59 +01:00
Webber
d5a5335100 Simplify explanation about id's 2020-01-31 01:15:59 +01:00
Webber
c937b9ed6c Update docs 2020-01-31 01:15:59 +01:00
Webber
56b8c04f36 Remove 2018 until multi-serial support 2020-01-31 01:15:59 +01:00
Webber
a18b837919 Update and test folder regex 2020-01-31 01:15:59 +01:00
Webber
033a0990cb Test one version 2020-01-31 01:15:59 +01:00
Webber
24fe88806a Save the best for last 2020-01-31 01:15:59 +01:00
Webber
e2f2badc29 Update workflow to use with instead of env 2020-01-31 01:15:59 +01:00
Webber
3ccd77fd44 Add custom parameters 2020-01-31 01:15:59 +01:00
Webber
686f633329 Add steps to dockerfile 2020-01-31 01:15:59 +01:00
Webber
28154ea36e Enforce real folder names 2020-01-31 01:15:59 +01:00
Webber
2ca91788af Split up steps and implement license management 2020-01-31 01:15:59 +01:00
Webber
2d11601618 Add tests to pipeline 2020-01-31 01:15:59 +01:00
Webber
545600f75b Make image variable 2020-01-31 01:15:59 +01:00
Webber
d6c937fe37 Add action logic 2020-01-31 01:15:59 +01:00
Webber
d105f8c891 Move dockerfile and entrypoint to action folder 2020-01-31 01:15:59 +01:00
Webber
048c75a66e Add meta files 2020-01-31 01:15:59 +01:00
Webber
a08a398026 Add workflow caching and strategy for multiple versions 2020-01-31 01:15:59 +01:00
Webber
311b685893 Add static license file to allow for PRs 2020-01-31 01:15:59 +01:00
Michael Bradley
3d7f5a853b Fix mislabeled header in entrypoint.sh
Both test mode results were labeled "Edit Mode".
2019-12-15 21:01:18 +01:00
65 changed files with 8609 additions and 166 deletions

21
.editorconfig Normal file
View File

@@ -0,0 +1,21 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 100
tab_width = 2
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false
[*.{yml,yaml}]
max_line_length = off
[COMMIT_EDITMSG]
max_line_length = off

2
.eslintignore Normal file
View File

@@ -0,0 +1,2 @@
**/node_modules/**
**/action/**

22
.eslintrc.json Normal file
View File

@@ -0,0 +1,22 @@
{
"parser": "babel-eslint",
"env": {
"node": true,
"es6": true,
"jest": true
},
"parserOptions": {
"ecmaVersion": 2020,
"ecmaFeatures": {
"impliedStrict": true
}
},
"extends": ["airbnb", "plugin:unicorn/recommended", "prettier"],
"plugins": ["react", "jsx-a11y", "import", "prettier", "flowtype", "unicorn"],
"settings": { "react": { "version": "latest" } },
"rules": {
"prettier/prettier": "error",
"import/no-extraneous-dependencies": 0,
"no-underscore-dangle": 0
}
}

7
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10

9
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,9 @@
#### Changes
- ...
#### Checklist
- [x] Read the contribution [guide](../CONTRIBUTING.md) and accept the [code](../CODE_OF_CONDUCT.md) of conduct
- [ ] Readme (updated or not needed)
- [ ] Tests (added, updated or not needed)

16
.github/workflows/cats.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: Cats 😺
on:
pull_request_target:
types:
- opened
- reopened
jobs:
aCatForCreatingThePullRequest:
name: A cat for your effort!
runs-on: ubuntu-latest
steps:
- uses: ruairidhwm/action-cats@1.0.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,132 +1,265 @@
name: Actions 😎
on:
pull_request: {}
push: { branches: [master] }
push: { branches: [main] }
pull_request:
paths-ignore:
- '.github/**'
env:
UNITY_LICENSE: "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root>\n <License id=\"Terms\">\n <MachineBindings>\n <Binding Key=\"1\" Value=\"576562626572264761624c65526f7578\"/>\n <Binding Key=\"2\" Value=\"576562626572264761624c65526f7578\"/>\n </MachineBindings>\n <MachineID Value=\"D7nTUnjNAmtsUMcnoyrqkgIbYdM=\"/>\n <SerialHash Value=\"2033b8ac3e6faa3742ca9f0bfae44d18f2a96b80\"/>\n <Features>\n <Feature Value=\"33\"/>\n <Feature Value=\"1\"/>\n <Feature Value=\"12\"/>\n <Feature Value=\"2\"/>\n <Feature Value=\"24\"/>\n <Feature Value=\"3\"/>\n <Feature Value=\"36\"/>\n <Feature Value=\"17\"/>\n <Feature Value=\"19\"/>\n <Feature Value=\"62\"/>\n </Features>\n <DeveloperData Value=\"AQAAAEY0LUJHUlgtWEQ0RS1aQ1dWLUM1SlctR0RIQg==\"/>\n <SerialMasked Value=\"F4-BGRX-XD4E-ZCWV-C5JW-XXXX\"/>\n <StartDate Value=\"2021-02-08T00:00:00\"/>\n <UpdateDate Value=\"2021-02-09T00:34:57\"/>\n <InitialActivationDate Value=\"2021-02-08T00:34:56\"/>\n <LicenseVersion Value=\"6.x\"/>\n <ClientProvidedVersion Value=\"2018.4.30f1\"/>\n <AlwaysOnline Value=\"false\"/>\n <Entitlements>\n <Entitlement Ns=\"unity_editor\" Tag=\"UnityPersonal\" Type=\"EDITOR\" ValidTo=\"9999-12-31T00:00:00\"/>\n <Entitlement Ns=\"unity_editor\" Tag=\"DarkSkin\" Type=\"EDITOR_FEATURE\" ValidTo=\"9999-12-31T00:00:00\"/>\n </Entitlements>\n </License>\n<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><SignedInfo><CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments\"/><SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha1\"/><Reference URI=\"#Terms\"><Transforms><Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/></Transforms><DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"/><DigestValue>m0Db8UK+ktnOLJBtHybkfetpcKo=</DigestValue></Reference></SignedInfo><SignatureValue>o/pUbSQAukz7+ZYAWhnA0AJbIlyyCPL7bKVEM2lVqbrXt7cyey+umkCXamuOgsWPVUKBMkXtMH8L\n5etLmD0getWIhTGhzOnDCk+gtIPfL4jMo9tkEuOCROQAXCci23VFscKcrkB+3X6h4wEOtA2APhOY\nB+wvC794o8/82ffjP79aVAi57rp3Wmzx+9pe9yMwoJuljAy2sc2tIMgdQGWVmOGBpQm3JqsidyzI\nJWG2kjnc7pDXK9pwYzXoKiqUqqrut90d+kQqRyv7MSZXR50HFqD/LI69h68b7P8Bjo3bPXOhNXGR\n9YCoemH6EkfCJxp2gIjzjWW+l2Hj2EsFQi8YXw==</SignatureValue></Signature></root>"
jobs:
tests:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 12.x
- run: yarn
- run: yarn lint
- run: yarn test
- run: yarn build || { echo "build command should always succeed" ; exit 61; }
- run: yarn build --quiet && git diff --quiet action || { echo "ERROR - index.js is different from repository version. Forgot to run `yarn build`?" ; exit 62; }
testAllModesLikeInTheReadme:
name: Test in ${{ matrix.testMode }} on version ${{ matrix.unityVersion }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- unity-project-with-correct-tests
unityVersion:
- 2019.2.11f1
testMode:
- playmode
- editmode
steps:
###########################
# Checkout #
###########################
- name: Checkout
uses: actions/checkout@v2
with:
lfs: true
###########################
# Cache #
###########################
- uses: actions/cache@v2
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}
restore-keys: |
Library-
- uses: ./
id: tests
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: ${{ matrix.testMode }}
artifactsPath: ${{ matrix.testMode }}-artifacts
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
- uses: actions/upload-artifact@v2
with:
name: Test results for ${{ matrix.testMode }}
path: ${{ steps.tests.outputs.artifactsPath }}
retention-days: 14
testRunnerInAllModes:
name: Test all modes ✨
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- unity-project-with-correct-tests
unityVersion:
- 2019.2.11f1
steps:
# Checkout repository (required to test local actions)
- name: Checkout repository
uses: actions/checkout@v1
###########################
# Checkout #
###########################
- uses: actions/checkout@v2
with:
lfs: true
# Activate license
- name: Activate Unity
uses: webbertakken/unity-activate@v1
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
###########################
# Cache #
###########################
- uses: actions/cache@v1.1.0
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
# Configure test runner
- name: Run tests
id: allTests
uses: ./
env:
TEST_MODE: all
PROJECT_PATH: unity-project-with-correct-tests
# Test implicit ARTIFACTS_PATH, by not setting it
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: all
# Test implicit artifactsPath, by not setting it
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
with:
name: Test results (all)
path: ${{ steps.allTests.outputs.artifactsPath }}
retention-days: 14
testRunnerInEditMode:
name: Test edit mode 📝
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
unityVersion:
- 2019.2.11f1
projectPath:
- unity-project-with-correct-tests
steps:
# Checkout repository (required to test local actions)
- name: Checkout repository
uses: actions/checkout@v1
###########################
# Checkout #
###########################
- uses: actions/checkout@v2
with:
lfs: true
# Activate license
- name: Activate Unity
uses: webbertakken/unity-activate@v1
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
###########################
# Cache #
###########################
- uses: actions/cache@v1.1.0
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
# Configure test runner
- name: Run tests
id: editMode
uses: ./
env:
TEST_MODE: editmode
PROJECT_PATH: unity-project-with-correct-tests
ARTIFACTS_PATH: artifacts/editmode
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: editmode
artifactsPath: artifacts/editmode
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
with:
name: Test results (edit mode)
path: ${{ steps.editMode.outputs.artifactsPath }}
retention-days: 14
testRunnerInPlayMode:
name: Test play mode 📺
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- unity-project-with-correct-tests
unityVersion:
- 2019.2.11f1
steps:
# Checkout repository (required to test local actions)
- name: Checkout repository
uses: actions/checkout@v1
###########################
# Checkout #
###########################
- uses: actions/checkout@v2
with:
lfs: true
# Activate license
- name: Activate Unity
uses: webbertakken/unity-activate@v1
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
###########################
# Cache #
###########################
- uses: actions/cache@v1.1.0
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
# Configure test runner
- name: Run tests
id: playMode
uses: ./
env:
TEST_MODE: playmode
PROJECT_PATH: unity-project-with-correct-tests
ARTIFACTS_PATH: artifacts/editmode
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: playmode
artifactsPath: artifacts/playmode
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
with:
name: Test results (play mode)
path: ${{ steps.playMode.outputs.artifactsPath }}
retention-days: 14
testRunnerInEachModeSeparately:
testEachModeSequentially:
name: Test each mode sequentially 👩‍👩‍👧‍👦 # don't try this at home (it's much slower)
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
unityVersion:
- 2019.2.11f1
projectPath:
- unity-project-with-correct-tests
steps:
# Checkout repository (required to test local actions)
- name: Checkout repository
uses: actions/checkout@v1
###########################
# Checkout #
###########################
- uses: actions/checkout@v2
with:
lfs: true
# Activate license
- name: Activate Unity
uses: webbertakken/unity-activate@v1
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
###########################
# Cache #
###########################
- uses: actions/cache@v1.1.0
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
# Configure first test runner
- name: Tests in editmode 📝
uses: ./
env:
TEST_MODE: editmode
PROJECT_PATH: unity-project-with-correct-tests
ARTIFACTS_PATH: artifacts/editmode
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: editmode
artifactsPath: artifacts/editmode
# Configure second test runner
- name: Tests in playmode 📺
uses: ./
env:
TEST_MODE: playmode
PROJECT_PATH: unity-project-with-correct-tests
ARTIFACTS_PATH: artifacts/playmode
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: playmode
artifactsPath: artifacts/playmode
# Upload combined artifacts
- name: Upload combined test results
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
with:
name: Test results (combined)
path: artifacts/
retention-days: 14

14
.github/workflows/versioning.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: Versioning
on:
release:
types: [published, edited]
jobs:
updateMajorTag:
name: Update major tag
runs-on: ubuntu-latest
steps:
- uses: Actions-R-Us/actions-tagger@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -1 +1,2 @@
.idea
node_modules

2
.prettierignore Normal file
View File

@@ -0,0 +1,2 @@
**/node_modules/**
**/action/**

7
.prettierrc.json Normal file
View File

@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"arrowParens": "avoid"
}

3
.yarnrc Normal file
View File

@@ -0,0 +1,3 @@
save-prefix ""
--install.audit true
--add.audit true

76
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or
advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at webber@takken.io. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

39
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,39 @@
# Contributing
## How to Contribute
#### Code of Conduct
This repository has adopted the Contributor Covenant as it's
Code of Conduct. It is expected that participants adhere to it.
#### Proposing a Change
If you are unsure about whether or not a change is desired,
you can create an issue. This is useful because it creates
the possibility for a discussion that's visible to everyone.
When fixing a bug it is fine to submit a pull request right away.
#### Sending a Pull Request
Steps to be performed to submit a pull request:
1. Fork the repository and create your branch from `master`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Fill out the description, link any related issues and submit your pull request.
#### Pull Request Prerequisites
You have [Node](https://nodejs.org/) installed at v12.2.0+ and [Yarn](https://yarnpkg.com/) at v1.18.0+.
Please note that commit hooks will run automatically to perform some tasks;
- format your code
- run tests & lint - `yarn lint && yarn test`
- build distributable files - `yarn build`
#### License
By contributing to this repository, you agree that your contributions will be licensed under its MIT license.

View File

@@ -1,81 +1,44 @@
# Unity - Test runner
[![Actions status](https://github.com/webbertakken/unity-test-runner/workflows/Actions%20%F0%9F%98%8E/badge.svg)](https://github.com/webbertakken/unity-test-runner/actions?query=branch%3Amaster+workflow%3A%22Actions+%F0%9F%98%8E%22)
---
(Not affiliated with Unity Technologies)
GitHub Action to
[run tests](https://github.com/marketplace/actions/unity-test-runner)
for any Unity project.
GitHub Action to
[run tests](https://github.com/marketplace/actions/unity-test-runner)
for any Unity project.
Part of the
[Unity Actions](https://github.com/webbertakken/unity-actions)
collection.
Part of the <a href="https://game.ci">GameCI</a> open source project.
<br />
<br />
---
[![Actions status](https://github.com/game-ci/unity-test-runner/workflows/Actions%20%F0%9F%98%8E/badge.svg)](https://github.com/game-ci/unity-test-runner/actions?query=workflow%3A%22Actions+%F0%9F%98%8E%22)
<br />
<br />
This is a recommended step to prepare your pipeline for using the
[Build](https://github.com/webbertakken/unity-actions#build)
action. This action also requires the [activation](https://github.com/marketplace/actions/unity-activate) step.
## How to use
## Documentation
Find the
[docs](https://game.ci/docs/github/test-runner)
on the GameCI
[documentation website](https://game.ci/docs).
See the
[Unity Actions](https://github.com/webbertakken/unity-actions)
collection repository for workflow documentation and reference implementation.
## Related actions
## Usage
Visit the
GameCI <a href="https://github.com/game-ci/unity-actions">Unity Actions</a>
status repository for related Actions.
Create or edit the file called `.github/workflows/main.yml` and add a job to it.
## Community
```yaml
name: Test project
on: [push]
jobs:
testRunnerInAllModes:
name: Test all modes ✨
runs-on: ubuntu-latest
steps:
```
Feel free to join us on
<a href="http://game.ci/discord"><img height="30" src="media/Discord-Logo.svg" alt="Discord" /></a>
and engage with the community.
Configure the test runner as follows:
## Contributing
```yaml
# Configure test runner
- name: Run tests
id: myTestStep
uses: webbertakken/unity-test-runner@v1.1
env:
# Choose: "all", "playmode", "editmode"
TEST_MODE: all
# Optional: Path to your project, leave blank for "./"
PROJECT_PATH: relative/path/to/your/project
To help improve the documentation, please find the docs [repository](https://github.com/game-ci/documentation).
# Optional: Artifacts path, leave blank for "artifacts"
ARTIFACTS_PATH: store/artifacts/here
```
To contribute to this project, kindly read the [contribution guide](./CONTRIBUTING.md).
You use the id to **upload the artifacts** like so:
```yaml
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v1
with:
name: Test results
path: ${{ steps.myTestStep.outputs.artifactsPath }}
```
Commit and push your workflow definition.
## More actions
Visit
[Unity Actions](https://github.com/webbertakken/unity-actions)
to find related actions for Unity.
Feel free to contribute.
## Licence
## Licence
[MIT](./LICENSE)

View File

@@ -1,13 +1,47 @@
name: 'Unity - Test runner'
author: Webber Takken <webber@takken.io>
description: 'Run tests for any Unity project.'
inputs: {}
inputs:
unityVersion:
required: false
default: 'auto'
description: 'Version of unity to use for testing the project. Use "auto" to get from your ProjectSettings/ProjectVersion.txt'
customImage:
required: false
default: ''
description: 'Specific docker image that should be used for testing the project'
projectPath:
required: false
description: 'Path to the Unity project to be tested.'
testMode:
required: false
default: 'all'
description: 'The type of tests to be run by the test runner.'
artifactsPath:
required: false
default: 'artifacts'
description: 'Path where test artifacts should be stored.'
useNetworkHost:
required: false
default: false
description: 'Initialises Docker using the hosts network.'
customParameters:
required: false
description: 'Extra parameters to configure the Unity editor run.'
githubToken:
required: false
default: ''
description: 'Token to authorize access to the GitHub REST API. If provided, a check run will be created with the test results.'
checkName:
required: false
default: 'Test Results'
description: 'Name for the check run that is created when a github token is provided.'
outputs:
artifactsPath:
description: 'Path where the artifacts are stored'
runs:
using: 'docker'
image: 'Dockerfile'
branding:
icon: 'box'
color: 'gray-dark'
runs:
using: 'node12'
main: 'action/index.js'

View File

@@ -1,4 +1,5 @@
FROM gableroux/unity3d:2019.2.11f1
ARG IMAGE
FROM $IMAGE
LABEL "com.github.actions.name"="Unity - Test runner"
LABEL "com.github.actions.description"="Run tests for any Unity project."
@@ -9,6 +10,8 @@ LABEL "repository"="http://github.com/webbertakken/unity-actions"
LABEL "homepage"="http://github.com/webbertakken/unity-actions"
LABEL "maintainer"="Webber Takken <webber@takken.io>"
ADD steps /steps
RUN chmod -R +x /steps
ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

47
action/entrypoint.sh Normal file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env bash
#
# Create directory for license activation
#
ACTIVATE_LICENSE_PATH="$GITHUB_WORKSPACE/_activate-license"
mkdir -p "$ACTIVATE_LICENSE_PATH"
#
# Run steps
#
source /steps/activate.sh
source /steps/run_tests.sh
source /steps/return_license.sh
#
# Remove license activation directory
#
rm -r "$ACTIVATE_LICENSE_PATH"
#
# Instructions for debugging
#
if [[ $TEST_RUNNER_EXIT_CODE -gt 0 ]]; then
echo ""
echo "###########################"
echo "# Failure #"
echo "###########################"
echo ""
echo "Please note that the exit code is not very descriptive."
echo "Most likely it will not help you solve the issue."
echo ""
echo "To find the reason for failure: please search for errors in the log above."
echo ""
fi;
#
# Exit with code from the build step.
#
if [ $USE_EXIT_CODE = true ]; then
exit $TEST_RUNNER_EXIT_CODE
fi;

1
action/index.js Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
{{#runs}}
<details><summary>{{summary}}</summary>
{{#suites}}
* {{summary}}
{{#tests}}
* {{summary}}
{{#if annotation}}
{{indent annotation.message}}
{{indent annotation.raw_details}}
{{/if}}
{{/tests}}
{{/suites}}
</details>
{{/runs}}

View File

@@ -0,0 +1,3 @@
{{#runs}}
### {{summary}}
{{/runs}}

111
action/steps/activate.sh Normal file
View File

@@ -0,0 +1,111 @@
#!/usr/bin/env bash
# Run in ACTIVATE_LICENSE_PATH directory
echo "Changing to \"$ACTIVATE_LICENSE_PATH\" directory."
pushd "$ACTIVATE_LICENSE_PATH"
if [[ -n "$UNITY_LICENSE" ]] || [[ -n "$UNITY_LICENSE_FILE" ]]; then
#
# PERSONAL LICENSE MODE
#
# This will activate Unity, using a license file
#
# Note that this is the ONLY WAY for PERSONAL LICENSES in 2020.
# * See for more details: https://gitlab.com/gableroux/unity3d-gitlab-ci-example/issues/5#note_72815478
#
# The license file can be acquired using `game-ci/request-manual-activation-file` action.
echo "Requesting activation (personal license)"
# Set the license file path
FILE_PATH=UnityLicenseFile.ulf
if [[ -n "$UNITY_LICENSE" ]]; then
# Copy license file from Github variables
echo "$UNITY_LICENSE" | tr -d '\r' > $FILE_PATH
elif [[ -n "$UNITY_LICENSE_FILE" ]]; then
# Copy license file from file system
cat "$UNITY_LICENSE_FILE" | tr -d '\r' > $FILE_PATH
fi
# Activate license
ACTIVATION_OUTPUT=$(unity-editor \
-batchmode \
-nographics \
-logFile /dev/stdout \
-quit \
-manualLicenseFile $FILE_PATH)
# Store the exit code from the verify command
UNITY_EXIT_CODE=$?
# The exit code for personal activation is always 1;
# Determine whether activation was successful.
#
# Successful output should include the following:
#
# "LICENSE SYSTEM [2020120 18:51:20] Next license update check is after 2019-11-25T18:23:38"
#
ACTIVATION_SUCCESSFUL=$(echo $ACTIVATION_OUTPUT | grep 'Next license update check is after' | wc -l)
# Set exit code to 0 if activation was successful
if [[ $ACTIVATION_SUCCESSFUL -eq 1 ]]; then
UNITY_EXIT_CODE=0
fi;
# Remove license file
rm -f $FILE_PATH
elif [[ -n "$UNITY_SERIAL" && -n "$UNITY_EMAIL" && -n "$UNITY_PASSWORD" ]]; then
#
# PROFESSIONAL (SERIAL) LICENSE MODE
#
# This will activate unity, using the activating process.
#
# Note: This is the preferred way for PROFESSIONAL LICENSES.
#
echo "Requesting activation (professional license)"
# Activate license
unity-editor \
-batchmode \
-nographics \
-logFile /dev/stdout \
-quit \
-serial "$UNITY_SERIAL" \
-username "$UNITY_EMAIL" \
-password "$UNITY_PASSWORD"
# Store the exit code from the verify command
UNITY_EXIT_CODE=$?
else
#
# NO LICENSE ACTIVATION STRATEGY MATCHED
#
# This will exit since no activation strategies could be matched.
#
echo "License activation strategy could not be determined."
echo ""
echo "Visit https://github.com/webbertakken/unity-builder#usage for more"
echo "details on how to set up one of the possible activation strategies."
# Immediately exit as no UNITY_EXIT_CODE can be derived.
exit 1;
fi
#
# Display information about the result
#
if [ $UNITY_EXIT_CODE -eq 0 ]; then
# Activation was a success
echo "Activation complete."
else
# Activation failed so exit with the code from the license verification step
echo "Unclassified error occured while trying to activate license."
echo "Exit code was: $UNITY_EXIT_CODE"
exit $UNITY_EXIT_CODE
fi
# Return to previous working directory
popd

View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# Run in ACTIVATE_LICENSE_PATH directory
echo "Changing to \"$ACTIVATE_LICENSE_PATH\" directory."
pushd "$ACTIVATE_LICENSE_PATH"
if [[ -n "$UNITY_SERIAL" ]]; then
#
# PROFESSIONAL (SERIAL) LICENSE MODE
#
# This will return the license that is currently in use.
#
unity-editor \
-batchmode \
-nographics \
-logFile /dev/stdout \
-quit \
-returnlicense
fi
# Return to previous working directory
popd

View File

@@ -1,14 +1,24 @@
#!/usr/bin/env bash
# Set the license file path
UNITY_PROJECT_PATH=$GITHUB_WORKSPACE/$PROJECT_PATH
#
# Set and display project path
#
# Set the artifacts path
if [ -z "$ARTIFACTS_PATH" ]; then
ARTIFACTS_PATH=artifacts
fi
UNITY_PROJECT_PATH="$GITHUB_WORKSPACE/$PROJECT_PATH"
echo "Using project path \"$UNITY_PROJECT_PATH\"."
#
# Set and display the artifacts path
#
echo "Using artifacts path \"$ARTIFACTS_PATH\" to save test results."
FULL_ARTIFACTS_PATH=$GITHUB_WORKSPACE/$ARTIFACTS_PATH
#
# Display custom parameters
#
echo "Using custom parameters $CUSTOM_PARAMETERS."
# Set the modes for testing
case $TEST_MODE in
editmode)
@@ -29,6 +39,12 @@ esac
# The following tests are 2019 mode (requires Unity 2019.2.11f1 or later)
# Reference: https://docs.unity3d.com/2019.3/Documentation/Manual/CommandLineArguments.html
#
# Display the unity version
#
echo "Using Unity version \"$UNITY_VERSION\" to test."
#
# Overall info
#
@@ -58,18 +74,21 @@ if [ $EDIT_MODE = true ]; then
echo "# Testing in EditMode #"
echo "###########################"
echo ""
xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
/opt/Unity/Editor/Unity \
-batchmode \
-logfile /dev/stdout \
-projectPath "$UNITY_PROJECT_PATH" \
-runTests \
-testPlatform editmode \
-testResults "$FULL_ARTIFACTS_PATH/editmode-results.xml"
unity-editor \
-batchmode \
-logFile "$FULL_ARTIFACTS_PATH/editmode.log" \
-projectPath "$UNITY_PROJECT_PATH" \
-runTests \
-testPlatform editmode \
-testResults "$FULL_ARTIFACTS_PATH/editmode-results.xml" \
$CUSTOM_PARAMETERS
# Catch exit code
EDIT_MODE_EXIT_CODE=$?
# Print unity log output
cat "$FULL_ARTIFACTS_PATH/editmode.log"
# Display results
if [ $EDIT_MODE_EXIT_CODE -eq 0 ]; then
echo "Run succeeded, no failures occurred";
@@ -92,18 +111,21 @@ if [ $PLAY_MODE = true ]; then
echo "# Testing in PlayMode #"
echo "###########################"
echo ""
xvfb-run --auto-servernum --server-args='-screen 0 640x480x24' \
/opt/Unity/Editor/Unity \
-batchmode \
-logfile /dev/stdout \
-projectPath "$UNITY_PROJECT_PATH" \
-runTests \
-testPlatform playmode \
-testResults "$FULL_ARTIFACTS_PATH/playmode-results.xml"
unity-editor \
-batchmode \
-logFile "$FULL_ARTIFACTS_PATH/playmode.log" \
-projectPath "$UNITY_PROJECT_PATH" \
-runTests \
-testPlatform playmode \
-testResults "$FULL_ARTIFACTS_PATH/playmode-results.xml" \
$CUSTOM_PARAMETERS
# Catch exit code
PLAY_MODE_EXIT_CODE=$?
# Print unity log output
cat "$FULL_ARTIFACTS_PATH/playmode.log"
# Display results
if [ $PLAY_MODE_EXIT_CODE -eq 0 ]; then
echo "Run succeeded, no failures occurred";
@@ -140,28 +162,21 @@ fi
if [ $PLAY_MODE = true ]; then
echo ""
echo "###########################"
echo "# Edit Mode Results #"
echo "# Play Mode Results #"
echo "###########################"
echo ""
cat "$FULL_ARTIFACTS_PATH/playmode-results.xml"
cat "$FULL_ARTIFACTS_PATH/playmode-results.xml" | grep test-run | grep Passed
fi
#
# Output variables
#
# Set resulting name as output variable
echo ::set-output name=artifactsPath::$ARTIFACTS_PATH
#
# Exit
#
if [ $EDIT_MODE_EXIT_CODE -gt 0 ]; then
exit $EDIT_MODE_EXIT_CODE
TEST_RUNNER_EXIT_CODE=$EDIT_MODE_EXIT_CODE
fi
if [ $PLAY_MODE_EXIT_CODE -gt 0 ]; then
exit $PLAY_MODE_EXIT_CODE
TEST_RUNNER_EXIT_CODE=$PLAY_MODE_EXIT_CODE
fi

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<test-run id="2" testcasecount="6" result="Failed(Child)" total="6" passed="2" failed="2" inconclusive="0" skipped="2" asserts="0" engine-version="3.5.0.0" clr-version="4.0.30319.42000" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.1168037">
<test-suite type="TestSuite" id="1012" name="sample-project" fullname="sample-project" runstate="Runnable" testcasecount="6" result="Failed" site="Child" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.116804" total="6" passed="2" failed="2" inconclusive="0" skipped="2" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="Assembly" id="1020" name="Editor.dll" fullname="/github/workspace/unity-project/Library/ScriptAssemblies/Editor.dll" runstate="Runnable" testcasecount="6" result="Failed" site="Child" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.087946" total="6" passed="2" failed="2" inconclusive="0" skipped="2" asserts="0">
<properties>
<property name="_PID" value="78" />
<property name="_APPDOMAIN" value="Unity Child Domain" />
<property name="platform" value="EditMode" />
</properties>
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="1021" name="Editor" fullname="Editor" runstate="Runnable" testcasecount="6" result="Failed" site="Child" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.086212" total="6" passed="2" failed="2" inconclusive="0" skipped="2" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestFixture" id="1013" name="EditorModeTest" fullname="Editor.EditorModeTest" classname="Editor.EditorModeTest" runstate="Runnable" testcasecount="6" result="Failed" site="Child" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.076416" total="6" passed="2" failed="2" inconclusive="0" skipped="2" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<output><![CDATA[You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all
]]></output>
<test-case id="1016" name="FailedTest" fullname="Editor.EditorModeTest.FailedTest" methodname="FailedTest" classname="Editor.EditorModeTest" runstate="Runnable" seed="330279882" result="Failed" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.023093" asserts="0">
<properties />
<failure>
<message><![CDATA[ Expected: True
But was: False
]]></message>
<stack-trace><![CDATA[at Editor.EditorModeTest.FailedTest () [0x00000] in /github/workspace/unity-project/Assets/Editor/EditorModeTest.cs:21
]]></stack-trace>
</failure>
</test-case>
<test-case id="1019" name="FailedUnityTest" fullname="Editor.EditorModeTest.FailedUnityTest" methodname="FailedUnityTest" classname="Editor.EditorModeTest" runstate="Runnable" seed="347277877" result="Failed" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.014203" asserts="0">
<properties>
<property name="_JOINTYPE" value="UnityCombinatorial" />
</properties>
<failure>
<message><![CDATA[ Expected: True
But was: False
]]></message>
<stack-trace><![CDATA[at Editor.EditorModeTest+<FailedUnityTest>d__5.MoveNext () [0x0002e] in /github/workspace/unity-project/Assets/Editor/EditorModeTest.cs:40
at UnityEngine.TestTools.TestEnumerator+<Execute>d__6.MoveNext () [0x00038] in /github/workspace/unity-project/Library/PackageCache/com.unity.test-framework@1.1.19/UnityEngine.TestRunner/NUnitExtensions/Attributes/TestEnumerator.cs:36
]]></stack-trace>
</failure>
</test-case>
<test-case id="1015" name="IgnoredTest" fullname="Editor.EditorModeTest.IgnoredTest" methodname="IgnoredTest" classname="Editor.EditorModeTest" runstate="Ignored" seed="1319288303" result="Skipped" label="Ignored" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.000218" asserts="0">
<properties>
<property name="_SKIPREASON" value="ignore" />
</properties>
<reason>
<message><![CDATA[ignore]]></message>
</reason>
</test-case>
<test-case id="1018" name="IgnoredUnityTest" fullname="Editor.EditorModeTest.IgnoredUnityTest" methodname="IgnoredUnityTest" classname="Editor.EditorModeTest" runstate="Ignored" seed="2034877647" result="Skipped" label="Ignored" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.000004" asserts="0">
<properties>
<property name="_JOINTYPE" value="UnityCombinatorial" />
<property name="_SKIPREASON" value="ignore" />
</properties>
<reason>
<message><![CDATA[ignore]]></message>
</reason>
</test-case>
<test-case id="1014" name="PassedTest" fullname="Editor.EditorModeTest.PassedTest" methodname="PassedTest" classname="Editor.EditorModeTest" runstate="Runnable" seed="387558551" result="Passed" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.000366" asserts="0">
<properties />
</test-case>
<test-case id="1017" name="PassedUnityTest" fullname="Editor.EditorModeTest.PassedUnityTest" methodname="PassedUnityTest" classname="Editor.EditorModeTest" runstate="Runnable" seed="1069930397" result="Passed" start-time="2021-01-19 20:51:34Z" end-time="2021-01-19 20:51:34Z" duration="0.007903" asserts="0">
<properties>
<property name="_JOINTYPE" value="UnityCombinatorial" />
</properties>
</test-case>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-run>

View File

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<test-run id="2" testcasecount="8" result="Failed(Child)" total="8" passed="2" failed="4" inconclusive="0" skipped="2" asserts="0" engine-version="3.5.0.0" clr-version="4.0.30319.42000" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.1055695">
<test-suite type="TestSuite" id="1000" name="sample-project" fullname="sample-project" runstate="Runnable" testcasecount="8" result="Failed" site="Child" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.105570" total="8" passed="2" failed="4" inconclusive="0" skipped="2" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="Assembly" id="1012" name="Assembly-CSharp.dll" fullname="/github/workspace/unity-project/Library/ScriptAssemblies/Assembly-CSharp.dll" runstate="Runnable" testcasecount="8" result="Failed" site="Child" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.088008" total="8" passed="2" failed="4" inconclusive="0" skipped="2" asserts="0">
<properties>
<property name="_PID" value="474" />
<property name="_APPDOMAIN" value="Unity Child Domain" />
<property name="platform" value="PlayMode" />
</properties>
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestSuite" id="1013" name="Tests" fullname="Tests" runstate="Runnable" testcasecount="8" result="Failed" site="Child" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.084864" total="8" passed="2" failed="4" inconclusive="0" skipped="2" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-suite type="TestFixture" id="1001" name="PlayModeTest" fullname="Tests.PlayModeTest" classname="Tests.PlayModeTest" runstate="Runnable" testcasecount="6" result="Failed" site="Child" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.074407" total="6" passed="2" failed="2" inconclusive="0" skipped="2" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-case id="1004" name="FailedTest" fullname="Tests.PlayModeTest.FailedTest" methodname="FailedTest" classname="Tests.PlayModeTest" runstate="Runnable" seed="1067965392" result="Failed" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.034377" asserts="0">
<properties />
<failure>
<message><![CDATA[ Expected: True
But was: False
]]></message>
<stack-trace><![CDATA[at Tests.PlayModeTest.FailedTest () [0x00000] in /github/workspace/unity-project/Assets/Tests/PlayModeTest.cs:20
]]></stack-trace>
</failure>
</test-case>
<test-case id="1007" name="FailedUnityTest" fullname="Tests.PlayModeTest.FailedUnityTest" methodname="FailedUnityTest" classname="Tests.PlayModeTest" runstate="Runnable" seed="318345342" result="Failed" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.009524" asserts="0">
<properties>
<property name="_JOINTYPE" value="UnityCombinatorial" />
</properties>
<failure>
<message><![CDATA[ Expected: True
But was: False
]]></message>
<stack-trace><![CDATA[at Tests.PlayModeTest+<FailedUnityTest>d__5.MoveNext () [0x0002e] in /github/workspace/unity-project/Assets/Tests/PlayModeTest.cs:39
at UnityEngine.TestTools.TestEnumerator+<Execute>d__6.MoveNext () [0x00038] in /github/workspace/unity-project/Library/PackageCache/com.unity.test-framework@1.1.19/UnityEngine.TestRunner/NUnitExtensions/Attributes/TestEnumerator.cs:36
]]></stack-trace>
</failure>
</test-case>
<test-case id="1003" name="IgnoredTest" fullname="Tests.PlayModeTest.IgnoredTest" methodname="IgnoredTest" classname="Tests.PlayModeTest" runstate="Ignored" seed="1914466070" result="Skipped" label="Ignored" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.000211" asserts="0">
<properties>
<property name="_SKIPREASON" value="ignore" />
</properties>
<reason>
<message><![CDATA[ignore]]></message>
</reason>
</test-case>
<test-case id="1006" name="IgnoredUnityTest" fullname="Tests.PlayModeTest.IgnoredUnityTest" methodname="IgnoredUnityTest" classname="Tests.PlayModeTest" runstate="Ignored" seed="475291067" result="Skipped" label="Ignored" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.000004" asserts="0">
<properties>
<property name="_JOINTYPE" value="UnityCombinatorial" />
<property name="_SKIPREASON" value="ignore" />
</properties>
<reason>
<message><![CDATA[ignore]]></message>
</reason>
</test-case>
<test-case id="1002" name="PassedTest" fullname="Tests.PlayModeTest.PassedTest" methodname="PassedTest" classname="Tests.PlayModeTest" runstate="Runnable" seed="635988114" result="Passed" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.000400" asserts="0">
<properties />
</test-case>
<test-case id="1005" name="PassedUnityTest" fullname="Tests.PlayModeTest.PassedUnityTest" methodname="PassedUnityTest" classname="Tests.PlayModeTest" runstate="Runnable" seed="881217608" result="Passed" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.000736" asserts="0">
<properties>
<property name="_JOINTYPE" value="UnityCombinatorial" />
</properties>
</test-case>
</test-suite>
<test-suite type="TestFixture" id="1008" name="SetupFailedTest" fullname="Tests.SetupFailedTest" classname="Tests.SetupFailedTest" runstate="Runnable" testcasecount="1" result="Failed" site="Child" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.004318" total="1" passed="0" failed="1" inconclusive="0" skipped="0" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-case id="1009" name="PassedTest" fullname="Tests.SetupFailedTest.PassedTest" methodname="PassedTest" classname="Tests.SetupFailedTest" runstate="Runnable" seed="1423699315" result="Failed" label="Error" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.003206" asserts="0">
<properties />
<failure>
<message><![CDATA[SetUp : System.NullReferenceException : Object reference not set to an instance of an object]]></message>
<stack-trace><![CDATA[--SetUp
at Tests.SetupFailedTest.SetUp () [0x00000] in /github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs:10
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <9577ac7a62ef43179789031239ba8798>:0 ]]></stack-trace>
</failure>
</test-case>
</test-suite>
<test-suite type="TestFixture" id="1010" name="TearDownFailedTest" fullname="Tests.TearDownFailedTest" classname="Tests.TearDownFailedTest" runstate="Runnable" testcasecount="1" result="Failed" site="Child" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.001857" total="1" passed="0" failed="1" inconclusive="0" skipped="0" asserts="0">
<properties />
<failure>
<message><![CDATA[One or more child tests had errors]]></message>
</failure>
<test-case id="1011" name="PassedTest" fullname="Tests.TearDownFailedTest.PassedTest" methodname="PassedTest" classname="Tests.TearDownFailedTest" runstate="Runnable" seed="1384928637" result="Failed" label="Error" start-time="2021-01-19 20:51:44Z" end-time="2021-01-19 20:51:44Z" duration="0.000755" asserts="0">
<properties />
<failure>
<message><![CDATA[TearDown : System.NullReferenceException : Object reference not set to an instance of an object]]></message>
<stack-trace><![CDATA[--TearDown
at Tests.TearDownFailedTest.TearDown () [0x00000] in /github/workspace/unity-project/Assets/Tests/TearDownFailedTest.cs:10
at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00032] in <9577ac7a62ef43179789031239ba8798>:0 ]]></stack-trace>
</failure>
</test-case>
</test-suite>
</test-suite>
</test-suite>
</test-suite>
</test-run>

17
babel.config.js Normal file
View File

@@ -0,0 +1,17 @@
const esModules = ['lodash-es'].join('|');
module.exports = {
ignore: [`/node_modules/(?!${esModules})`],
presets: [
[
'@babel/preset-env',
{
targets: {
node: true,
},
},
],
'@babel/typescript',
],
plugins: ['@babel/plugin-proposal-class-properties', '@babel/proposal-object-rest-spread'],
};

8
jest.config.js Normal file
View File

@@ -0,0 +1,8 @@
const esModules = ['lodash-es'].join('|');
module.exports = {
testEnvironment: 'node',
moduleFileExtensions: ['ts', 'js', 'jsx', 'json', 'vue'],
transform: { '^.+\\.(ts|js|jsx)?$': 'babel-jest' },
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
};

1
media/Discord-Logo.svg Normal file
View File

@@ -0,0 +1 @@
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 272.1"><style>.st0{fill:#7289DA;}</style><path class="st0" d="M142.8 120.1c-5.7 0-10.2 4.9-10.2 11s4.6 11 10.2 11c5.7 0 10.2-4.9 10.2-11s-4.6-11-10.2-11zM106.3 120.1c-5.7 0-10.2 4.9-10.2 11s4.6 11 10.2 11c5.7 0 10.2-4.9 10.2-11 .1-6.1-4.5-11-10.2-11z"/><path class="st0" d="M191.4 36.9h-134c-11.3 0-20.5 9.2-20.5 20.5v134c0 11.3 9.2 20.5 20.5 20.5h113.4l-5.3-18.3 12.8 11.8 12.1 11.1 21.6 18.7V57.4c-.1-11.3-9.3-20.5-20.6-20.5zm-38.6 129.5s-3.6-4.3-6.6-8c13.1-3.7 18.1-11.8 18.1-11.8-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.4-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.6-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.2-1.8-1-2.8-1.7-2.8-1.7s4.8 7.9 17.5 11.7c-3 3.8-6.7 8.2-6.7 8.2-22.1-.7-30.5-15.1-30.5-15.1 0-31.9 14.4-57.8 14.4-57.8 14.4-10.7 28-10.4 28-10.4l1 1.2c-18 5.1-26.2 13-26.2 13s2.2-1.2 5.9-2.8c10.7-4.7 19.2-5.9 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.5 0 0-7.9-7.5-24.9-12.6l1.4-1.6s13.7-.3 28 10.4c0 0 14.4 25.9 14.4 57.8 0-.1-8.4 14.3-30.5 15zM303.8 79.7h-33.2V117l22.1 19.9v-36.2h11.8c7.5 0 11.2 3.6 11.2 9.4v27.7c0 5.8-3.5 9.7-11.2 9.7h-34v21.1h33.2c17.8.1 34.5-8.8 34.5-29.2v-29.8c.1-20.8-16.6-29.9-34.4-29.9zm174 59.7v-30.6c0-11 19.8-13.5 25.8-2.5l18.3-7.4c-7.2-15.8-20.3-20.4-31.2-20.4-17.8 0-35.4 10.3-35.4 30.3v30.6c0 20.2 17.6 30.3 35 30.3 11.2 0 24.6-5.5 32-19.9l-19.6-9c-4.8 12.3-24.9 9.3-24.9-1.4zM417.3 113c-6.9-1.5-11.5-4-11.8-8.3.4-10.3 16.3-10.7 25.6-.8l14.7-11.3c-9.2-11.2-19.6-14.2-30.3-14.2-16.3 0-32.1 9.2-32.1 26.6 0 16.9 13 26 27.3 28.2 7.3 1 15.4 3.9 15.2 8.9-.6 9.5-20.2 9-29.1-1.8l-14.2 13.3c8.3 10.7 19.6 16.1 30.2 16.1 16.3 0 34.4-9.4 35.1-26.6 1-21.7-14.8-27.2-30.6-30.1zm-67 55.5h22.4V79.7h-22.4v88.8zM728 79.7h-33.2V117l22.1 19.9v-36.2h11.8c7.5 0 11.2 3.6 11.2 9.4v27.7c0 5.8-3.5 9.7-11.2 9.7h-34v21.1H728c17.8.1 34.5-8.8 34.5-29.2v-29.8c0-20.8-16.7-29.9-34.5-29.9zm-162.9-1.2c-18.4 0-36.7 10-36.7 30.5v30.3c0 20.3 18.4 30.5 36.9 30.5 18.4 0 36.7-10.2 36.7-30.5V109c0-20.4-18.5-30.5-36.9-30.5zm14.4 60.8c0 6.4-7.2 9.7-14.3 9.7-7.2 0-14.4-3.1-14.4-9.7V109c0-6.5 7-10 14-10 7.3 0 14.7 3.1 14.7 10v30.3zM682.4 109c-.5-20.8-14.7-29.2-33-29.2h-35.5v88.8h22.7v-28.2h4l20.6 28.2h28L665 138.1c10.7-3.4 17.4-12.7 17.4-29.1zm-32.6 12h-13.2v-20.3h13.2c14.1 0 14.1 20.3 0 20.3z"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

67
package.json Normal file
View File

@@ -0,0 +1,67 @@
{
"name": "unity-test-runner",
"version": "0.0.0",
"description": "Run tests for any Unity project.",
"main": "action/index.js",
"repository": "git@github.com:webbertakken/unity-test-runner.git",
"author": "Webber <webber@takken.io>",
"license": "MIT",
"scripts": {
"prebuild": "yarn",
"build": "ncc build src --out action --minify",
"lint": "prettier --check \"src/**/*.js\" && eslint src",
"test": "jest"
},
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/exec": "1.0.4",
"@actions/github": "^4.0.0",
"@octokit/types": "6.10.1",
"handlebars": "4.7.7",
"xml-js": "1.6.11"
},
"devDependencies": {
"@babel/cli": "7.12.10",
"@babel/core": "7.12.10",
"@babel/plugin-proposal-class-properties": "^7.12.13",
"@babel/plugin-proposal-object-rest-spread": "^7.12.13",
"@babel/preset-env": "7.12.11",
"@babel/preset-typescript": "^7.12.17",
"@zeit/ncc": "0.22.3",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "10.1.0",
"babel-jest": "^26.6.3",
"eslint": "7.17.0",
"eslint-config-airbnb": "18.2.1",
"eslint-config-prettier": "7.1.0",
"eslint-plugin-flowtype": "5.2.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-prettier": "3.3.1",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-unicorn": "25.0.1",
"husky": "4.3.7",
"jest": "26.6.3",
"lint-staged": "10.5.3",
"lodash-es": "4.17.20",
"prettier": "2.2.1",
"typescript": "^4.1.5"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged && yarn build && git add action/index.js"
}
},
"lint-staged": {
"*.{js,jsx}": [
"prettier --write",
"eslint",
"git add",
"jest --findRelatedTests"
],
"*.{json,md,yaml,yml}": [
"prettier --write",
"git add"
]
}
}

51
src/index.js Normal file
View File

@@ -0,0 +1,51 @@
import * as core from '@actions/core';
import { Action, Docker, Input, ImageTag, Output, ResultsCheck } from './model';
async function action() {
Action.checkCompatibility();
const { dockerfile, workspace, actionFolder } = Action;
const {
unityVersion,
customImage,
projectPath,
testMode,
artifactsPath,
useHostNetwork,
customParameters,
githubToken,
checkName,
} = Input.getFromUser();
const baseImage = ImageTag.createForBase({ version: unityVersion, customImage });
try {
// Build docker image
const actionImage = await Docker.build({ path: actionFolder, dockerfile, baseImage });
// Run docker image
await Docker.run(actionImage, {
workspace,
unityVersion,
projectPath,
testMode,
artifactsPath,
useHostNetwork,
customParameters,
githubToken,
});
} finally {
// Set output
await Output.setArtifactsPath(artifactsPath);
}
if (githubToken) {
const failedTestCount = await ResultsCheck.createCheck(artifactsPath, githubToken, checkName);
if (failedTestCount >= 1) {
core.setFailed(`Test(s) Failed! Check '${checkName}' for details.`);
}
}
}
action().catch(error => {
core.setFailed(error.message);
});

48
src/model/action.js Normal file
View File

@@ -0,0 +1,48 @@
import path from 'path';
class Action {
static get supportedPlatforms() {
return ['linux'];
}
static get isRunningLocally() {
return process.env.RUNNER_WORKSPACE === undefined;
}
static get isRunningFromSource() {
return path.basename(__dirname) === 'model';
}
static get name() {
return 'unity-test-runner';
}
static get rootFolder() {
if (Action.isRunningFromSource) {
return path.dirname(path.dirname(path.dirname(__filename)));
}
return path.dirname(path.dirname(__filename));
}
static get actionFolder() {
return `${Action.rootFolder}/action`;
}
static get dockerfile() {
return `${Action.actionFolder}/Dockerfile`;
}
static get workspace() {
return process.env.GITHUB_WORKSPACE;
}
static checkCompatibility() {
const currentPlatform = process.platform;
if (!Action.supportedPlatforms.includes(currentPlatform)) {
throw new Error(`Currently ${currentPlatform}-platform is not supported`);
}
}
}
export default Action;

36
src/model/action.test.js Normal file
View File

@@ -0,0 +1,36 @@
import path from 'path';
import fs from 'fs';
import Action from './action';
describe('Action', () => {
describe('compatibility check', () => {
it('throws for anything other than linux', () => {
if (process.platform !== 'linux') {
expect(() => Action.checkCompatibility()).toThrow();
} else {
expect(() => Action.checkCompatibility()).not.toThrow();
}
});
});
it('returns the root folder of the action', () => {
const { rootFolder, name } = Action;
expect(path.basename(rootFolder)).toStrictEqual(name);
expect(fs.existsSync(rootFolder)).toStrictEqual(true);
});
it('returns the action folder', () => {
const { actionFolder } = Action;
expect(path.basename(actionFolder)).toStrictEqual('action');
expect(fs.existsSync(actionFolder)).toStrictEqual(true);
});
it('returns the docker file', () => {
const { dockerfile } = Action;
expect(path.basename(dockerfile)).toStrictEqual('Dockerfile');
expect(fs.existsSync(dockerfile)).toStrictEqual(true);
});
});

73
src/model/docker.js Normal file
View File

@@ -0,0 +1,73 @@
import { exec } from '@actions/exec';
import ImageTag from './image-tag';
class Docker {
static async build(buildParameters, silent = false) {
const { path, dockerfile, baseImage } = buildParameters;
const { version } = baseImage;
const tag = ImageTag.createForAction(version);
const command = `docker build ${path} \
--file ${dockerfile} \
--build-arg IMAGE=${baseImage} \
--tag ${tag}`;
await exec(command, undefined, { silent });
return tag;
}
static async run(image, parameters, silent = false) {
const {
unityVersion,
workspace,
projectPath,
testMode,
artifactsPath,
useHostNetwork,
customParameters,
githubToken,
} = parameters;
const command = `docker run \
--workdir /github/workspace \
--rm \
--env UNITY_LICENSE \
--env UNITY_LICENSE_FILE \
--env UNITY_EMAIL \
--env UNITY_PASSWORD \
--env UNITY_SERIAL \
--env UNITY_VERSION="${unityVersion}" \
--env PROJECT_PATH="${projectPath}" \
--env TEST_MODE="${testMode}" \
--env ARTIFACTS_PATH="${artifactsPath}" \
--env CUSTOM_PARAMETERS="${customParameters}" \
--env HOME=/github/home \
--env GITHUB_REF \
--env GITHUB_SHA \
--env GITHUB_REPOSITORY \
--env GITHUB_ACTOR \
--env GITHUB_WORKFLOW \
--env GITHUB_HEAD_REF \
--env GITHUB_BASE_REF \
--env GITHUB_EVENT_NAME \
--env GITHUB_WORKSPACE=/github/workspace \
--env GITHUB_ACTION \
--env GITHUB_EVENT_PATH \
--env RUNNER_OS \
--env RUNNER_TOOL_CACHE \
--env RUNNER_TEMP \
--env RUNNER_WORKSPACE \
--volume "/var/run/docker.sock":"/var/run/docker.sock" \
--volume "/home/runner/work/_temp/_github_home":"/github/home" \
--volume "/home/runner/work/_temp/_github_workflow":"/github/workflow" \
--volume "${workspace}":"/github/workspace" \
${useHostNetwork ? '--net=host' : ''} \
${githubToken ? '--env USE_EXIT_CODE=false' : '--env USE_EXIT_CODE=true'} \
${image}`;
await exec(command, undefined, { silent });
}
}
export default Docker;

25
src/model/docker.test.js Normal file
View File

@@ -0,0 +1,25 @@
import Action from './action';
import Docker from './docker';
import ImageTag from './image-tag';
describe('Docker', () => {
it('builds', async () => {
const path = Action.actionFolder;
const dockerfile = `${path}/Dockerfile`;
const image = new ImageTag({
repository: '',
name: 'alpine',
version: '3',
});
const baseImage = {
toString: () => image.toString().slice(0, image.toString().lastIndexOf('-base-0')),
version: image.version,
};
const tag = await Docker.build({ path, dockerfile, baseImage }, true);
expect(tag).toBeInstanceOf(ImageTag);
expect(tag.toString()).toStrictEqual('unity-action:3-base-0');
}, 240000);
});

45
src/model/image-tag.js Normal file
View File

@@ -0,0 +1,45 @@
import { trimStart } from 'lodash-es';
class ImageTag {
static createForBase({ version, customImage }) {
const repository = 'unityci';
const name = 'editor';
return new this({ repository, name, version, customImage });
}
static createForAction(version) {
const repository = '';
const name = 'unity-action';
return new this({ repository, name, version });
}
constructor({ repository = '', name, version, customImage }) {
if (!ImageTag.versionPattern.test(version)) {
throw new Error(`Invalid version "${version}".`);
}
Object.assign(this, { repository, name, version, customImage });
}
static get versionPattern() {
return /^20\d{2}\.\d\.\w{3,4}|3$/;
}
get tag() {
return this.version;
}
get image() {
return trimStart(`${this.repository}/${this.name}`, '/');
}
toString() {
if (this.customImage && this.customImage !== '') {
return this.customImage;
}
return `${this.image}:${this.tag}-base-0`;
}
}
export default ImageTag;

View File

@@ -0,0 +1,47 @@
import ImageTag from './image-tag';
describe('ImageTag', () => {
describe('constructor', () => {
const some = {
name: 'someName',
version: '2020.0.00f0',
};
it('can be called', () => {
expect(() => new ImageTag(some)).not.toThrow();
});
it('accepts parameters and sets the right properties', () => {
const image = new ImageTag(some);
expect(image.repository).toStrictEqual('');
expect(image.name).toStrictEqual(some.name);
expect(image.version).toStrictEqual(some.version);
});
test.each(['2000.0.0f0', '2011.1.11f1'])('accepts %p version format', version => {
expect(() => new ImageTag({ version })).not.toThrow();
});
test.each(['some version', '', 1, undefined])('throws for incorrect versions %p', version => {
expect(() => new ImageTag({ version })).toThrow();
});
});
describe('toString', () => {
it('returns the correct version', () => {
const image = ImageTag.createForBase({ version: '2099.1.1111' });
expect(image.toString()).toStrictEqual(`unityci/editor:2099.1.1111-base-0`);
});
it('returns customImage if given', () => {
const image = ImageTag.createForBase({
version: '2099.1.1111',
customImage: 'unityci/editor:2099.1.1111-base-0',
});
expect(image.toString()).toStrictEqual(image.customImage);
});
});
});

8
src/model/index.js Normal file
View File

@@ -0,0 +1,8 @@
import Action from './action';
import Docker from './docker';
import Input from './input';
import ImageTag from './image-tag';
import Output from './output';
import ResultsCheck from './results-check';
export { Action, Docker, Input, ImageTag, Output, ResultsCheck };

10
src/model/index.test.js Normal file
View File

@@ -0,0 +1,10 @@
import * as Index from '.';
describe('Index', () => {
test.each(['Action', 'Docker', 'ImageTag', 'Input', 'Output', 'ResultsCheck'])(
'exports %s',
exportedModule => {
expect(typeof Index[exportedModule]).toStrictEqual('function');
},
);
});

67
src/model/input.js Normal file
View File

@@ -0,0 +1,67 @@
import { getInput } from '@actions/core';
import { includes } from 'lodash-es';
import UnityVersionParser from './unity-version-parser';
class Input {
static get testModes() {
return ['all', 'playmode', 'editmode'];
}
static isValidFolderName(folderName) {
const validFolderName = new RegExp(/^(\.|\.\/)?(\.?\w+([_-]?\w+)*\/?)*$/);
return validFolderName.test(folderName);
}
static getFromUser() {
// Input variables specified in workflow using "with" prop.
const rawUnityVersion = getInput('unityVersion') || 'auto';
const customImage = getInput('customImage') || '';
const testMode = (getInput('testMode') || 'all').toLowerCase();
const rawProjectPath = getInput('projectPath') || '.';
const rawArtifactsPath = getInput('artifactsPath') || 'artifacts';
const rawUseHostNetwork = getInput('useHostNetwork') || 'false';
const customParameters = getInput('customParameters') || '';
const githubToken = getInput('githubToken') || '';
const checkName = getInput('checkName') || 'Test Results';
// Validate input
if (!includes(this.testModes, testMode)) {
throw new Error(`Invalid testMode ${testMode}`);
}
if (!this.isValidFolderName(rawArtifactsPath)) {
throw new Error(`Invalid artifactsPath "${rawArtifactsPath}"`);
}
if (!this.isValidFolderName(rawProjectPath)) {
throw new Error(`Invalid projectPath "${rawProjectPath}"`);
}
if (rawUseHostNetwork !== 'true' && rawUseHostNetwork !== 'false') {
throw new Error(`Invalid useHostNetwork "${rawUseHostNetwork}"`);
}
// Sanitise input
const projectPath = rawProjectPath.replace(/\/$/, '');
const artifactsPath = rawArtifactsPath.replace(/\/$/, '');
const useHostNetwork = rawUseHostNetwork === 'true';
const unityVersion =
rawUnityVersion === 'auto' ? UnityVersionParser.read(projectPath) : rawUnityVersion;
// Return sanitised input
return {
unityVersion,
customImage,
projectPath,
testMode,
artifactsPath,
useHostNetwork,
customParameters,
githubToken,
checkName,
};
}
}
export default Input;

34
src/model/input.test.js Normal file
View File

@@ -0,0 +1,34 @@
import Input from './input';
describe('Input', () => {
describe('getFromUser', () => {
it('does not throw', () => {
expect(() => Input.getFromUser()).not.toThrow();
});
it('returns an object', () => {
expect(typeof Input.getFromUser()).toStrictEqual('object');
});
});
describe('isValidFolderName', () => {
test.each([
'.',
'./',
'folder',
'trailing/',
'.hidden',
'.hidden/sub',
'.hidden/trailing/',
'./.hidden-sub',
'hyphen-folder',
'under_score',
])('returns true for %s', folderName => {
expect(Input.isValidFolderName(folderName)).toStrictEqual(true);
});
test.each(['..', '../'])('returns false for %s', folderName => {
expect(Input.isValidFolderName(folderName)).toStrictEqual(false);
});
});
});

9
src/model/output.js Normal file
View File

@@ -0,0 +1,9 @@
const core = require('@actions/core');
class Output {
static async setArtifactsPath(artifactsPath) {
await core.setOutput('artifactsPath', artifactsPath);
}
}
export default Output;

9
src/model/output.test.js Normal file
View File

@@ -0,0 +1,9 @@
import Output from './output';
describe('Output', () => {
describe('setArtifactsPath', () => {
it('does not throw', async () => {
await expect(Output.setArtifactsPath()).resolves.not.toThrow();
});
});
});

120
src/model/results-check.js Normal file
View File

@@ -0,0 +1,120 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import * as fs from 'fs';
import path from 'path';
import Handlebars from 'handlebars';
import ResultsParser from './results-parser';
import { RunMeta } from './ts/results-meta.ts';
class ResultsCheck {
static async createCheck(artifactsPath, githubToken, checkName) {
// Validate input
if (!fs.existsSync(artifactsPath) || !githubToken || !checkName) {
throw new Error(
`Missing input! {"artifactsPath": "${artifactsPath}", "githubToken": "${githubToken}, "checkName": "${checkName}"`,
);
}
// Parse all results files
const runs = [];
const files = fs.readdirSync(artifactsPath);
await Promise.all(
files.map(async filepath => {
if (!filepath.endsWith('.xml')) return;
core.info(`Processing file ${filepath}...`);
const fileData = await ResultsParser.parseResults(path.join(artifactsPath, filepath));
core.info(fileData.summary);
runs.push(fileData);
}),
);
// Combine all results into a single run summary
const runSummary = new RunMeta(checkName);
runs.forEach(run => {
runSummary.total += run.total;
runSummary.passed += run.passed;
runSummary.skipped += run.skipped;
runSummary.failed += run.failed;
runSummary.duration += run.duration;
run.suites.forEach(suite => {
runSummary.addTests(suite.tests);
});
});
// Log
core.info('=================');
core.info('Analyze result:');
core.info(runSummary.summary);
// Format output
const title = runSummary.summary;
const summary = await ResultsCheck.renderSummary(runs);
core.debug(`Summary view: ${summary}`);
const details = await ResultsCheck.renderDetails(runs);
core.debug(`Details view: ${details}`);
const rawAnnotations = runSummary.extractAnnotations();
core.debug(`Raw annotations: ${rawAnnotations}`);
const annotations = rawAnnotations.map(rawAnnotation => {
const annotation = rawAnnotation;
annotation.path = rawAnnotation.path.replace('/github/workspace/', '');
return annotation;
});
core.debug(`Annotations: ${annotations}`);
const output = {
title,
summary,
text: details,
annotations: annotations.slice(0, 50),
};
// Call GitHub API
await ResultsCheck.requestGitHubCheck(githubToken, checkName, output);
return runSummary.failed;
}
static async requestGitHubCheck(githubToken, checkName, output) {
const pullRequest = github.context.payload.pull_request;
const headSha = (pullRequest && pullRequest.head.sha) || github.context.sha;
core.info(`Posting results for ${headSha}`);
const createCheckRequest = {
...github.context.repo,
name: checkName,
head_sha: headSha,
status: 'completed',
conclusion: 'neutral',
output,
};
const octokit = github.getOctokit(githubToken);
await octokit.checks.create(createCheckRequest);
}
static async renderSummary(runMetas) {
return ResultsCheck.render(`${__dirname}/../views/results-check-summary.hbs`, runMetas);
}
static async renderDetails(runMetas) {
return ResultsCheck.render(`${__dirname}/../views/results-check-details.hbs`, runMetas);
}
static async render(viewPath, runMetas) {
Handlebars.registerHelper('indent', toIndent =>
toIndent
.split('\n')
.map(s => ` ${s.replace('/github/workspace/', '')}`)
.join('\n'),
);
const source = await fs.promises.readFile(viewPath, 'utf8');
const template = Handlebars.compile(source);
return template(
{ runs: runMetas },
{
allowProtoMethodsByDefault: true,
allowProtoPropertiesByDefault: true,
},
);
}
}
export default ResultsCheck;

View File

@@ -0,0 +1,9 @@
import ResultsCheck from './results-check';
describe('ResultsCheck', () => {
describe('createCheck', () => {
it('throws for missing input', () => {
expect(() => ResultsCheck.createCheck('', '', '')).rejects.toEqual(Error);
});
});
});

123
src/model/results-parser.js Normal file
View File

@@ -0,0 +1,123 @@
import * as core from '@actions/core';
import * as xmljs from 'xml-js';
import * as fs from 'fs';
import path from 'path';
import { RunMeta, TestMeta } from './ts/results-meta.ts';
class ResultsParser {
static async parseResults(filepath) {
if (!fs.existsSync(filepath)) {
throw new Error(`Missing file! {"filepath": "${filepath}"}`);
}
core.info(`Trying to open ${filepath}`);
const file = await fs.promises.readFile(filepath, 'utf8');
const results = xmljs.xml2js(file, { compact: true });
core.info(`File ${filepath} parsed...`);
return ResultsParser.convertResults(path.basename(filepath), results);
}
static convertResults(filename, filedata) {
core.info(`Start analyzing results: ${filename}`);
const run = filedata['test-run'];
const runMeta = new RunMeta(filename);
const tests = ResultsParser.convertSuite(run['test-suite']);
core.debug(tests);
runMeta.total = Number(run._attributes.total);
runMeta.failed = Number(run._attributes.failed);
runMeta.skipped = Number(run._attributes.skipped);
runMeta.passed = Number(run._attributes.passed);
runMeta.duration = Number(run._attributes.duration);
runMeta.addTests(tests);
return runMeta;
}
static convertSuite(suites) {
if (Array.isArray(suites)) {
const innerResult = [];
suites.forEach(suite => {
innerResult.push(...ResultsParser.convertSuite(suite));
});
return innerResult;
}
const result = [];
const innerSuite = suites['test-suite'];
if (innerSuite) {
result.push(...ResultsParser.convertSuite(innerSuite));
}
const tests = suites['test-case'];
if (tests) {
result.push(...ResultsParser.convertTests(suites._attributes.fullname, tests));
}
return result;
}
static convertTests(suite, tests) {
if (Array.isArray(tests)) {
const result = [];
tests.forEach(test => {
result.push(ResultsParser.convertTestCase(suite, test));
});
return result;
}
return [ResultsParser.convertTestCase(suite, tests)];
}
static convertTestCase(suite, testCase) {
const { _attributes, failure } = testCase;
const { name, fullname, result, duration } = _attributes;
const testMeta = new TestMeta(suite, name);
testMeta.result = result;
testMeta.duration = Number(duration);
if (!failure) {
core.debug(`Skip test ${fullname} without failure data`);
return testMeta;
}
core.debug(`Convert data for test ${fullname}`);
if (failure['stack-trace'] === undefined) {
core.warning(`No stack trace for test case: ${fullname}`);
return testMeta;
}
const trace = failure['stack-trace']._cdata;
const point = ResultsParser.findAnnotationPoint(trace);
if (!point.path || !point.line) {
core.warning(`Not able to find annotation point for failed test! Test trace: ${trace}`);
return testMeta;
}
testMeta.annotation = {
path: point.path,
start_line: point.line,
end_line: point.line,
annotation_level: 'failure',
title: fullname,
message: failure.message._cdata,
raw_details: trace,
};
core.info(
`- ${testMeta.annotation.path}:${testMeta.annotation.start_line} - ${testMeta.annotation.title}`,
);
return testMeta;
}
static findAnnotationPoint(trace) {
const match = trace.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/);
return {
path: match ? match.groups.path : '',
line: match ? Number(match.groups.line) : 0,
};
}
}
export default ResultsParser;

View File

@@ -0,0 +1,205 @@
import * as xmljs from 'xml-js';
import * as fs from 'fs';
import ResultsParser from './results-parser';
describe('ResultsParser', () => {
describe('parseResults', () => {
it('throws for missing file', () => {
expect(() => ResultsParser.parseResults('')).rejects.toEqual(Error);
});
it('parses editmode-results.xml', () => {
expect(() => ResultsParser.parseResults('./artifacts/editmode-results.xml')).not.toThrow();
});
it('parses playmode-results.xml', () => {
expect(() => ResultsParser.parseResults('./artifacts/playmode-results.xml')).not.toThrow();
});
});
describe('convertResults', () => {
it('converts editmode-results.xml', () => {
const file = fs.readFileSync('./artifacts/editmode-results.xml');
const filedata = xmljs.xml2js(file, { compact: true });
const result = ResultsParser.convertResults('editmode-results.xml', filedata);
expect(result.suites.length).toEqual(1);
});
it('converts playmode-results.xml', () => {
const file = fs.readFileSync('./artifacts/playmode-results.xml');
const filedata = xmljs.xml2js(file, { compact: true });
const result = ResultsParser.convertResults('playmode-results.xml', filedata);
expect(result.suites.length).toEqual(3);
});
});
describe('convertSuite', () => {
test('convert single', () => {
const targetSuite = {
_attributes: {
fullname: 'Suite Full Name',
},
'test-case': [{ _attributes: { name: 'testA' } }, { _attributes: { name: 'testB' } }],
'test-suite': [
{
_attributes: {
fullname: 'Inner Suite Full Name',
},
'test-case': { _attributes: { name: 'testC' } },
'test-suite': [],
},
],
};
const result = ResultsParser.convertSuite(targetSuite);
expect(result).toMatchObject([
{
annotation: undefined,
duration: Number.NaN,
result: undefined,
suite: 'Inner Suite Full Name',
title: 'testC',
},
{
annotation: undefined,
duration: Number.NaN,
result: undefined,
suite: 'Suite Full Name',
title: 'testA',
},
{
annotation: undefined,
duration: Number.NaN,
result: undefined,
suite: 'Suite Full Name',
title: 'testB',
},
]);
});
});
describe('convertTests', () => {
test('convert array', () => {
const testA = { _attributes: { name: 'testA' } };
const testB = { _attributes: { name: 'testB' } };
const testResult = [testA, testB];
const result = ResultsParser.convertTests('Test Suite', testResult);
expect(result).toMatchObject([
{ suite: 'Test Suite', title: 'testA' },
{ suite: 'Test Suite', title: 'testB' },
]);
});
test('convert single', () => {
const testA = { _attributes: { name: 'testA' } };
const result = ResultsParser.convertTests('Test Suite', testA);
expect(result).toMatchObject([{ suite: 'Test Suite', title: 'testA' }]);
});
});
describe('convertTestCase', () => {
test('not failed', () => {
const result = ResultsParser.convertTestCase('Test Suite', {
_attributes: {
name: 'Test Name',
duration: '3.14',
},
});
expect(result.suite).toBe('Test Suite');
expect(result.title).toBe('Test Name');
expect(result.duration).toBe(3.14);
expect(result.annotation).toBeUndefined();
});
test('no stack trace', () => {
const result = ResultsParser.convertTestCase('Test Suite', {
_attributes: {
name: 'Test Name',
duration: '3.14',
},
failure: {
message: { _cdata: 'Message CDATA' },
},
});
expect(result.suite).toBe('Test Suite');
expect(result.title).toBe('Test Name');
expect(result.duration).toBe(3.14);
expect(result.annotation).toBeUndefined();
});
test('no annotation path', () => {
const result = ResultsParser.convertTestCase('Test Suite', {
_attributes: {
name: 'Test Name',
duration: '3.14',
},
failure: {
message: { _cdata: 'Message CDATA' },
'stack-trace': { _cdata: 'Test CDATA' },
},
});
expect(result.suite).toBe('Test Suite');
expect(result.title).toBe('Test Name');
expect(result.duration).toBe(3.14);
expect(result.annotation).toBeUndefined();
});
test('prepare annotation', () => {
const result = ResultsParser.convertTestCase('Test Suite', {
_attributes: {
name: 'Test Name',
fullname: 'Test Full Name',
duration: '3.14',
},
failure: {
message: { _cdata: 'Message CDATA' },
'stack-trace': {
_cdata:
'at Tests.SetupFailedTest.SetUp () [0x00000] in /github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs:10',
},
},
});
expect(result.suite).toBe('Test Suite');
expect(result.title).toBe('Test Name');
expect(result.duration).toBe(3.14);
expect(result.annotation).toMatchObject({
annotation_level: 'failure',
end_line: 10,
message: 'Message CDATA',
path: '/github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs',
raw_details:
'at Tests.SetupFailedTest.SetUp () [0x00000] in /github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs:10',
start_line: 10,
title: 'Test Full Name',
});
});
});
describe('findAnnotationPoint', () => {
test('keep working if not matching', () => {
const result = ResultsParser.findAnnotationPoint('');
expect(result.path).toBe('');
expect(result.line).toBe(0);
});
test('simple annotation point', () => {
const result = ResultsParser.findAnnotationPoint(`at Tests.PlayModeTest+<FailedUnityTest>d__5.MoveNext () [0x0002e] in /github/workspace/unity-project/Assets/Tests/PlayModeTest.cs:39
at UnityEngine.TestTools.TestEnumerator+<Execute>d__6.MoveNext () [0x00038] in /github/workspace/unity-project/Library/PackageCache/com.unity.test-framework@1.1.19/UnityEngine.TestRunner/NUnitExtensions/Attributes/TestEnumerator.cs:36`);
expect(result.path).toBe('/github/workspace/unity-project/Assets/Tests/PlayModeTest.cs');
expect(result.line).toBe(39);
});
test('setup annotation point', () => {
const result = ResultsParser.findAnnotationPoint(`SetUp
at Tests.SetupFailedTest.SetUp () [0x00000] in /github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs:10`);
expect(result.path).toBe('/github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs');
expect(result.line).toBe(10);
});
});
});

View File

@@ -0,0 +1,118 @@
import { components } from '@octokit/openapi-types/dist-types/generated/types';
export function timeHelper(seconds: number): string {
return `${seconds.toFixed(3)}s`;
}
export abstract class Meta {
title: string;
duration = 0;
constructor(title: string) {
this.title = title;
}
abstract get summary(): string;
abstract get mark(): string;
}
export type Annotation = components['schemas']['check-annotation'];
export class RunMeta extends Meta {
total = 0;
passed = 0;
skipped = 0;
failed = 0;
tests: TestMeta[] = [];
suites: RunMeta[] = [];
extractAnnotations(): Annotation[] {
const result = [] as Annotation[];
for (const suite of this.suites) {
result.push(...suite.extractAnnotations());
}
for (const test of this.tests) {
if (test.annotation !== undefined) {
result.push(test.annotation);
}
}
return result;
}
addTests(testSuite: TestMeta[]): void {
testSuite.forEach(test => {
this.addTest(test);
});
}
addTest(test: TestMeta): void {
if (test.suite === undefined) {
return;
}
if (test.suite === this.title) {
this.total++;
this.duration += test.duration;
this.tests.push(test);
if (test.result === 'Passed') this.passed++;
else if (test.result === 'Failed') this.failed++;
else this.skipped++;
return;
}
let target = this.suites.find(s => s.title === test.suite);
if (target === undefined) {
target = new RunMeta(test.suite);
this.suites.push(target);
}
target.addTest(test);
}
get summary(): string {
const result = this.failed > 0 ? 'Failed' : 'Passed';
const sPart = this.skipped > 0 ? `, skipped: ${this.skipped}` : '';
const fPart = this.failed > 0 ? `, failed: ${this.failed}` : '';
const dPart = ` in ${timeHelper(this.duration)}`;
return `${this.mark} ${this.title} - ${this.passed}/${this.total}${sPart}${fPart} - ${result}${dPart}`;
}
get mark(): string {
if (this.failed > 0) return '❌️';
else if (this.skipped === 0) return '✅';
return '⚠️';
}
}
export class TestMeta extends Meta {
suite: string;
result: string | undefined;
annotation: Annotation | undefined;
constructor(suite: string, title: string) {
super(title);
this.suite = suite;
}
isSkipped(): boolean {
return this.result === 'Skipped';
}
isFailed(): boolean {
return this.result === 'Failed';
}
get summary(): string {
const dPart = this.isSkipped()
? ''
: ` in ${timeHelper(this.duration)}`;
return `${this.mark} **${this.title}** - ${this.result}${dPart}`;
}
get mark(): string {
if (this.isFailed()) return '❌️';
else if (this.isSkipped()) return '⚠️';
return '✅';
}
}

View File

@@ -0,0 +1,58 @@
interface CommonAttributes {
id: string;
result: string;
asserts: string;
'start-time': string;
'end-time': string;
duration: string;
}
interface CommonSuiteAttributes extends CommonAttributes {
total: string;
passed: string;
failed: string;
skipped: string;
}
export interface TestRun {
_attributes: TestRunAttributes;
'test-suite': TestSuite | TestSuite[];
}
export interface TestRunAttributes extends CommonSuiteAttributes {
testcasecount: string;
'engine-version': string;
}
export interface TestSuite {
_attributes: TestSuiteAttributes;
'test-suite': TestSuite | TestSuite[];
'test-case': TestCase | TestCase[];
failure?: FailureMessage;
}
export interface TestSuiteAttributes extends CommonSuiteAttributes {
type: string;
name: string;
fullname: string;
}
export interface TestCase {
_attributes: TestCaseAttributes;
failure?: FailureMessage;
}
export interface TestCaseAttributes extends CommonAttributes {
name: string;
fullname: string;
methodname: string;
classname: string;
runstate: string;
seed: string;
}
export interface FailureMessage {
message: { _cdata: string };
'stack-trace'?: { _cdata: string };
}

View File

@@ -0,0 +1,26 @@
import fs from 'fs';
import path from 'path';
class UnityVersionParser {
static get versionPattern() {
return /20\d{2}\.\d\.\w{3,4}|3/;
}
static parse(projectVersionTxt) {
const matches = projectVersionTxt.match(UnityVersionParser.versionPattern);
if (!matches || matches.length === 0) {
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
}
return matches[0];
}
static read(projectPath) {
const filePath = path.join(projectPath, 'ProjectSettings', 'ProjectVersion.txt');
if (!fs.existsSync(filePath)) {
return 'auto';
}
return UnityVersionParser.parse(fs.readFileSync(filePath, 'utf8'));
}
}
export default UnityVersionParser;

View File

@@ -0,0 +1,25 @@
import UnityVersionParser from './unity-version-parser';
describe('UnityVersionParser', () => {
describe('parse', () => {
it('throws for empty string', () => {
expect(() => UnityVersionParser.parse('')).toThrow(Error);
});
it('parses from ProjectVersion.txt', () => {
const projectVersionContents = `m_EditorVersion: 2019.2.11f1
m_EditorVersionWithRevision: 2019.2.11f1 (5f859a4cfee5)`;
expect(UnityVersionParser.parse(projectVersionContents)).toBe('2019.2.11f1');
});
});
describe('read', () => {
it('does not throw', () => {
expect(() => UnityVersionParser.read('')).not.toThrow();
});
it('reads from unity-project-with-correct-tests', () => {
expect(UnityVersionParser.read('./unity-project-with-correct-tests')).toBe('2019.2.11f1');
});
});
});

View File

@@ -0,0 +1,18 @@
{{#runs}}
<details><summary>{{summary}}</summary>
{{#suites}}
* {{summary}}
{{#tests}}
* {{summary}}
{{#if annotation}}
{{indent annotation.message}}
{{indent annotation.raw_details}}
{{/if}}
{{/tests}}
{{/suites}}
</details>
{{/runs}}

View File

@@ -0,0 +1,3 @@
{{#runs}}
### {{summary}}
{{/runs}}

71
tsconfig.json Normal file
View File

@@ -0,0 +1,71 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true /* Skip type checking of declaration files. */,
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": ["src/model/ts"]
}

View File

@@ -0,0 +1,17 @@
using UnityEngine;
public class SampleComponent : MonoBehaviour
{
public BasicCounter Counter;
void Start()
{
Counter = new BasicCounter(5);
}
// Update is called once per frame
void Update()
{
Counter.Increment();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7a5f63b9ea4b465194653c4d681faf42
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
using UnityEngine;
public class TimerComponent : MonoBehaviour
{
public BasicCounter Counter = new BasicCounter();
public float Timer = 1f;
void Update()
{
Timer -= Time.deltaTime;
if (Timer > 0)
return;
Counter.Increment();
Timer = 1f;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b668d68a45bb48108ccda73269e3da7b
timeCreated: 1610056748

View File

@@ -2,7 +2,8 @@
"name": "PlayModeTests",
"references": [
"UnityEngine.TestRunner",
"UnityEditor.TestRunner"
"UnityEditor.TestRunner",
"MyScripts"
],
"includePlatforms": [],
"excludePlatforms": [],
@@ -16,4 +17,4 @@
"UNITY_INCLUDE_TESTS"
],
"versionDefines": []
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class SampleComponentTest
{
private GameObject target;
private SampleComponent component;
[SetUp]
public void Setup()
{
target = GameObject.Instantiate(new GameObject());
component = target.AddComponent<SampleComponent>();
}
[UnityTest]
public IEnumerator TestIncrementOnUpdateAfterNextFrame()
{
// Save the current value, since it was updated after component Start() method called
var count = component.Counter.Count;
// Skip frame and assert the new value
yield return null;
Assert.AreEqual(count + 1, component.Counter.Count);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c688799d17b14d35ad515bff9de8d12c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +1,5 @@
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
@@ -12,8 +10,14 @@ namespace Tests
[Test]
public void NewTestScriptSimplePasses()
{
// Use the Assert class to test conditions
Assert.True(true);
// Given
var counter = new BasicCounter(0);
// When
counter.Increment();
// Then
Assert.AreEqual(1, counter.Count);
}
// A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
@@ -21,9 +25,18 @@ namespace Tests
[UnityTest]
public IEnumerator NewTestScriptWithEnumeratorPasses()
{
// Given
var counter = new BasicCounter(3);
// Use the Assert class to test conditions.
// Use yield to skip a frame.
yield return null;
// When
counter.Increment();
// Then
Assert.AreEqual(4, counter.Count);
}
}
}

View File

@@ -0,0 +1,66 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class TimerComponentTest
{
private GameObject target;
private TimerComponent component;
[SetUp]
public void Setup()
{
target = GameObject.Instantiate(new GameObject());
component = target.AddComponent<TimerComponent>();
}
[UnityTest]
public IEnumerator TestIncrementAfterSomeTime()
{
// Save the current value, since it was updated after component Start() method called
var count = component.Counter.Count;
// Skip frame and assert the new value
yield return null;
Assert.AreEqual(count, component.Counter.Count);
yield return new WaitForSeconds(1.1f);
Assert.AreEqual(count + 1, component.Counter.Count);
yield return new WaitForSeconds(1.1f);
Assert.AreEqual(count + 2, component.Counter.Count);
}
[UnityTest]
public IEnumerator TestTimeScaleIsAffectingIncrement()
{
// Save the current value, since it was updated after component Start() method called
var count = component.Counter.Count;
Time.timeScale = .5f;
// Skip frame and assert the new value
yield return null;
Assert.AreEqual(count, component.Counter.Count);
yield return WaitForRealSeconds(1.1f);
Assert.AreEqual(count, component.Counter.Count);
yield return WaitForRealSeconds(1.1f);
Assert.AreEqual(count + 1, component.Counter.Count);
}
// Skipping time ignoring Time.scale
// https://answers.unity.com/questions/301868/yield-waitforseconds-outside-of-timescale.html
public static IEnumerator WaitForRealSeconds(float time)
{
float start = Time.realtimeSinceStartup;
while (Time.realtimeSinceStartup < start + time)
{
yield return null;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 818b22370d404398b87b47a922a435c9
timeCreated: 1610056889

6177
yarn.lock Normal file

File diff suppressed because it is too large Load Diff