Skip to content

Commit 00229a3

Browse files
authored
GHA integration test (#637)
Add GHA for tests Currently only run tests except for NUnit tests since it is broken from Unity 2019. Also add logs when test starts and summary when all the tests are finished.
1 parent 65d9919 commit 00229a3

File tree

3 files changed

+201
-36
lines changed

3 files changed

+201
-36
lines changed

.github/workflows/test.yaml

+129-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,145 @@
11
name: Test
22

33
on:
4+
schedule:
5+
- cron: "0 11 * * *" # 11am UTC = 3`am PST
6+
7+
pull_request:
8+
types: [ labeled, closed ]
9+
410
workflow_dispatch:
511
inputs:
6-
unity_versions:
7-
description: 'Unity version (value: 2018, 2019, 2020. separated by commas)'
12+
unity_version:
13+
description: 'Unity version (value: 2018, 2019, 2020)'
814
default: '2019'
915
required: true
16+
include_test_types:
17+
description: 'Specify the only types of tests to run, separated by comma. See TestTypesEnum in build.gradle for options.'
18+
default: ''
19+
required: false
20+
exclude_test_types:
21+
description: 'Specify the types of tests to exclude, separated by comma. See TestTypesEnum in build.gradle for options.'
22+
default: ''
23+
required: false
24+
include_test_modules:
25+
description: 'Specify the only modules to test against, separated by comma. See TestModulesEnum in build.gradle for options.'
26+
default: ''
27+
required: false
28+
exclude_test_modules:
29+
description: 'Specify the modules to exclude from testing against, separated by comma. See TestModulesEnum in build.gradle for options.'
30+
default: ''
31+
required: false
32+
exclude_tests:
33+
description: 'Specify the tests to exclude, separated by comma. See the tasks in build.gradle for options.'
34+
default: ''
35+
required: false
1036

1137
env:
1238
pythonVersion: '3.7'
1339
artifactRetentionDays: 2
1440

1541
jobs:
42+
check_and_prepare:
43+
runs-on: ubuntu-latest
44+
outputs:
45+
unity_version: ${{ steps.set_outputs.outputs.unity_version }}
46+
include_test_types: ${{ steps.set_outputs.outputs.include_test_types }}
47+
exclude_test_types: ${{ steps.set_outputs.outputs.exclude_test_types }}
48+
include_test_modules: ${{ steps.set_outputs.outputs.include_test_modules }}
49+
exclude_test_modules: ${{ steps.set_outputs.outputs.exclude_test_modules }}
50+
exclude_tests: ${{ steps.set_outputs.outputs.exclude_tests }}
51+
steps:
52+
- id: set_outputs
53+
run: |
54+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
55+
echo "unity_version=${{ github.event.inputs.unity_version }}" >> $GITHUB_OUTPUT
56+
echo "include_test_types=${{ github.event.inputs.include_test_types }}" >> $GITHUB_OUTPUT
57+
echo "exclude_test_types=${{ github.event.inputs.exclude_test_types }}" >> $GITHUB_OUTPUT
58+
echo "include_test_modules=${{ github.event.inputs.include_test_modules }}" >> $GITHUB_OUTPUT
59+
echo "exclude_test_modules=${{ github.event.inputs.exclude_test_modules }}" >> $GITHUB_OUTPUT
60+
echo "exclude_tests=${{ github.event.inputs.exclude_tests }}" >> $GITHUB_OUTPUT
61+
else
62+
# inputs are not available for non "workflow_dispatch" events. Therefore, set default value here.
63+
echo "unity_version=2019" >> $GITHUB_OUTPUT
64+
echo "include_test_types=" >> $GITHUB_OUTPUT
65+
echo "exclude_test_types=" >> $GITHUB_OUTPUT
66+
echo "include_test_modules=" >> $GITHUB_OUTPUT
67+
echo "exclude_test_modules=" >> $GITHUB_OUTPUT
68+
echo "exclude_tests=" >> $GITHUB_OUTPUT
69+
fi
70+
71+
- name: Print output
72+
run: |
73+
echo outputs.unity_version : ${{ steps.set_outputs.outputs.unity_version }}
74+
echo outputs.include_test_types : ${{ steps.set_outputs.outputs.include_test_types }}
75+
echo outputs.exclude_test_types : ${{ steps.set_outputs.outputs.exclude_test_types }}
76+
echo outputs.include_test_modules : ${{ steps.set_outputs.outputs.include_test_modules }}
77+
echo outputs.exclude_test_modules : ${{ steps.set_outputs.outputs.exclude_test_modules }}
78+
echo outputs.exclude_tests : ${{ steps.set_outputs.outputs.exclude_tests }}
79+
1680
test_on_macos:
81+
name: test-macOS-unity${{ needs.check_and_prepare.outputs.unity_version }}
1782
runs-on: macos-latest
83+
needs: [check_and_prepare]
84+
strategy:
85+
fail-fast: false
1886
steps:
19-
- run: echo "Hello World"
87+
- uses: actions/checkout@v3
88+
- id: build_setup
89+
uses: ./gha/build_setup
90+
timeout-minutes: 30
91+
with:
92+
unity_version: ${{ needs.check_and_prepare.outputs.unity_version }}
93+
platform: macOS
94+
python_version: ${{ env.pythonVersion }}
95+
unity_username: ${{ secrets.UNITY_USERNAME }}
96+
unity_password: ${{ secrets.UNITY_PASSWORD }}
97+
unity_serial_id: ${{ secrets.SERIAL_ID }}
98+
99+
- name: Set Unity Env for EDM4U build script
100+
shell: bash
101+
run: echo "UNITY_EXE=${{ env.UNITY_ROOT_DIR }}/Unity.app/Contents/MacOS/Unity" >> $GITHUB_ENV
102+
103+
- name: Run tests
104+
shell: bash
105+
timeout-minutes: 60
106+
run: |
107+
# DISABLE: NUnit test is currently broken from Unity 2019
108+
# DISABLE: testVersionHandlerActivationBatchMode is causing timeout.
109+
./gradlew test -q \
110+
-PINTERACTIVE_MODE_TESTS_ENABLED=0 \
111+
-PINCLUDE_TEST_TYPES="${{ needs.check_and_prepare.outputs.include_test_types }}" \
112+
-PEXCLUDE_TEST_TYPES="NUnit,${{ needs.check_and_prepare.outputs.exclude_test_types }}" \
113+
-PINCLUDE_TEST_MODULES="${{ needs.check_and_prepare.outputs.include_test_modules }}" \
114+
-PEXCLUDE_TEST_MODULES="${{ needs.check_and_prepare.outputs.exclude_test_modules }}" \
115+
-PEXCLUDE_TESTS="testVersionHandlerActivationBatchMode,${{ needs.check_and_prepare.outputs.exclude_tests }}"
116+
117+
- name: Print test log
118+
if: always()
119+
shell: bash
120+
continue-on-error: true
121+
run: cat test_output/test*IntegrationTestsBatchMode/*.log
122+
123+
- name: Obtain Failed tests
124+
if: always()
125+
shell: bash
126+
continue-on-error: true
127+
run: |
128+
cat test_output/test*/*_test.log | grep "^Test .* PASSED$"
129+
cat test_output/test*/*_test.log | grep "^Test .* FAILED$"
130+
cat test_output/test*/*_test.log | grep "^Test .* SKIPPED$"
131+
132+
- name: Return Unity license
133+
if: always()
134+
uses: firebase/firebase-unity-sdk/gha/unity@main
135+
with:
136+
version: ${{ inputs.unity_version }}
137+
release_license: "true"
138+
139+
- name: Upload build logs
140+
uses: actions/upload-artifact@v3
141+
if: ${{ !cancelled() }}
142+
with:
143+
name: logs
144+
path: test_output/test*/*.log
145+
retention-days: ${{ env.artifactRetentionDays }}

build.gradle

+71-32
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,9 @@ void setTestProperties(Task task, TestTypeEnum type, TestModuleEnum module) {
526526
*/
527527
task(testTestTypeEnum) { task ->
528528
setTestProperties(task, TestTypeEnum.GRADLE, TestModuleEnum.TOOL)
529+
doFirst {
530+
ReportTestStarted(task)
531+
}
529532
doLast {
530533
def expectedTestTypeEnumCompleteSet =
531534
new HashSet([
@@ -570,6 +573,9 @@ task(testTestTypeEnum) { task ->
570573
*/
571574
task(testTestModuleEnum) { task ->
572575
setTestProperties(task, TestTypeEnum.GRADLE, TestModuleEnum.TOOL)
576+
doFirst {
577+
ReportTestStarted(task)
578+
}
573579
doLast {
574580
def expectedTestModuleEnumCompleteSet =
575581
new HashSet([
@@ -1480,6 +1486,9 @@ Task createUnityTestTask(String taskName, String description,
14801486
doLast {
14811487
EvaluateTestResult(task)
14821488
}
1489+
doFirst {
1490+
ReportTestStarted(task)
1491+
}
14831492
setTestProperties(task, testType, testModule)
14841493
}
14851494

@@ -1713,54 +1722,62 @@ task testDownloadArtifacts(type: GradleBuild) { task ->
17131722
doLast {
17141723
EvaluateTestResult(task)
17151724
}
1725+
doFirst {
1726+
ReportTestStarted(task)
1727+
}
17161728
finalizedBy "reportAllTestsResult"
17171729
}
17181730

1731+
1732+
/*
1733+
* Report when a test starts to run
1734+
*
1735+
* @param testTask Task for test to start.
1736+
*/
1737+
void ReportTestStarted(Task testTask) {
1738+
println sprintf("Test %s STARTED", testTask.name)
1739+
}
1740+
17191741
/*
17201742
* Evaluate previously-ran test result
17211743
*
17221744
* @param testTask Task for previously-ran test
17231745
*/
17241746
void EvaluateTestResult(Task testTask) {
1747+
Boolean succeeded = false
17251748
if (testTask.class.simpleName.startsWith("Exec")) {
1726-
if (testTask.execResult.exitValue != 0) {
1727-
String errorMsg = sprintf("Test %s FAILED", testTask.name)
1728-
println sprintf("::error::%s", errorMsg)
1729-
project.ext.testSessions.add(new TestSession(
1730-
name: testTask.name,
1731-
type: testTask.ext.testType,
1732-
module: testTask.ext.testModule,
1733-
isPassed: false))
1734-
if (!project.ext.continueOnFailForTestsEnabled) {
1735-
throw new GradleException(errorMsg)
1736-
}
1737-
} else {
1738-
println sprintf("::debug::Test %s PASSED", testTask.name, testTask.execResult.exitValue)
1739-
project.ext.testSessions.add(new TestSession(
1740-
name: testTask.name,
1741-
type: testTask.ext.testType,
1742-
module: testTask.ext.testModule,
1743-
isPassed: true))
1749+
if (testTask.execResult.exitValue == 0) {
1750+
succeeded = true
17441751
}
17451752
} else if (testTask.class.simpleName.startsWith("DefaultTask") ||
17461753
testTask.class.simpleName.startsWith("GradleBuild")) {
17471754
if (testTask.state.didWork && testTask.state.failure == null) {
1748-
project.ext.testSessions.add(new TestSession(
1749-
name: testTask.name,
1750-
type: testTask.ext.testType,
1751-
module: testTask.ext.testModule,
1752-
isPassed: true))
1753-
} else {
1754-
project.ext.testSessions.add(new TestSession(
1755-
name: testTask.name,
1756-
type: testTask.ext.testType,
1757-
module: testTask.ext.testModule,
1758-
isPassed: false))
1755+
succeeded = true
17591756
}
17601757
} else {
17611758
throw new GradleException(
17621759
sprintf("Unsupported test class %s", testTask.class.simpleName))
17631760
}
1761+
1762+
if (succeeded) {
1763+
println sprintf("Test %s PASSED", testTask.name)
1764+
project.ext.testSessions.add(new TestSession(
1765+
name: testTask.name,
1766+
type: testTask.ext.testType,
1767+
module: testTask.ext.testModule,
1768+
isPassed: true))
1769+
} else {
1770+
String errorMsg = sprintf("Test %s FAILED", testTask.name)
1771+
println sprintf("::error::%s", errorMsg)
1772+
project.ext.testSessions.add(new TestSession(
1773+
name: testTask.name,
1774+
type: testTask.ext.testType,
1775+
module: testTask.ext.testModule,
1776+
isPassed: false))
1777+
if (!project.ext.continueOnFailForTestsEnabled) {
1778+
throw new GradleException(errorMsg)
1779+
}
1780+
}
17641781
}
17651782

17661783
Task reportAllTestsResult = tasks.create (
@@ -1769,26 +1786,36 @@ Task reportAllTestsResult = tasks.create (
17691786
type: Task
17701787
).with {
17711788
doLast {
1789+
if (project.ext.testSessions.isEmpty()) {
1790+
return
1791+
}
1792+
1793+
println "\n\n[Test Summary]"
17721794
int failedCount = 0
17731795
int totalCount = 0
17741796
project.ext.testSessions.each { session ->
17751797
String resultStr
17761798
++totalCount
1799+
String logType = ""
17771800
if (session.isPassed) {
17781801
resultStr = "PASSED"
17791802
} else {
17801803
resultStr = "FAILED"
1804+
logType = "::error::"
17811805
++failedCount
17821806
}
1783-
println sprintf("Test %s %s [%s/%s]",
1807+
println sprintf("%sTest %s %s [%s/%s]",
1808+
logType,
17841809
session.name,
17851810
resultStr,
17861811
session.type,
17871812
session.module)
17881813
}
1814+
println "--------------------------------------"
1815+
println sprintf("::notice::%s out of %d test(s) passed", totalCount - failedCount, totalCount)
17891816
if (failedCount > 0) {
17901817
throw new GradleException(
1791-
sprintf("%d out of %d tests failed", failedCount, totalCount))
1818+
sprintf("%d out of %d test(s) failed", failedCount, totalCount))
17921819
}
17931820
}
17941821
}
@@ -1805,6 +1832,9 @@ Task testPackageUploader = createPythonTask(
18051832
doLast {
18061833
EvaluateTestResult(task)
18071834
}
1835+
doFirst {
1836+
ReportTestStarted(task)
1837+
}
18081838
setTestProperties(task, TestTypeEnum.PYTHON, TestModuleEnum.TOOL)
18091839
}
18101840

@@ -1821,7 +1851,10 @@ createPythonTask(
18211851
doLast {
18221852
EvaluateTestResult(task)
18231853
}
1824-
}
1854+
doFirst {
1855+
ReportTestStarted(task)
1856+
}
1857+
}
18251858

18261859
createPythonTask(
18271860
"testGenGuids",
@@ -1836,6 +1869,9 @@ createPythonTask(
18361869
doLast {
18371870
EvaluateTestResult(task)
18381871
}
1872+
doFirst {
1873+
ReportTestStarted(task)
1874+
}
18391875
}
18401876

18411877
createPythonTask(
@@ -1851,6 +1887,9 @@ createPythonTask(
18511887
doLast {
18521888
EvaluateTestResult(task)
18531889
}
1890+
doFirst {
1891+
ReportTestStarted(task)
1892+
}
18541893
}
18551894

18561895
task updateEmbeddedGradleWrapper(type: Zip) {

gha/build_setup/action.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ runs:
6565
with:
6666
version: ${{ inputs.unity_version }}
6767
# iOS build support is always required to build EDM4U
68-
platforms: "${{ inputs.platform }},iOS"
68+
platforms: "${{ inputs.platform }},iOS,Android"
6969
username: ${{ inputs.unity_username }}
7070
password: ${{ inputs.unity_password }}
7171
serial_ids: ${{ inputs.unity_serial_id }}

0 commit comments

Comments
 (0)