-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathunit_test.py
More file actions
126 lines (104 loc) · 5.9 KB
/
unit_test.py
File metadata and controls
126 lines (104 loc) · 5.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""
Runs the unit test suite for the Unity SDK's C# implementation layer.
Unless explicitly stated otherwise, all files in this repository are licensed under the
Apache License Version 2.0. This product includes software developed at Datadog
(https://www.datadoghq.com/). Copyright 2025-Present Datadog, Inc.
"""
import os
import sys
import argparse
from typing import List
from junitparser.junitparser import JUnitXml, TestCase
from common.log import init_logger
from common.unity import UnityHub, resolve_unity_install, UnityLicenseStatus
from common.xslt import transform_nunit_to_junit
__repo_root__ = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
__default_test_project_root__ = os.path.join(__repo_root__, 'samples', 'Datadog Sample')
__default_test_project_unity_version__ = '2022'
def unit_test(version_prefix: str, project_path: str, platforms: List[str], out_junit_path_pattern: str):
"""
Prerequisites: Unity Hub must be installed on the system, and the target version of
Unity Editor must be installed through Unity Hub. If no fixed license is installed
locally, the Unity Licensing Client must be configured to obtain a floating license.
"""
log = init_logger()
# Require at least one valid platform
if not platforms:
raise ValueError('No test platforms specified')
# Ensure that our output path has a 'platform' placeholder
if r'%(platform)s' not in out_junit_path_pattern:
root, ext = os.path.splitext(out_junit_path_pattern)
out_junit_path_pattern = root + r'-%(platform)s' + ext
# Check to see if we have the requisite Unity version installed
unity_hub = UnityHub.require()
unity_installs = unity_hub.list_installs()
unity_install = resolve_unity_install(unity_installs, version_prefix)
if not unity_install:
raise RuntimeError(f'No Unity version matching {version_prefix} is installed')
for platform in platforms:
# Compute paths to artifact files
junit_abspath = os.path.abspath(out_junit_path_pattern % {'platform': platform.lower()})
artifact_dir, junit_filename = os.path.split(junit_abspath)
junit_filename_noext, _ = os.path.splitext(junit_filename)
nunit_abspath = os.path.join(artifact_dir, 'nunit-' + junit_filename)
log_abspath = os.path.join(artifact_dir, junit_filename_noext + '.log')
# Ensure that any stale artifacts from previous runs are cleaned up
for abspath in [junit_abspath, nunit_abspath, log_abspath]:
if os.path.isfile(abspath):
log.info(f'Deleting old artifact: {abspath}')
os.remove(abspath)
log.info(f'Running {platform} unit tests for project {os.path.basename(project_path)} in Unity {unity_install.version}...')
args = [
'-runTests',
'-testCategory', '!integration',
'-testPlatform', platform,
'-testResults', nunit_abspath,
]
result = unity_install.run_batchmode(project_path, *args, log_path=log_abspath)
if result.exitcode == 0:
log.info('Tests finished successfully.')
elif result.exitcode == 2:
log.error('Tests failed.')
elif result.license_status != UnityLicenseStatus.VALID:
log.error('Unity failed to acquire a license.')
return 86
else:
raise RuntimeError(f'Unity exited with status code {result.exitcode}')
# Verify that fresh test results have been written to disk
if not os.path.isfile(nunit_abspath):
raise RuntimeError(f'Unity failed to write test results to {nunit_abspath}')
# Convert the intermediate NUnit results file to JUnit format, and parse them
transform_nunit_to_junit(nunit_abspath, junit_abspath)
log.info(f'JUnit results written to: {junit_abspath}')
os.remove(nunit_abspath)
test_results = JUnitXml.fromfile(junit_abspath)
# Summarize JUnit results in the console
num_skipped = 0
num_passed = 0
failed_cases: List[TestCase] = []
for suite in test_results:
for case in suite:
if case.is_skipped:
num_skipped += 1
continue
if case.is_passed:
num_passed += 1
continue
failed_cases.append(case)
# If any tests failed, print a basic summary and propagate Unity's exit
# code: do not proceed to testing additional platforms
if failed_cases or result.exitcode == 2:
log.error(f'{len(failed_cases)} of {num_passed + len(failed_cases)} tests failed:')
for case in failed_cases:
log.error(f'❌ {case.name}')
return 2
log.info(f'✅ {num_passed} tests passed ({num_skipped} skipped).')
log.info('Unit tests completed OK.')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Runs the Unity SDK\'s Unit Test suite against the given version of Unity running the specified project')
parser.add_argument('--unity-version', '-u', default=__default_test_project_unity_version__, help='The target version of Unity to build with; may be a partial specifier (e.g. "6000", "2023.3")')
parser.add_argument('--project', '-p', default=__default_test_project_root__, help="Path to the root directory of the Unity project to load; defaults to 'samples/Datadog Sample' in this repo")
parser.add_argument('--platform', dest='platforms', action='append', default=['EditMode', 'PlayMode'], help='Platforms to test, e.g. EditMode, PlayMode, or a supported build platform')
parser.add_argument('--out-junit-path-pattern', '-o', default='unit-test-%(platform)s.xml', help='Path where JUnit-formatted results will be written, relative to working directory')
args = parser.parse_args()
sys.exit(unit_test(args.unity_version, args.project, args.platforms, args.out_junit_path_pattern))