Compare commits

...

13 Commits
v4.1.0 ... main

Author SHA1 Message Date
Renner 61fd9aa167
Provide descriptive activation information on error (#296)
When trying to activate using Unity.Licensing.Client, any errors will
provide no output. This change makes sure to provide context as to why
the Unity.Licensing.Client has failed to retrieve a license.

Signed-off-by: J. Renner <joao.renner@virtualisurg.com>
2025-08-01 13:26:43 -05:00
Gabriel Le Breton 0483262850
Add warning for invalid nunit xml files (#286)
* Allow ResultsParser to fail on non-nunit xml files

* yarn build

* Add file check for NUnit XML format before parsing

* yarn build

* Update src/model/results-check.ts

Co-authored-by: Koji Hasegawa <hasegawa@nowsprinting.com>

---------

Co-authored-by: Koji Hasegawa <hasegawa@nowsprinting.com>
2024-11-08 23:43:21 +01:00
Joe Anderson 05a00ef5ac
Fix: Debug.LogError annotation point not parsed correctly (#279) 2024-07-20 14:25:59 -05:00
David Finol 0ff419b913
Fix GitHub Issue #214 (#274) 2024-06-15 11:17:55 -07:00
David Finol e0e796f3d9
Fix README.md typo (#273) 2024-06-12 06:16:26 -05:00
nic van dessel eba7e93e66
feat: support private scoped registry on ubuntu (#272) 2024-06-03 19:06:26 +02:00
Andrew Kahr 5817131b76
Parity with unity builder image version regex (#267) 2024-05-07 12:08:32 +02:00
Andrew Kahr fea469be8c
Support new unity versioning scheme with regex matching groups (#264)
* Support new unity versioning scheme with regex matching groups

* Update github action packages

* Pin windows runner image version to 2022. Fix artifact name. Remove max-parallel cap for tests
2024-05-06 22:49:20 +01:00
Sokuhatiku 75d0d76deb
fix: Action did not work on Windows runners. (#257)
* Remove symlink files

* Update entrypoint scripts for windows runner

* Add windows runner tests

* Fix unity editor path

* Set -nographics option for avoid d3d11 initialization error

* Fix Unity project path in windows standalone build script
2024-03-21 14:12:35 +01:00
Quake 35b5a08132
fix: add check before performing chmod on the code coverage path (#262)
* fix: add check before performing chmod on the code coverage path, as it does not exist if the package is not installed

* fix: generalise the dir not existing message more

* fix: improve guide message

---------

Co-authored-by: Quake <QuakeEye@users.noreply.GitHub.com>
2024-03-15 01:25:44 +01:00
nic van dessel 317261b223
fix(package-mode): scoped registry manifest conditional (#263)
* fix: registry incorrectly added to manifest when package testing

* fix scopes conditional

---------

Co-authored-by: Tobias Perelstein <5562156+tobocop2@users.noreply.github.com>
2024-03-14 14:18:56 -04:00
nic van dessel 9d8ff067a3
Add support for Scoped Registries (#261)
* add: new inputs and method params

* feat: add scoped registry to manifest

* feat: setup test job

* fix(workflow): revert change from license to serial

* feat: support private scoped registries

* fix: multiple scopes
2024-03-14 17:13:12 +01:00
Falko 7c242f70d9
Set fullProjectPath variable in entrypoint.sh (#256)
* Set fullProjectPath variable in entrypoint.sh (#255)

* Add test that runs as host user

This should catch bugs like the one described in #255.
2023-12-25 11:53:38 +01:00
56 changed files with 2248 additions and 1514 deletions

View File

@ -27,11 +27,14 @@ jobs:
# - 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
name: Test in ${{ matrix.testMode }} of version ${{ matrix.unityVersion }} on ${{ matrix.baseRunner }}
runs-on: ${{ matrix.baseRunner }}
strategy:
fail-fast: false
matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath:
- unity-project-with-correct-tests
unityVersion:
@ -54,12 +57,12 @@ jobs:
###########################
# Cache #
###########################
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }}
restore-keys: |
Library-
Library-${{ matrix.baseRunner }}
- uses: ./
id: tests
with:
@ -68,18 +71,21 @@ jobs:
testMode: ${{ matrix.testMode }}
artifactsPath: ${{ matrix.testMode }}-artifacts
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: Test results for ${{ matrix.testMode }}
name: Test results for ${{ matrix.testMode }} (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: ${{ steps.tests.outputs.artifactsPath }}
retention-days: 14
testRunnerInAllModes:
name: Test all modes ✨
runs-on: ubuntu-latest
runs-on: ${{ matrix.baseRunner }}
strategy:
fail-fast: false
matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath:
- unity-project-with-correct-tests
unityVersion:
@ -97,13 +103,12 @@ jobs:
###########################
# Cache #
###########################
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
Library-${{ matrix.baseRunner }}
# Configure test runner
- name: Run tests
@ -118,32 +123,38 @@ jobs:
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Test results (all)
name: Test results (all) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: ${{ steps.allTests.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Coverage results (all)
name: Coverage results (all) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: ${{ steps.allTests.outputs.coveragePath }}
retention-days: 14
testRunnerInEditMode:
name: Test edit mode 📝
runs-on: ubuntu-latest
runs-on: ${{ matrix.baseRunner }}
strategy:
fail-fast: false
matrix:
baseRunner:
- ubuntu-latest
- windows-2022
unityVersion:
- 2022.3.13f1
- 2023.1.19f1
- 2023.2.2f1
projectPath:
- unity-project-with-correct-tests
runAsHostUser:
- true
- false
steps:
###########################
# Checkout #
@ -155,13 +166,12 @@ jobs:
###########################
# Cache #
###########################
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
Library-${{ matrix.baseRunner }}
# Configure test runner
- name: Run tests
@ -170,31 +180,35 @@ jobs:
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
runAsHostUser: ${{ matrix.runAsHostUser }}
testMode: editmode
artifactsPath: artifacts/editmode
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Test results (edit mode)
name: Test results (edit mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}, ${{ matrix.runAsHostUser }})
path: ${{ steps.editMode.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Coverage results (edit mode)
name: Coverage results (edit mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }}, ${{ matrix.runAsHostUser }})
path: ${{ steps.editMode.outputs.coveragePath }}
retention-days: 14
testRunnerInPlayMode:
name: Test play mode 📺
runs-on: ubuntu-latest
runs-on: ${{ matrix.baseRunner }}
strategy:
fail-fast: false
matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath:
- unity-project-with-correct-tests
unityVersion:
@ -212,13 +226,12 @@ jobs:
###########################
# Cache #
###########################
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
Library-${{ matrix.baseRunner }}
# Configure test runner
- name: Run tests
@ -232,26 +245,29 @@ jobs:
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Test results (play mode)
name: Test results (play mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: ${{ steps.playMode.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Coverage results (play mode)
name: Coverage results (play mode) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: ${{ steps.playMode.outputs.coveragePath }}
retention-days: 14
testRunnerInStandalone:
name: Test standalone 📺
runs-on: ubuntu-latest
runs-on: ${{ matrix.baseRunner }}
strategy:
fail-fast: false
matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath:
- unity-project-with-correct-tests
unityVersion:
@ -269,13 +285,12 @@ jobs:
###########################
# Cache #
###########################
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
Library-${{ matrix.baseRunner }}-
# Configure test runner
- name: Run tests
@ -289,18 +304,21 @@ jobs:
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Test results (play mode)
name: Test results (play mode standalone) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: ${{ steps.standalone.outputs.artifactsPath }}
retention-days: 14
testRunnerInStandaloneWithIL2CPP:
name: Test standalone with IL2CPP 📺
runs-on: ubuntu-latest
runs-on: ${{ matrix.baseRunner }}
strategy:
fail-fast: false
matrix:
baseRunner:
- ubuntu-latest
- windows-2022
projectPath:
- unity-project-with-correct-tests
unityVersion:
@ -318,13 +336,12 @@ jobs:
###########################
# Cache #
###########################
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
Library-${{ matrix.baseRunner }}-
# Set scripting backend to IL2CPP
- name: Rewrite ProjectSettings
@ -332,6 +349,7 @@ jobs:
DefineOriginal=" scriptingBackend: {}"
DefineReplace=" scriptingBackend: \\n Standalone: 1"
sed -i "{s/$DefineOriginal/$DefineReplace/g}" ${{ matrix.projectPath }}/ProjectSettings/ProjectSettings.asset
shell: bash
# Configure test runner
- name: Run tests
@ -345,18 +363,21 @@ jobs:
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Test results (play mode)
name: Test results (play mode standalone il2cpp) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: ${{ steps.standalone.outputs.artifactsPath }}
retention-days: 14
testEachModeSequentially:
name: Test each mode sequentially 👩‍👩‍👧‍👦 # don't try this at home (it's much slower)
runs-on: ubuntu-latest
runs-on: ${{ matrix.baseRunner }}
strategy:
fail-fast: false
matrix:
baseRunner:
- ubuntu-latest
- windows-2022
unityVersion:
- 2022.3.13f1
- 2023.1.19f1
@ -374,13 +395,12 @@ jobs:
###########################
# Cache #
###########################
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
path: ${{ matrix.projectPath }}/Library
key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
key: Library-${{ matrix.baseRunner }}-${{ matrix.projectPath }}
restore-keys: |
Library-${{ matrix.projectPath }}-
Library-
Library-${{ matrix.baseRunner }}-
# Configure first test runner
- name: Tests in editmode 📝
@ -411,9 +431,9 @@ jobs:
# Upload combined artifacts
- name: Upload combined test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Test results (combined)
name: Test results (combined sequential) (${{ matrix.baseRunner }}, ${{ matrix.unityVersion }})
path: artifacts/
retention-days: 14
@ -452,9 +472,9 @@ jobs:
customParameters: -profile SomeProfile -someBoolean -someValue exampleValue
packageMode: true
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: Package test results for ${{ matrix.testMode }}
name: Package test results for ${{ matrix.testMode }} (${{ matrix.unityVersion }})
path: ${{ steps.packageTests.outputs.artifactsPath }}
retention-days: 14
@ -492,17 +512,17 @@ jobs:
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Package test results (all)
name: Package test results (all) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Package Coverage results (all)
name: Package Coverage results (all) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.coveragePath }}
retention-days: 14
@ -540,17 +560,17 @@ jobs:
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Package test results (edit mode)
name: Package test results (edit mode) (${{ matrix.unityVersion }})
path: ${{ steps.packageEditMode.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Package Coverage results (edit mode)
name: Package Coverage results (edit mode) (${{ matrix.unityVersion }})
path: ${{ steps.packageEditMode.outputs.coveragePath }}
retention-days: 14
@ -588,17 +608,17 @@ jobs:
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Package test results (play mode)
name: Package test results (play mode) (${{ matrix.unityVersion }})
path: ${{ steps.packagePlayMode.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Package Coverage results (play mode)
name: Package Coverage results (play mode) (${{ matrix.unityVersion }})
path: ${{ steps.packagePlayMode.outputs.coveragePath }}
retention-days: 14
@ -644,8 +664,108 @@ jobs:
# Upload combined artifacts
- name: Upload combined test results
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: Package test results (combined)
name: Package test results (combined sequential) (${{ matrix.unityVersion }})
path: packageArtifacts/
retention-days: 14
testPackageRunnerWithScopeRegistry:
name: Test package mode in all modes with Scoped Registry 📦✨
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- unity-package-with-correct-tests/com.dependencyexample.testpackage
unityVersion:
- 2022.3.13f1
- 2023.1.19f1
- 2023.2.2f1
steps:
###########################
# Checkout #
###########################
- uses: actions/checkout@v4
with:
lfs: true
# Configure test runner
- name: Run tests
id: packageAllTests
uses: ./
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: all
coverageOptions: 'generateAdditionalMetrics;generateHtmlReport;generateBadgeReport;assemblyFilters:+dependencyexample.testpackage.*,-*Tests*'
packageMode: true
scopedRegistryUrl: https://package.openupm.com
registryScopes: 'com.cysharp.unitask'
# Test implicit artifactsPath, by not setting it
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: Package test results (Scope Registry) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v4
with:
name: Package Coverage results (Scope Registry) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.coveragePath }}
retention-days: 14
testPackageRunnerWithScopeRegistryAndMultipleScopes:
name: Test package mode in all modes with Scoped Registry and Multiple Scopes 🔎📦✨
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
projectPath:
- unity-package-with-correct-tests/com.dependencyexample.testpackage
unityVersion:
- 2022.3.13f1
- 2023.1.19f1
- 2023.2.2f1
steps:
###########################
# Checkout #
###########################
- uses: actions/checkout@v4
with:
lfs: true
# Configure test runner
- name: Run tests
id: packageAllTests
uses: ./
with:
projectPath: ${{ matrix.projectPath }}
unityVersion: ${{ matrix.unityVersion }}
testMode: all
coverageOptions: 'generateAdditionalMetrics;generateHtmlReport;generateBadgeReport;assemblyFilters:+dependencyexample.testpackage.*,-*Tests*'
packageMode: true
scopedRegistryUrl: https://package.openupm.com
registryScopes: 'com.cysharp, com.cysharp.unitask'
# Test implicit artifactsPath, by not setting it
# Upload artifacts
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: Package test results (Multi Scope Regristy) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.artifactsPath }}
retention-days: 14
# Upload coverage
- name: Upload coverage results
uses: actions/upload-artifact@v4
with:
name: Package Coverage results (Multi Scope Registry) (${{ matrix.unityVersion }})
path: ${{ steps.packageAllTests.outputs.coveragePath }}
retention-days: 14

View File

@ -45,7 +45,7 @@ GameCI is free for everyone forever.
You can support us at [OpenCollective](https://opencollective.com/game-ci).
## Licence
## License
This repository is [MIT](./LICENSE) licensed.

View File

@ -56,6 +56,14 @@ inputs:
required: false
default: false
description: 'Whether the tests are being run for a Unity package instead of a Unity project. If true, the action can only be run on Linux runners, and any custom docker image passed to this action must have `jq` installed. NOTE: may not work properly for packages with dependencies outside of the Unity Registry.'
scopedRegistryUrl:
required: false
default: ''
description: 'Scoped registry to use for resolving package dependencies. Only applicable if packageMode is true.'
registryScopes:
required: false
default: ''
description: 'Registry scopes to use for resolving package dependencies. Only applicable if packageMode is true. Required if scopedRegistry is set.'
chownFilesTo:
required: false
default: ''

2715
dist/index.js generated vendored

File diff suppressed because it is too large Load Diff

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

1
dist/main.js vendored
View File

@ -1 +0,0 @@
index.js

3
dist/main.js vendored 100644
View File

@ -0,0 +1,3 @@
const index = require('./index.js');
index.main();

View File

@ -65,7 +65,14 @@ elif [[ -n "$UNITY_LICENSING_SERVER" ]]; then
FLOATING_LICENSE=$(sed -n 2p <<< "$PARSEDFILE")
FLOATING_LICENSE_TIMEOUT=$(sed -n 4p <<< "$PARSEDFILE")
echo "Acquired floating license: \"$FLOATING_LICENSE\" with timeout $FLOATING_LICENSE_TIMEOUT"
if [[ -z "$FLOATING_LICENSE" || -z "$FLOATING_LICENSE_TIMEOUT" ]]; then
echo "::error ::Failed to acquire floating license from Unity Licensing Server."
echo "Check the activation log below for more details."
cat license.txt
else
echo "Acquired floating license: \"$FLOATING_LICENSE\" with timeout $FLOATING_LICENSE_TIMEOUT"
fi
# Store the exit code from the verify command
else
#

View File

@ -9,6 +9,8 @@ fi
if [[ "$RUN_AS_HOST_USER" == "true" ]]; then
echo "Running as host user"
fullProjectPath="$GITHUB_WORKSPACE/$PROJECT_PATH"
# Stop on error if we can't set up the user
set -e

View File

@ -36,6 +36,25 @@ echo "Using custom parameters $CUSTOM_PARAMETERS."
echo "Using Unity version \"$UNITY_VERSION\" to test."
#
# Setup token for private package registry.
#
if [ -n "$PRIVATE_REGISTRY_TOKEN" ]; then
echo "Private registry token detected, creating .upmconfig.toml"
UPM_CONFIG_TOML_PATH="$HOME/.upmconfig.toml"
echo "Creating toml at path: $UPM_CONFIG_TOML_PATH"
touch $UPM_CONFIG_TOML_PATH
cat > "$UPM_CONFIG_TOML_PATH" <<EOF
[npmAuth."$SCOPED_REGISTRY_URL"]
token = "$PRIVATE_REGISTRY_TOKEN"
alwaysAuth = true
EOF
fi
#
# Create an empty project for testing if in package mode
#
@ -95,14 +114,32 @@ if [ "$PACKAGE_MODE" = "true" ]; then
fi
PACKAGE_MANIFEST_JSON=$(cat "$PACKAGE_MANIFEST_PATH")
echo "$PACKAGE_MANIFEST_JSON" | \
jq \
--arg packageName "$PACKAGE_NAME" \
--arg projectPath "$UNITY_PROJECT_PATH" \
'.dependencies += {"com.unity.testtools.codecoverage": "1.1.1"} | .dependencies += {"\($packageName)": "file:\($projectPath)"} | . += {testables: ["\($packageName)"]}' \
> "$PACKAGE_MANIFEST_PATH"
if [ -z "$SCOPED_REGISTRY_URL" ] || [ -z "$REGISTRY_SCOPES" ]; then
echo "$PACKAGE_MANIFEST_JSON" | \
jq \
--arg packageName "$PACKAGE_NAME" \
--arg projectPath "$UNITY_PROJECT_PATH" \
'.dependencies += {"com.unity.testtools.codecoverage": "1.1.1"} | .dependencies += {"\($packageName)": "file:\($projectPath)"} | . += {testables: ["\($packageName)"]}' \
> "$PACKAGE_MANIFEST_PATH"
else
echo "$PACKAGE_MANIFEST_JSON" | \
jq \
--arg packageName "$PACKAGE_NAME" \
--arg projectPath "$UNITY_PROJECT_PATH" \
--arg scopedRegistryUrl "$SCOPED_REGISTRY_URL" \
--argjson registryScopes "$(echo "[\"$REGISTRY_SCOPES\"]" | sed 's/,/","/g')" \
'.dependencies += {"com.unity.testtools.codecoverage": "1.1.1"} |
.dependencies += {"\($packageName)": "file:\($projectPath)"} |
. += {testables: ["\($packageName)"]} |
. += {scopedRegistries: [{"name":"dependency", "url":"\($scopedRegistryUrl)", scopes: $registryScopes}] }' \
> "$PACKAGE_MANIFEST_PATH"
fi
UNITY_PROJECT_PATH="$TEMP_PROJECT_PATH"
fi
@ -242,4 +279,10 @@ fi
# Add read permissions for everyone to all artifacts
chmod -R a+r "$UNITY_PROJECT_PATH"
chmod -R a+r "$FULL_ARTIFACTS_PATH"
chmod -R a+r "$FULL_COVERAGE_RESULTS_PATH"
# Check if coverage results directory exists
if [ -d "$FULL_COVERAGE_RESULTS_PATH" ]; then
chmod -R a+r "$FULL_COVERAGE_RESULTS_PATH"
else
echo "Coverage results directory does not exist. If you are expecting coverage results, please make sure the Code Coverage package is installed in your unity project and that it is set up correctly."
fi

View File

@ -67,24 +67,24 @@ foreach ( $platform in ${env:TEST_PLATFORMS}.Split(";") )
Write-Output ""
# Create directories if they do not exist
if(-Not (Test-Path -Path $Env:UNITY_PROJECT_PATH\Assets\Editor))
if(-Not (Test-Path -Path $UNITY_PROJECT_PATH\Assets\Editor))
{
# We use -Force to suppress output, doesn't overwrite anything
New-Item -ItemType Directory -Force -Path $Env:UNITY_PROJECT_PATH\Assets\Editor
New-Item -ItemType Directory -Force -Path $UNITY_PROJECT_PATH\Assets\Editor
}
if(-Not (Test-Path -Path $Env:UNITY_PROJECT_PATH\Assets\Player))
if(-Not (Test-Path -Path $UNITY_PROJECT_PATH\Assets\Player))
{
# We use -Force to suppress output, doesn't overwrite anything
New-Item -ItemType Directory -Force -Path $Env:UNITY_PROJECT_PATH\Assets\Player
}
# Copy the scripts
Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Editor" -Destination $Env:UNITY_PROJECT_PATH\Assets\Editor -Recurse
Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Player" -Destination $Env:UNITY_PROJECT_PATH\Assets\Player -Recurse
Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Editor" -Destination $UNITY_PROJECT_PATH\Assets\Editor -Recurse
Copy-Item -Path "c:\UnityStandaloneScripts\Assets\Player" -Destination $UNITY_PROJECT_PATH\Assets\Player -Recurse
# Verify recursive paths
Get-ChildItem -Path $Env:UNITY_PROJECT_PATH\Assets\Editor -Recurse
Get-ChildItem -Path $Env:UNITY_PROJECT_PATH\Assets\Player -Recurse
Get-ChildItem -Path $UNITY_PROJECT_PATH\Assets\Editor -Recurse
Get-ChildItem -Path $UNITY_PROJECT_PATH\Assets\Player -Recurse
$runTests="-runTests -testPlatform StandaloneWindows64 -builtTestRunnerPath $UNITY_PROJECT_PATH\Build\UnityTestRunner-Standalone.exe"
}
@ -106,7 +106,20 @@ foreach ( $platform in ${env:TEST_PLATFORMS}.Split(";") )
}
}
$TEST_OUTPUT = Start-Process -NoNewWindow -Wait -PassThru "C:\Program Files\Unity\Hub\Editor\${env:UNITY_VERSION}\editor\Unity.exe" -ArgumentList "-batchmode -logFile $FULL_ARTIFACTS_PATH\$platform.log -projectPath $UNITY_PROJECT_PATH -coverageResultsPath $FULL_COVERAGE_RESULTS_PATH $runTests -enableCodeCoverage -debugCodeOptimization -coverageOptions ${env:COVERAGE_OPTIONS} ${env:CUSTOM_PARAMETERS}"
$TEST_OUTPUT = Start-Process -FilePath "$Env:UNITY_PATH/Editor/Unity.exe" `
-NoNewWindow `
-Wait `
-PassThru `
-ArgumentList "-batchmode `
-nographics `
-logFile $FULL_ARTIFACTS_PATH\$platform.log `
-projectPath $UNITY_PROJECT_PATH `
-coverageResultsPath $FULL_COVERAGE_RESULTS_PATH `
$runTests `
-enableCodeCoverage `
-debugCodeOptimization `
-coverageOptions ${env:COVERAGE_OPTIONS} `
${env:CUSTOM_PARAMETERS}"
# Catch exit code
$TEST_EXIT_CODE = $TEST_OUTPUT.ExitCode

1
dist/post.js vendored
View File

@ -1 +0,0 @@
index.js

3
dist/post.js vendored 100644
View File

@ -0,0 +1,3 @@
const index = require('./index.js');
index.post();

View File

@ -1,30 +1,2 @@
import { run as main } from './main';
import path from 'path';
import { run as post } from './post';
/*
* GitHub Action can provide multiple executable entrypoints (pre, main, post),
* but it is complicated process to generate multiple `.js` files with `ncc`.
* So we rather generate just one entrypoint, that is symlinked to multiple locations (main.js and post.js).
* Then when GitHub Action Runner executes it as `node path/to/main.js` and `node path/to/post.js`,
* it can read arguments it was executed with and decide which file to execute.
* The argv[0] is going to be a full path to `node` executable and
* the argv[1] is going to be the full path to the script.
* In case index.js would be marked executable and executed directly without the argv[1] it defaults to "main.js".
*/
async function run([, name = 'main.js']: string[]) {
const script = path.basename(name);
switch (script) {
case 'main.js':
await main();
break;
case 'post.js':
await post();
break;
default:
throw new Error(`Unknown script argument: '${script}'`);
}
}
run(process.argv);
export { run as main } from './main';
export { run as post } from './post';

View File

@ -22,6 +22,8 @@ export async function run() {
checkName,
packageMode,
packageName,
scopedRegistryUrl,
registryScopes,
chownFilesTo,
dockerCpuLimit,
dockerMemoryLimit,
@ -55,6 +57,8 @@ export async function run() {
sshPublicKeysDirectoryPath,
packageMode,
packageName,
scopedRegistryUrl,
registryScopes,
gitPrivateToken,
githubToken,
chownFilesTo,

View File

@ -38,6 +38,9 @@ class ImageEnvironmentFactory {
{ name: 'ARTIFACTS_PATH', value: parameters.artifactsPath },
{ name: 'PACKAGE_MODE', value: parameters.packageMode },
{ name: 'PACKAGE_NAME', value: parameters.packageName },
{ name: 'SCOPED_REGISTRY_URL', value: parameters.scopedRegistryUrl },
{ name: 'REGISTRY_SCOPES', value: parameters.registryScopes },
{ name: 'PRIVATE_REGISTRY_TOKEN', value: process.env.UPM_REGISTRY_TOKEN },
{ name: 'GIT_PRIVATE_TOKEN', value: parameters.gitPrivateToken },
{ name: 'VERSION', value: parameters.buildVersion },
{ name: 'CUSTOM_PARAMETERS', value: parameters.customParameters },

View File

@ -2,7 +2,7 @@ import ImageTag from './image-tag';
describe('ImageTag', () => {
const some = {
editorVersion: '2099.9.f9f9',
editorVersion: '2099.9.9f9',
targetPlatform: 'Test',
builderPlatform: '',
containerRegistryRepository: 'unityci/editor',
@ -28,11 +28,14 @@ describe('ImageTag', () => {
expect(image.targetPlatformSuffix).toStrictEqual(some.builderPlatform);
});
test.each(['2000.0.0f0', '2011.1.11f1'])('accepts %p version format', editorVersion => {
expect(
() => new ImageTag({ editorVersion, targetPlatform: some.targetPlatform }),
).not.toThrow();
});
test.each(['2000.0.0f0', '2011.1.11f1', '6000.0.0f1'])(
'accepts %p version format',
editorVersion => {
expect(
() => new ImageTag({ editorVersion, targetPlatform: some.targetPlatform }),
).not.toThrow();
},
);
test.each(['some version', '', 1])('throws for incorrect versions %p', editorVersion => {
const { targetPlatform } = some;
@ -43,7 +46,7 @@ describe('ImageTag', () => {
describe('toString', () => {
it('returns the correct version', () => {
const image = new ImageTag({
editorVersion: '2099.1.1111',
editorVersion: '2099.1.1111f1',
targetPlatform: some.targetPlatform,
containerRegistryRepository: 'unityci/editor',
containerRegistryImageVersion: '3',
@ -51,16 +54,16 @@ describe('ImageTag', () => {
switch (process.platform) {
case 'win32':
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111-3`);
expect(image.toString()).toStrictEqual(`${defaults.image}:windows-2099.1.1111f1-3`);
break;
case 'linux':
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111-3`);
expect(image.toString()).toStrictEqual(`${defaults.image}:ubuntu-2099.1.1111f1-3`);
break;
}
});
it('returns customImage if given', () => {
const image = new ImageTag({
editorVersion: '2099.1.1111',
editorVersion: '2099.1.1111f1',
targetPlatform: some.targetPlatform,
customImage: `${defaults.image}:2099.1.1111@347598437689743986`,
containerRegistryRepository: 'unityci/editor',

View File

@ -35,7 +35,7 @@ class ImageTag {
}
static get versionPattern() {
return /^20\d{2}\.\d\.\w{3,4}|3$/;
return /^\d+\.\d+\.\d+[a-z]\d+$/;
}
static get targetPlatformSuffixes() {

View File

@ -101,6 +101,9 @@ class Input {
const checkName = getInput('checkName') || 'Test Results';
const rawPackageMode = getInput('packageMode') || 'false';
let packageName = '';
const scopedRegistryUrl = getInput('scopedRegistryUrl') || '';
const rawScopes = getInput('registryScopes') || '';
let registryScopes: string[] = [];
const chownFilesTo = getInput('chownFilesTo') || '';
const dockerCpuLimit = getInput('dockerCpuLimit') || os.cpus().length.toString();
const bytesInMegabyte = 1024 * 1024;
@ -171,6 +174,16 @@ class Input {
packageName = this.getPackageNameFromPackageJson(projectPath);
this.verifyTestsFolderIsPresent(projectPath);
if (scopedRegistryUrl !== '') {
if (rawScopes === '') {
throw new Error(
'Scoped registry is set, but registryScopes is not set. registryScopes is required when using scopedRegistryUrl.',
);
}
registryScopes = rawScopes.split(',').map(scope => scope.trim());
}
}
if (runAsHostUser !== 'true' && runAsHostUser !== 'false') {
@ -219,6 +232,8 @@ class Input {
checkName,
packageMode,
packageName,
scopedRegistryUrl,
registryScopes,
chownFilesTo,
dockerCpuLimit,
dockerMemoryLimit,

View File

@ -22,9 +22,18 @@ const ResultsCheck = {
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);
try {
const content = fs.readFileSync(path.join(artifactsPath, filepath), 'utf8');
if (!content.includes('<test-run')) {
// noinspection ExceptionCaughtLocallyJS
throw new Error('File does not appear to be a NUnit XML file');
}
const fileData = await ResultsParser.parseResults(path.join(artifactsPath, filepath));
core.info(fileData.summary);
runs.push(fileData);
} catch (error: any) {
core.warning(`Failed to parse ${filepath}: ${error.message}`);
}
}),
);
@ -76,10 +85,12 @@ const ResultsCheck = {
const pullRequest = github.context.payload.pull_request;
const headSha = (pullRequest && pullRequest.head.sha) || github.context.sha;
// Check max length for https://github.com/game-ci/unity-test-runner/issues/214
const maxLength = 65_534;
if (output.length > maxLength) {
core.warning(`Output too long (${output.length}) truncating to ${maxLength}`);
output = output.slice(0, maxLength);
if (output.text.length > maxLength) {
core.warning(`Test details of ${output.text.length} surpass limit of ${maxLength}`);
output.text =
'Test details omitted from GitHub UI due to length. See console logs for details.';
}
core.info(`Posting results for ${headSha}`);

View File

@ -248,5 +248,13 @@ at Tests.SetupFailedTest.SetUp () [0x00000] in /github/workspace/unity-project/A
expect(result.path).toBe('/github/workspace/unity-project/Assets/Tests/SetupFailedTest.cs');
expect(result.line).toBe(10);
});
test('Debug.LogError annotation point', () => {
const result = ResultsParser.findAnnotationPoint(
`FMODUnity.RuntimeUtils:DebugLogError (string) (at Assets/Plugins/FMOD/src/RuntimeUtils.cs:580)`,
);
expect(result.path).toBe('Assets/Plugins/FMOD/src/RuntimeUtils.cs');
expect(result.line).toBe(580);
});
});
});

View File

@ -127,12 +127,13 @@ const ResultsParser = {
},
findAnnotationPoint(trace) {
const regex = /at(?: .* in)? ((?<path>[^:]+):(?<line>\d+))/;
// Find first entry with non-zero line number in stack trace
const items = trace.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/g);
const items = trace.match(new RegExp(regex, 'g'));
if (Array.isArray(items)) {
const result: { path: any; line: number }[] = [];
for (const item of items) {
const match = item.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/);
const match = item.match(regex);
const point = {
path: match ? match.groups.path : '',
line: match ? Number(match.groups.line) : 0,
@ -146,7 +147,7 @@ const ResultsParser = {
}
}
// If all entries have zero line number match fallback pattern
const match = trace.match(/at .* in ((?<path>[^:]+):(?<line>\d+))/);
const match = trace.match(regex);
return {
path: match ? match.groups.path : '',
line: match ? Number(match.groups.line) : 0,

View File

@ -11,6 +11,12 @@ describe('UnityVersionParser', () => {
m_EditorVersionWithRevision: 2022.3.7f1 (b16b3b16c7a0)`;
expect(UnityVersionParser.parse(projectVersionContents)).toBe('2022.3.7f1');
});
it('parses Unity 6000 and newer from ProjectVersion.txt', () => {
const projectVersionContents = `m_EditorVersion: 6000.0.0f1
m_EditorVersionWithRevision: 6000.0.0f1 (cb45f9cae8b7)`;
expect(UnityVersionParser.parse(projectVersionContents)).toBe('6000.0.0f1');
});
});
describe('read', () => {

View File

@ -2,16 +2,15 @@ import fs from 'fs';
import path from 'path';
const UnityVersionParser = {
get versionPattern() {
return /20\d{2}\.\d\.\w{3,4}|3/;
},
parse(projectVersionTxt) {
const matches = projectVersionTxt.match(UnityVersionParser.versionPattern);
if (!matches || matches.length === 0) {
throw new Error(`Failed to parse version from "${projectVersionTxt}".`);
const versionRegex = /m_EditorVersion: (\d+\.\d+\.\d+[A-Za-z]?\d+)/;
const matches = projectVersionTxt.match(versionRegex);
if (!matches || matches.length < 2) {
throw new Error(`Failed to extract version from "${projectVersionTxt}".`);
}
return matches[0];
return matches[1];
},
read(projectPath) {

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a62b511ba12825d4d9f992b4ed37a533
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e3a65787d84893340b9dc38af5b7c31f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,15 @@
using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(TimerComponent))]
public class LevelScriptEditor : Editor
{
public override void OnInspectorGUI()
{
TimerComponent myTarget = (TimerComponent)target;
EditorGUILayout.LabelField("Timer", myTarget.Timer.ToString());
}
}

View File

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

View File

@ -0,0 +1,16 @@
{
"name": "example.testpackage.Editor",
"rootNamespace": "",
"references": [
"example.testpackage.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 8223b1b52474b674a87c6113b6384f10
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e472ec5749e60ca4db87f10cec905d2c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 21861106477d38342a589fc525c4e0bb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6c6729c46a2a6594da2ce1182420ab81
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,18 @@
using System;
public class BasicCounter
{
public const int MaxCount = 10;
public BasicCounter(int count = 0)
{
Count = count;
}
public void Increment()
{
Count = Math.Min(MaxCount, Count + 1);
}
public int Count { get; private set; }
}

View File

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

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: 121f2ede62657a84082c012941df22d5
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,11 @@
fileFormatVersion: 2
guid: 563e4fb514abf6141b80ca1b71c08889
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,14 @@
{
"name": "example.testpackage.Runtime",
"rootNamespace": "",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b20629d7e725e1e449076020f132df2a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d0f3a0ff2938264498234e4aaa66cf5f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7644cfe4cdc2d0f4ebc7ab351323a576
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,38 @@
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class SampleEditModeTest
{
[Test]
public void TestIncrement()
{
// Given
var counter = new BasicCounter(0);
// When
counter.Increment();
// Then
Assert.AreEqual(1, counter.Count);
}
[Test]
public void TestMaxCount()
{
// Given
var counter = new BasicCounter(BasicCounter.MaxCount);
// When
counter.Increment();
// Then
Assert.AreEqual(BasicCounter.MaxCount, counter.Count);
}
}
}

View File

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

View File

@ -0,0 +1,25 @@
{
"name": "example.testpackage.EditorTests",
"rootNamespace": "",
"references": [
"UnityEngine.TestRunner",
"UnityEditor.TestRunner",
"example.testpackage.Editor",
"example.testpackage.Runtime"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b5712d2009ce3b34a8ca077667b16764
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b4f774583b1374a4abe450c7100726bd
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

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: b551b84934711564eb78aab8c16425ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,42 @@
using System.Collections;
using NUnit.Framework;
using UnityEngine.TestTools;
namespace Tests
{
public class SamplePlayModeTest
{
// A Test behaves as an ordinary method
[Test]
public void NewTestScriptSimplePasses()
{
// 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
// `yield return null;` to skip a frame.
[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,11 @@
fileFormatVersion: 2
guid: 4dbe2d2dc79550c4d81602bcf94a9824
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

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,11 @@
fileFormatVersion: 2
guid: 010121a56a70d60428dc89307eb77b54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,22 @@
{
"name": "example.testpackage.RuntimeTests",
"rootNamespace": "",
"references": [
"UnityEngine.TestRunner",
"UnityEditor.TestRunner",
"example.testpackage.Runtime"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 902aaaf7a59149243b2f4e38fc9f388e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
{
"name": "com.dependencyexample.testpackage",
"version": "0.0.1",
"displayName": "Test Package",
"description": "Test Package",
"unity": "2022.3",
"unityRelease": "7f1",
"dependencies": {
"com.cysharp.unitask": "2.5.3"
},
"keywords": [
"nothing"
],
"author": {
"name": "Example Author",
"email": "author@example.com",
"url": "example.com"
},
"type": "tool",
"hideInEditor": false
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4232dbd3889ab6a4393e846291288fb0
PackageManifestImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: