Remy
7 年前
当前提交
4c3a954c
共有 64 个文件被更改,包括 1456 次插入 和 10 次删除
-
20.gitignore
-
1build.py
-
5com.unity.testframework.graphics/.gitignore
-
12com.unity.testframework.graphics/.gitlab-ci.yml
-
10com.unity.testframework.graphics/.npmignore
-
12com.unity.testframework.graphics/CHANGELOG.md
-
7com.unity.testframework.graphics/CHANGELOG.md.meta
-
9com.unity.testframework.graphics/CONTRIBUTIONS.md
-
7com.unity.testframework.graphics/CONTRIBUTIONS.md.meta
-
8com.unity.testframework.graphics/Documentation.meta
-
68com.unity.testframework.graphics/Documentation/com.unity.testframework.graphics.md
-
7com.unity.testframework.graphics/Documentation/com.unity.testframework.graphics.md.meta
-
8com.unity.testframework.graphics/Editor.meta
-
15com.unity.testframework.graphics/Editor/CreateSceneListFileFromBuildSettings.cs
-
11com.unity.testframework.graphics/Editor/CreateSceneListFileFromBuildSettings.cs.meta
-
88com.unity.testframework.graphics/Editor/SetupGraphicsTestCases.cs
-
11com.unity.testframework.graphics/Editor/SetupGraphicsTestCases.cs.meta
-
16com.unity.testframework.graphics/Editor/UnityEditor.TestTools.Graphics.asmdef
-
7com.unity.testframework.graphics/Editor/UnityEditor.TestTools.Graphics.asmdef.meta
-
5com.unity.testframework.graphics/LICENSE.md
-
7com.unity.testframework.graphics/LICENSE.md.meta
-
26com.unity.testframework.graphics/QAReport.md
-
7com.unity.testframework.graphics/QAReport.md.meta
-
13com.unity.testframework.graphics/README.md
-
7com.unity.testframework.graphics/README.md.meta
-
8com.unity.testframework.graphics/Runtime.meta
-
8com.unity.testframework.graphics/Tests.meta
-
8com.unity.testframework.graphics/Tests/Runtime.meta
-
69com.unity.testframework.graphics/Tests/Runtime/ImageAssertTests.cs
-
11com.unity.testframework.graphics/Tests/Runtime/ImageAssertTests.cs.meta
-
14com.unity.testframework.graphics/Tests/Runtime/UnityEngine.TestTools.Graphics.Tests.asmdef
-
7com.unity.testframework.graphics/Tests/Runtime/UnityEngine.TestTools.Graphics.Tests.asmdef.meta
-
10com.unity.testframework.graphics/package.json
-
7com.unity.testframework.graphics/package.json.meta
-
3com.unity.testframework.graphics/Runtime/AssemblyInfo.cs
-
11com.unity.testframework.graphics/Runtime/AssemblyInfo.cs.meta
-
95com.unity.testframework.graphics/Runtime/EditorGraphicsTestCaseProvider.cs
-
11com.unity.testframework.graphics/Runtime/EditorGraphicsTestCaseProvider.cs.meta
-
29com.unity.testframework.graphics/Runtime/GraphicsTestCase.cs
-
11com.unity.testframework.graphics/Runtime/GraphicsTestCase.cs.meta
-
7com.unity.testframework.graphics/Runtime/GraphicsTestSettings.cs
-
11com.unity.testframework.graphics/Runtime/GraphicsTestSettings.cs.meta
-
34com.unity.testframework.graphics/Runtime/IGraphicsTestCaseProvider.cs
-
11com.unity.testframework.graphics/Runtime/IGraphicsTestCaseProvider.cs.meta
-
224com.unity.testframework.graphics/Runtime/ImageAssert.cs
-
11com.unity.testframework.graphics/Runtime/ImageAssert.cs.meta
-
42com.unity.testframework.graphics/Runtime/ImageComparisonSettings.cs
-
11com.unity.testframework.graphics/Runtime/ImageComparisonSettings.cs.meta
-
124com.unity.testframework.graphics/Runtime/ResultsUtility.cs
-
11com.unity.testframework.graphics/Runtime/ResultsUtility.cs.meta
-
58com.unity.testframework.graphics/Runtime/RuntimeGraphicsTestCaseProvider.cs
-
11com.unity.testframework.graphics/Runtime/RuntimeGraphicsTestCaseProvider.cs.meta
-
10com.unity.testframework.graphics/Runtime/UnityEngine.TestTools.Graphics.asmdef
-
7com.unity.testframework.graphics/Runtime/UnityEngine.TestTools.Graphics.asmdef.meta
-
65com.unity.testframework.graphics/Runtime/UseGraphicsTestCasesAttribute.cs
-
11com.unity.testframework.graphics/Runtime/UseGraphicsTestCasesAttribute.cs.meta
-
11com.unity.testframework.graphics/Runtime/Utils.cs.meta
-
118com.unity.testframework.graphics/Runtime/Utils.cs
|
|||
artifacts/** |
|||
build/** |
|||
Documentation/ApiDocs/** |
|||
.DS_Store |
|||
.npmrc |
|
|||
image: node:6.10.0 |
|||
|
|||
stages: |
|||
- push_to_packman_staging |
|||
|
|||
push_to_packman_staging: |
|||
stage: push_to_packman_staging |
|||
only: |
|||
- tags |
|||
script: |
|||
- curl -u $USER_NAME:$API_KEY https://staging-packages.unity.com/auth > .npmrc |
|||
- npm publish |
|
|||
artifacts/** |
|||
build/** |
|||
Documentation/ApiDocs/** |
|||
.DS_Store |
|||
.npmrc |
|||
.npmignore |
|||
.gitignore |
|||
QAReport.md |
|||
QAReport.md.meta |
|||
.gitlab-ci.yml |
|
|||
# Changelog |
|||
All notable changes to this package will be documented in this file. |
|||
|
|||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) |
|||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). |
|||
|
|||
## [0.1.0] - 2018-05-04 |
|||
|
|||
### This is the first release of *Unity Package com.unity.testframework.graphics*. |
|||
|
|||
* ImageAssert for comparing images |
|||
* Automatic management of reference images and test case generation |
|
|||
fileFormatVersion: 2 |
|||
guid: cd04314c81180ae40bf3b7b030d390c5 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# Contributions |
|||
|
|||
## If you are interested in contributing, here are some ground rules: |
|||
* ... Define guidelines & rules for what contributors need to know to successfully make Pull requests against your repo ... |
|||
|
|||
## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/licenses/Unity_Contribution_Agreement) |
|||
By making a pull request, you are confirming agreement to the terms and conditions of the UCA, including that your Contributions are your original creation and that you have complete right and authority to make your Contributions. |
|||
|
|||
## Once you have a change ready following these ground rules. Simply make a pull request in Github |
|
|||
fileFormatVersion: 2 |
|||
guid: 55bc73776cee17b4c9292ea7e6a53de8 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 40c3f3b81e020124a9bbf1c1318b9929 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# About the Graphics Test Framework |
|||
|
|||
Use the Graphics Test Framework package to create automated tests for rendering outputs - tests that render an image and compare it to a 'known good' reference image. |
|||
|
|||
# Installing the Graphics Test Framework |
|||
|
|||
To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html). |
|||
|
|||
<a name="UsingPackageName"></a> |
|||
# Using the Graphics Test Framework |
|||
|
|||
There are two main components to the framework: |
|||
|
|||
## ImageAssert.AreEqual() |
|||
|
|||
This is a new assertion method that you can use in your tests to check two images for equality. There is also an overload that takes a camera instead of an image, and automatically captures the camera output for you and compares that. |
|||
|
|||
An optional third parameter allows you to configure the sensitivity of the check. Even when everything else is the same, it's common for there to be small differences between images due to changes in hardware, driver version, and so on. You can use this third parameter to set a threshold for how different pixels need to be before they are counted, and you can set a threshold for how different the overall image needs to be before the assertion will fail. |
|||
|
|||
## Automatic test case management |
|||
|
|||
The framework can automatically generate test cases based on the scenes in the project and manage reference images for them. |
|||
|
|||
Using this feature requires a little bit of setup. Firstly, on your test method itself, you should add two attributes, `[PrebuildSetup("SetupGraphicsTestCases")]` and `[UseGraphicsTestCases]`, like this: |
|||
|
|||
``` |
|||
[UnityTest] |
|||
[PrebuildSetup("SetupGraphicsTestCases")] |
|||
[UseGraphicsTestCases] |
|||
public IEnumerator DoTest(GraphicsTestCase testCase) |
|||
{ |
|||
|
|||
} |
|||
``` |
|||
|
|||
Your test method should also take a single `GraphicsTestCase` parameter. You will also usually want to use `[UnityTest]` and return `IEnumerator`, rather than using `[Test]` and returning `void`, because usually you will want to load a new scene in your test, and this requires yielding one frame for the load to complete. |
|||
|
|||
With this in place, any scene added to the build systems will result in a test case for the scene being generated in the test runner. |
|||
|
|||
### Reference images |
|||
|
|||
The simplest way to set up your initial reference images is to allow the tests to generate them. Once you have created your tests and added them to the Build Settings, you can either run the tests in-Editor to generate images using the Editor renderer, or you can exit Unity and run the tests on-device from the commandline. |
|||
|
|||
When the run completes, you should be able to obtain a TestResults.xml file for the run. As well as reporting that the tests failed (because they have no reference images), the TestResults.xml file will also contain encoded versions of the rendered images. |
|||
|
|||
In Unity, go to `Tests -> Extract images from TestResults.xml...` and select the TestResults.xml file created by the run. The framework will process the images in the test results and put them into a folder called "ActualImages" in the root of your Assets folder, where you can inspect them to make sure they look correct. |
|||
|
|||
Once you're happy that the images look correct, you should rename the `ActualImages` folder to `ReferenceImages` (or merge the images into the existing ReferenceImages folder, if there is one). Run the tests again and you should see that they now use the reference images successfully! |
|||
|
|||
By default, reference images will be set up in a three-level hierarchy of folders: `ColorSpace/Platform/GraphicsAPI`. If you want to use the same reference image across multiple graphics APIs, you can put it directly into the `ColorSpace/Platform` folder. |
|||
|
|||
# Technical details |
|||
## Requirements |
|||
|
|||
This version of the Graphics Test Framework is compatible with the following versions of the Unity Editor: |
|||
|
|||
* 2018.1 and later (recommended) |
|||
|
|||
## Known limitations |
|||
|
|||
Graphics Test Framework version 0.1.0 includes the following known limitations: |
|||
|
|||
* Actual/Diff images cannot be retrieved from test results when running in-player tests from the Unity Test Runner interactively. The commandline must be used instead. |
|||
|
|||
## Document revision history |
|||
|Date|Reason| |
|||
|---|---| |
|||
|May 10, 2018|Document created. Matches package version 0.1| |
|
|||
fileFormatVersion: 2 |
|||
guid: 03d48d8ca28e87a48a9d0314d7ac63b6 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: eb1b22e9f00ada6419bc30328a2c466a |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.IO; |
|||
using System.Linq; |
|||
using UnityEngine.TestTools; |
|||
|
|||
namespace UnityEditor.TestTools.Graphics |
|||
{ |
|||
internal class CreateSceneListFileFromBuildSettings : IPrebuildSetup |
|||
{ |
|||
public void Setup() |
|||
{ |
|||
File.WriteAllLines("Assets/StreamingAssets/SceneList.txt", |
|||
EditorBuildSettings.scenes.Select(s => s.path).ToArray()); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e02dcad3481a66646ab624b2c38ab235 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
using UnityEngine.Rendering; |
|||
using UnityEngine.TestTools; |
|||
|
|||
namespace UnityEditor.TestTools.Graphics |
|||
{ |
|||
/// <summary>
|
|||
/// Test framework prebuild step to collect reference images for the current test run and prepare them for use in the
|
|||
/// player.
|
|||
/// </summary>
|
|||
public class SetupGraphicsTestCases : IPrebuildSetup |
|||
{ |
|||
private static bool IsBuildingForEditorPlaymode |
|||
{ |
|||
get |
|||
{ |
|||
var playmodeLauncher = |
|||
typeof(UnityEditor.TestTools.RequirePlatformSupportAttribute).Assembly.GetType( |
|||
"UnityEditor.TestTools.TestRunner.PlaymodeLauncher"); |
|||
var isRunningField = playmodeLauncher.GetField("IsRunning"); |
|||
|
|||
return (bool)isRunningField.GetValue(null); |
|||
} |
|||
} |
|||
|
|||
public void Setup() |
|||
{ |
|||
ColorSpace colorSpace; |
|||
BuildTarget buildPlatform; |
|||
RuntimePlatform runtimePlatform; |
|||
GraphicsDeviceType[] graphicsDevices; |
|||
|
|||
// Figure out if we're preparing to run in Editor playmode, or if we're building to run outside the Editor
|
|||
if (IsBuildingForEditorPlaymode) |
|||
{ |
|||
colorSpace = QualitySettings.activeColorSpace; |
|||
buildPlatform = BuildTarget.NoTarget; |
|||
runtimePlatform = Application.platform; |
|||
graphicsDevices = new[] {SystemInfo.graphicsDeviceType}; |
|||
} |
|||
else |
|||
{ |
|||
buildPlatform = EditorUserBuildSettings.activeBuildTarget; |
|||
runtimePlatform = Utils.BuildTargetToRuntimePlatform(buildPlatform); |
|||
colorSpace = PlayerSettings.colorSpace; |
|||
graphicsDevices = PlayerSettings.GetGraphicsAPIs(buildPlatform); |
|||
} |
|||
|
|||
var bundleBuilds = new List<AssetBundleBuild>(); |
|||
|
|||
foreach (var api in graphicsDevices) |
|||
{ |
|||
var images = EditorGraphicsTestCaseProvider.CollectReferenceImagePathsFor(colorSpace, runtimePlatform, api); |
|||
|
|||
Utils.SetupReferenceImageImportSettings(images.Values); |
|||
|
|||
if (buildPlatform == BuildTarget.NoTarget) |
|||
continue; |
|||
|
|||
bundleBuilds.Add(new AssetBundleBuild |
|||
{ |
|||
assetBundleName = string.Format("referenceimages-{0}-{1}-{2}", colorSpace, runtimePlatform, api), |
|||
addressableNames = images.Keys.ToArray(), |
|||
assetNames = images.Values.ToArray() |
|||
}); |
|||
} |
|||
|
|||
if (bundleBuilds.Count > 0) |
|||
{ |
|||
if (!Directory.Exists("Assets/StreamingAssets")) |
|||
Directory.CreateDirectory("Assets/StreamingAssets"); |
|||
|
|||
foreach (var bundle in bundleBuilds) |
|||
{ |
|||
BuildPipeline.BuildAssetBundles("Assets/StreamingAssets", new [] { bundle }, BuildAssetBundleOptions.None, |
|||
buildPlatform); |
|||
} |
|||
} |
|||
|
|||
if (!IsBuildingForEditorPlaymode) |
|||
new CreateSceneListFileFromBuildSettings().Setup(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b1376c1a2d73304458dee9c0d11fa244 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
{ |
|||
"name": "UnityEditor.TestTools.Graphics", |
|||
"references": [ |
|||
"UnityEngine.TestTools.Graphics" |
|||
], |
|||
"optionalUnityReferences": [ |
|||
"TestAssemblies" |
|||
], |
|||
"includePlatforms": [ |
|||
"Editor" |
|||
], |
|||
"excludePlatforms": [], |
|||
"allowUnsafeCode": false, |
|||
"overrideReferences": false, |
|||
"precompiledReferences": [] |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: e18141520846dcc44b725b2f74e91229 |
|||
AssemblyDefinitionImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
com.unity.testframework.graphics copyright © 2018 Unity Technologies ApS |
|||
|
|||
Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). |
|||
|
|||
Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. |
|
|||
fileFormatVersion: 2 |
|||
guid: e3f03ad65feb1c145911fb05f2bd3df2 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# Quality Report |
|||
Use this file to outline the test strategy for this package. |
|||
|
|||
## Version tested: [*package version*] |
|||
|
|||
## QA Owner: [*Add Name*] |
|||
## UX Owner: [*Add Name*] |
|||
|
|||
## Test strategy |
|||
*Use this section to describe how this feature was tested.* |
|||
* A link to the Test Plan (Test Rails, other) |
|||
* Results from the package's editor and runtime test suite. |
|||
* Link to automated test results (if any) |
|||
* Manual test Results, [here's an example](https://docs.google.com/spreadsheets/d/12A76U5Gf969w10KL4Ik0wC1oFIBDUoRrqIvQgD18TFo/edit#gid=0) |
|||
* Scenario test week outcome |
|||
* etc. |
|||
|
|||
## Package Status |
|||
Use this section to describe: |
|||
* UX status/evaluation results |
|||
* package stability |
|||
* known bugs, issues |
|||
* performance metrics, |
|||
* etc |
|||
|
|||
In other words, a general feeling on the health of this package. |
|
|||
fileFormatVersion: 2 |
|||
guid: f1ed2c05113675d469b2f8c8e7a2fab6 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# Graphics Tests Framework |
|||
|
|||
This package provides a foundation for writing tests for Graphics features in Unity projects. |
|||
|
|||
Currently it contains: |
|||
|
|||
* ImageAssert, for doing image renders and comparisons with reference images |
|||
* Automatic collection and deployment of reference images |
|||
* Automatic generation of tests from scenes in the project |
|||
|
|||
It's currently a bit rough, but as improvments to Unity's test framework are made we should be able to make it nicer, as well as expand the functionality it offers. |
|||
|
|||
See [the Documentation](Documentation/com.unity.testframework.graphics.md) for more information. |
|
|||
fileFormatVersion: 2 |
|||
guid: a384776e66fd10945a4f895de0a9d592 |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: a9f5808abb9428c4f8cd4b9f3fd8c4b7 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 4694165483353794497d1849029e2c06 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 8792dcc714120a04493082afd2214c3d |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using NUnit.Framework; |
|||
|
|||
namespace UnityEngine.TestTools.Graphics.Tests |
|||
{ |
|||
public class ImageAssertTests |
|||
{ |
|||
[Test] |
|||
public void AreEqual_WithNullCamera_ThrowsArgumentNullException() |
|||
{ |
|||
Assert.That(() => ImageAssert.AreEqual(new Texture2D(1, 1), (Camera)null), Throws.ArgumentNullException); |
|||
} |
|||
|
|||
[Test] |
|||
public void AreEqual_WithNullActualImage_ThrowsArgumentNullException() |
|||
{ |
|||
Assert.That(() => ImageAssert.AreEqual(new Texture2D(1, 1), (Texture2D)null), Throws.ArgumentNullException); |
|||
} |
|||
|
|||
[Test] |
|||
public void AreEqual_WithIdenticalImage_Succeeds() |
|||
{ |
|||
var testImage = new Texture2D(64, 64); |
|||
var pixels = new Color32[64 * 64]; |
|||
for (int i = 0; i < pixels.Length; ++i) |
|||
pixels[i] = i % 2 == 1 ? Color.black : Color.white; |
|||
testImage.SetPixels32(pixels); |
|||
testImage.Apply(false); |
|||
|
|||
Assert.That(() => ImageAssert.AreEqual(testImage, testImage), Throws.Nothing); |
|||
} |
|||
|
|||
[Test] |
|||
public void AreEqual_WithTotallyDifferentImages_ThrowsAssertionException() |
|||
{ |
|||
Assert.That(() => ImageAssert.AreEqual(Texture2D.whiteTexture, Texture2D.blackTexture), Throws.InstanceOf<AssertionException>()); |
|||
} |
|||
|
|||
[Test] |
|||
public void AreEqual_WithSlightlyDifferentImages_SucceedsWithAppropriateTolerance() |
|||
{ |
|||
var expected = Texture2D.blackTexture; |
|||
var actual = new Texture2D(expected.width, expected.height); |
|||
var pixels = new Color32[actual.width * actual.height]; |
|||
for (int i = 0; i < pixels.Length; ++i) |
|||
pixels[i] = new Color32(0x01, 0x01, 0x01, 0x01); |
|||
actual.SetPixels32(pixels); |
|||
actual.Apply(false); |
|||
|
|||
Assert.That(() => ImageAssert.AreEqual(expected, actual), Throws.InstanceOf<AssertionException>()); |
|||
Assert.That(() => ImageAssert.AreEqual(expected, actual, new ImageComparisonSettings { PerPixelCorrectnessThreshold = 0.005f }), Throws.Nothing); |
|||
} |
|||
|
|||
[Test] |
|||
public void AreEqual_WidthDifferentSizeImages_ThrowsAssertionException() |
|||
{ |
|||
var c = Color.black; |
|||
|
|||
var expected = new Texture2D(1, 1); |
|||
expected.SetPixels(new [] { c }); |
|||
expected.Apply(false); |
|||
|
|||
var actual = new Texture2D(1, 2); |
|||
actual.SetPixels(new [] { c, c }); |
|||
actual.Apply(false); |
|||
|
|||
Assert.That(() => ImageAssert.AreEqual(expected, actual), Throws.InstanceOf<AssertionException>()); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6ef35499de2abc64baf4327fb701ddfc |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
{ |
|||
"name": "UnityEngine.TestTools.Graphics.Tests", |
|||
"references": [ |
|||
"UnityEngine.TestTools.Graphics" |
|||
], |
|||
"optionalUnityReferences": [ |
|||
"TestAssemblies" |
|||
], |
|||
"includePlatforms": [], |
|||
"excludePlatforms": [], |
|||
"allowUnsafeCode": false, |
|||
"overrideReferences": false, |
|||
"precompiledReferences": [] |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d38aa57151b4a464c9be60e1149213a6 |
|||
AssemblyDefinitionImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
{ |
|||
"name": "com.unity.testframework.graphics", |
|||
"displayName":"Graphics Tests Framework", |
|||
"version": "0.1.0-preview", |
|||
"unity": "2018.2", |
|||
"description": "Provides test framework helpers for writing tests for graphics code, such as image comparison assertions and automatic management of reference images.", |
|||
"keywords": ["qa", "test", "testing", "tests", "graphics"], |
|||
"dependencies": { |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3b04d151afeee394391283a0ef3a1b4b |
|||
TextScriptImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
[assembly: InternalsVisibleTo("UnityEditor.TestTools.Graphics")] |
|
|||
fileFormatVersion: 2 |
|||
guid: f267eabe7863252429325ab8e9ff384b |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#if UNITY_EDITOR
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using UnityEngine.TestTools.Graphics; |
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEditor.TestTools.Graphics |
|||
{ |
|||
internal class EditorGraphicsTestCaseProvider : IGraphicsTestCaseProvider |
|||
{ |
|||
public ColorSpace ColorSpace |
|||
{ |
|||
get |
|||
{ |
|||
return QualitySettings.activeColorSpace; |
|||
} |
|||
} |
|||
|
|||
public RuntimePlatform Platform |
|||
{ |
|||
get |
|||
{ |
|||
return Application.platform; |
|||
} |
|||
} |
|||
|
|||
public GraphicsDeviceType GraphicsDevice |
|||
{ |
|||
get |
|||
{ |
|||
return SystemInfo.graphicsDeviceType; |
|||
} |
|||
} |
|||
|
|||
|
|||
public IEnumerable<GraphicsTestCase> GetTestCases() |
|||
{ |
|||
var allImages = CollectReferenceImagePathsFor(QualitySettings.activeColorSpace, Application.platform, |
|||
SystemInfo.graphicsDeviceType); |
|||
|
|||
foreach (var scenePath in EditorBuildSettings.scenes.Select(s => s.path)) |
|||
{ |
|||
Texture2D referenceImage = null; |
|||
|
|||
string imagePath; |
|||
if (allImages.TryGetValue(Path.GetFileNameWithoutExtension(scenePath), out imagePath)) |
|||
{ |
|||
referenceImage = AssetDatabase.LoadAssetAtPath<Texture2D>(imagePath); |
|||
} |
|||
|
|||
yield return new GraphicsTestCase(scenePath, referenceImage); |
|||
} |
|||
} |
|||
|
|||
public const string ReferenceImagesRoot = "Assets/ReferenceImages"; |
|||
|
|||
public static Dictionary<string, string> CollectReferenceImagePathsFor(ColorSpace colorSpace, RuntimePlatform runtimePlatform, |
|||
GraphicsDeviceType graphicsApi) |
|||
{ |
|||
var result = new Dictionary<string, string>(); |
|||
|
|||
if (!Directory.Exists(ReferenceImagesRoot)) |
|||
return result; |
|||
|
|||
var fullPathPrefix = string.Format("{0}/{1}/{2}/{3}/", ReferenceImagesRoot, colorSpace, runtimePlatform, graphicsApi); |
|||
|
|||
foreach (var assetPath in AssetDatabase.GetAllAssetPaths() |
|||
.Where(p => p.StartsWith(ReferenceImagesRoot, StringComparison.OrdinalIgnoreCase)) |
|||
.Where(p => fullPathPrefix.StartsWith(Path.GetDirectoryName(p))) |
|||
.OrderBy(p => p.Count(ch => ch == '/'))) |
|||
{ |
|||
// Skip directories
|
|||
if (!File.Exists(assetPath)) |
|||
continue; |
|||
|
|||
var fileName = Path.GetFileNameWithoutExtension(assetPath); |
|||
if (fileName == null) |
|||
continue; |
|||
|
|||
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath); |
|||
if (!texture) |
|||
continue; |
|||
|
|||
result[fileName] = assetPath; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
#endif
|
|
|||
fileFormatVersion: 2 |
|||
guid: 968c885912a3e9d49be2783ccea03cce |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEngine.TestTools.Graphics |
|||
{ |
|||
/// <summary>
|
|||
/// Represents one automatically-generated graphics test case.
|
|||
/// </summary>
|
|||
public class GraphicsTestCase |
|||
{ |
|||
private readonly string _scenePath; |
|||
private readonly Texture2D _referenceImage; |
|||
|
|||
public GraphicsTestCase(string scenePath, Texture2D referenceImage) |
|||
{ |
|||
_scenePath = scenePath; |
|||
_referenceImage = referenceImage; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The path to the scene to be used for this test case.
|
|||
/// </summary>
|
|||
public string ScenePath { get { return _scenePath; } } |
|||
|
|||
/// <summary>
|
|||
/// The reference image that represents the expected output for this test case.
|
|||
/// </summary>
|
|||
public Texture2D ReferenceImage { get { return _referenceImage; } } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2a7ae2407446ad8408658c99d513dd3f |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
namespace UnityEngine.TestTools.Graphics |
|||
{ |
|||
public class GraphicsTestSettings : MonoBehaviour |
|||
{ |
|||
public ImageComparisonSettings ImageComparisonSettings; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 20f198885badb1f4fa1e65869995ff82 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.TestTools.Graphics |
|||
{ |
|||
/// <summary>
|
|||
/// Describes an object that can provide GraphicsTestCase objects. THe framework provides different implementations
|
|||
/// for the Editor (which loads reference images directly from the Asset Database) and Players (which use the
|
|||
/// pre-built AssetBundle).
|
|||
/// </summary>
|
|||
public interface IGraphicsTestCaseProvider |
|||
{ |
|||
/// <summary>
|
|||
/// Retrieve the list of test cases to generate tests for.
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
IEnumerable<GraphicsTestCase> GetTestCases(); |
|||
|
|||
/// <summary>
|
|||
/// The color space that the test cases are for.
|
|||
/// </summary>
|
|||
ColorSpace ColorSpace { get; } |
|||
|
|||
/// <summary>
|
|||
/// The platform that the test cases are for.
|
|||
/// </summary>
|
|||
RuntimePlatform Platform { get; } |
|||
|
|||
/// <summary>
|
|||
/// The graphics device type that the test cases are for.
|
|||
/// </summary>
|
|||
GraphicsDeviceType GraphicsDevice { get; } |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 8b30b20945c243d4485ee181d069119b |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Linq; |
|||
using NUnit.Framework; |
|||
using Unity.Collections; |
|||
using Unity.Jobs; |
|||
|
|||
namespace UnityEngine.TestTools.Graphics |
|||
{ |
|||
/// <summary>
|
|||
/// Provides test assertion helpers for working with images.
|
|||
/// </summary>
|
|||
public class ImageAssert |
|||
{ |
|||
const int k_BatchSize = 1024; |
|||
|
|||
/// <summary>
|
|||
/// Render an image from the given camera and compare it to the reference image.
|
|||
/// </summary>
|
|||
/// <param name="expected">The expected image that should be rendered by the camera.</param>
|
|||
/// <param name="camera">The camera to render from.</param>
|
|||
/// <param name="settings">Optional settings that control how the image comparison is performed. Can be null, in which case the rendered image is required to be exactly identical to the reference.</param>
|
|||
public static void AreEqual(Texture2D expected, Camera camera, ImageComparisonSettings settings = null) |
|||
{ |
|||
if (!camera) |
|||
throw new ArgumentNullException("camera"); |
|||
|
|||
if (settings == null) |
|||
settings = new ImageComparisonSettings(); |
|||
|
|||
int width = settings.TargetWidth; |
|||
int height = settings.TargetHeight; |
|||
var format = expected != null ? expected.format : TextureFormat.ARGB32; |
|||
|
|||
var rt = RenderTexture.GetTemporary(width, height, 24); |
|||
Texture2D actual = null; |
|||
try |
|||
{ |
|||
camera.targetTexture = rt; |
|||
camera.Render(); |
|||
camera.targetTexture = null; |
|||
|
|||
actual = new Texture2D(width, height, format, false); |
|||
RenderTexture.active = rt; |
|||
actual.ReadPixels(new Rect(0, 0, width, height), 0, 0); |
|||
RenderTexture.active = null; |
|||
|
|||
actual.Apply(); |
|||
|
|||
AreEqual(expected, actual, settings); |
|||
} |
|||
finally |
|||
{ |
|||
RenderTexture.ReleaseTemporary(rt); |
|||
if (actual != null) |
|||
UnityEngine.Object.Destroy(actual); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares an image to a 'reference' image to see if it looks correct.
|
|||
/// </summary>
|
|||
/// <param name="expected">What the image is supposed to look like.</param>
|
|||
/// <param name="actual">What the image actually looks like.</param>
|
|||
/// <param name="settings">Optional settings that control how the comparison is performed. Can be null, in which case the images are required to be exactly identical.</param>
|
|||
public static void AreEqual(Texture2D expected, Texture2D actual, ImageComparisonSettings settings = null) |
|||
{ |
|||
if (actual == null) |
|||
throw new ArgumentNullException("actual"); |
|||
|
|||
try |
|||
{ |
|||
Assert.That(expected, Is.Not.Null, "No reference image was provided."); |
|||
|
|||
Assert.That(actual.width, Is.EqualTo(expected.width), |
|||
"The expected image had width {0}px, but the actual image had width {1}px.", expected.width, |
|||
actual.width); |
|||
Assert.That(actual.height, Is.EqualTo(expected.height), |
|||
"The expected image had height {0}px, but the actual image had height {1}px.", expected.height, |
|||
actual.height); |
|||
|
|||
Assert.That(actual.format, Is.EqualTo(expected.format), |
|||
"The expected image had format {0} but the actual image had format {1}.", expected.format, |
|||
actual.format); |
|||
|
|||
using (var expectedPixels = new NativeArray<Color32>(expected.GetPixels32(0), Allocator.Temp)) |
|||
using (var actualPixels = new NativeArray<Color32>(actual.GetPixels32(0), Allocator.Temp)) |
|||
using (var diffPixels = new NativeArray<Color32>(expectedPixels.Length, Allocator.Temp)) |
|||
using (var sumOverThreshold = new NativeArray<float>(Mathf.CeilToInt(expectedPixels.Length / (float)k_BatchSize), Allocator.Temp)) |
|||
{ |
|||
if (settings == null) |
|||
settings = new ImageComparisonSettings(); |
|||
|
|||
new ComputeDiffJob |
|||
{ |
|||
expected = expectedPixels, |
|||
actual = actualPixels, |
|||
diff = diffPixels, |
|||
sumOverThreshold = sumOverThreshold, |
|||
pixelThreshold = settings.PerPixelCorrectnessThreshold |
|||
}.Schedule(expectedPixels.Length, k_BatchSize).Complete(); |
|||
|
|||
float averageDeltaE = sumOverThreshold.Sum() / (expected.width * expected.height); |
|||
|
|||
try |
|||
{ |
|||
Assert.That(averageDeltaE, Is.LessThanOrEqualTo(settings.AverageCorrectnessThreshold)); |
|||
} |
|||
catch (AssertionException) |
|||
{ |
|||
var diffImage = new Texture2D(expected.width, expected.height, TextureFormat.RGB24, false); |
|||
var diffPixelsArray = new Color32[expected.width * expected.height]; |
|||
diffPixels.CopyTo(diffPixelsArray); |
|||
diffImage.SetPixels32(diffPixelsArray, 0); |
|||
diffImage.Apply(false); |
|||
|
|||
TestContext.CurrentContext.Test.Properties.Set("DiffImage", Convert.ToBase64String(diffImage.EncodeToPNG())); |
|||
throw; |
|||
} |
|||
} |
|||
} |
|||
catch (AssertionException) |
|||
{ |
|||
TestContext.CurrentContext.Test.Properties.Set("Image", Convert.ToBase64String(actual.EncodeToPNG())); |
|||
throw; |
|||
} |
|||
} |
|||
|
|||
struct ComputeDiffJob : IJobParallelFor |
|||
{ |
|||
[ReadOnly] public NativeArray<Color32> expected; |
|||
[ReadOnly] public NativeArray<Color32> actual; |
|||
public NativeArray<Color32> diff; |
|||
public float pixelThreshold; |
|||
|
|||
[NativeDisableParallelForRestriction] |
|||
public NativeArray<float> sumOverThreshold; |
|||
|
|||
public void Execute(int index) |
|||
{ |
|||
var exp = RGBtoJAB(expected[index]); |
|||
var act = RGBtoJAB(actual[index]); |
|||
|
|||
float deltaE = JABDeltaE(exp, act); |
|||
float overThreshold = Mathf.Max(0f, deltaE - pixelThreshold); |
|||
int batch = index / k_BatchSize; |
|||
sumOverThreshold[batch] = sumOverThreshold[batch] + overThreshold; |
|||
|
|||
// deltaE is linear, convert it to sRGB for easier debugging
|
|||
deltaE = Mathf.LinearToGammaSpace(deltaE); |
|||
var colorResult = new Color(deltaE, deltaE, deltaE, 1f); |
|||
diff[index] = colorResult; |
|||
} |
|||
} |
|||
|
|||
// Linear RGB to XYZ using D65 ref. white
|
|||
static Vector3 RGBtoXYZ(Color color) |
|||
{ |
|||
float x = color.r * 0.4124564f + color.g * 0.3575761f + color.b * 0.1804375f; |
|||
float y = color.r * 0.2126729f + color.g * 0.7151522f + color.b * 0.0721750f; |
|||
float z = color.r * 0.0193339f + color.g * 0.1191920f + color.b * 0.9503041f; |
|||
return new Vector3(x * 100f, y * 100f, z * 100f); |
|||
} |
|||
|
|||
// sRGB to JzAzBz
|
|||
// https://www.osapublishing.org/oe/fulltext.cfm?uri=oe-25-13-15131&id=368272
|
|||
static Vector3 RGBtoJAB(Color color) |
|||
{ |
|||
var xyz = RGBtoXYZ(color.linear); |
|||
|
|||
const float kB = 1.15f; |
|||
const float kG = 0.66f; |
|||
const float kC1 = 0.8359375f; // 3424 / 2^12
|
|||
const float kC2 = 18.8515625f; // 2413 / 2^7
|
|||
const float kC3 = 18.6875f; // 2392 / 2^7
|
|||
const float kN = 0.15930175781f; // 2610 / 2^14
|
|||
const float kP = 134.034375f; // 1.7 * 2523 / 2^5
|
|||
const float kD = -0.56f; |
|||
const float kD0 = 1.6295499532821566E-11f; |
|||
|
|||
float x2 = kB * xyz.x - (kB - 1f) * xyz.z; |
|||
float y2 = kG * xyz.y - (kG - 1f) * xyz.x; |
|||
|
|||
float l = 0.41478372f * x2 + 0.579999f * y2 + 0.0146480f * xyz.z; |
|||
float m = -0.2015100f * x2 + 1.120649f * y2 + 0.0531008f * xyz.z; |
|||
float s = -0.0166008f * x2 + 0.264800f * y2 + 0.6684799f * xyz.z; |
|||
l = Mathf.Pow(l / 10000f, kN); |
|||
m = Mathf.Pow(m / 10000f, kN); |
|||
s = Mathf.Pow(s / 10000f, kN); |
|||
|
|||
// Can we switch to unity.mathematics yet?
|
|||
var lms = new Vector3(l, m, s); |
|||
var a = new Vector3(kC1, kC1, kC1) + kC2 * lms; |
|||
var b = Vector3.one + kC3 * lms; |
|||
var tmp = new Vector3(a.x / b.x, a.y / b.y, a.z / b.z); |
|||
|
|||
lms.x = Mathf.Pow(tmp.x, kP); |
|||
lms.y = Mathf.Pow(tmp.y, kP); |
|||
lms.z = Mathf.Pow(tmp.z, kP); |
|||
|
|||
var jab = new Vector3( |
|||
0.5f * lms.x + 0.5f * lms.y, |
|||
3.524000f * lms.x + -4.066708f * lms.y + 0.542708f * lms.z, |
|||
0.199076f * lms.x + 1.096799f * lms.y + -1.295875f * lms.z |
|||
); |
|||
|
|||
jab.x = ((1f + kD) * jab.x) / (1f + kD * jab.x) - kD0; |
|||
|
|||
return jab; |
|||
} |
|||
|
|||
static float JABDeltaE(Vector3 v1, Vector3 v2) |
|||
{ |
|||
float c1 = Mathf.Sqrt(v1.y * v1.y + v1.z * v1.z); |
|||
float c2 = Mathf.Sqrt(v2.y * v2.y + v2.z * v2.z); |
|||
|
|||
float h1 = Mathf.Atan(v1.z / v1.y); |
|||
float h2 = Mathf.Atan(v2.z / v2.y); |
|||
|
|||
float deltaH = 2f * Mathf.Sqrt(c1 * c2) * Mathf.Sin((h1 - h2) / 2f); |
|||
float deltaE = Mathf.Sqrt(Mathf.Pow(v1.x - v2.x, 2f) + Mathf.Pow(c1 - c2, 2f) + deltaH * deltaH); |
|||
return deltaE; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6fba903785fbd444a9ad5d15b2176c7f |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
|
|||
namespace UnityEngine.TestTools.Graphics |
|||
{ |
|||
/// <summary>
|
|||
/// Settings to control how image comparison is performed by <c>ImageAssert.</c>
|
|||
/// </summary>
|
|||
[Serializable] |
|||
public class ImageComparisonSettings |
|||
{ |
|||
/// <summary>
|
|||
/// The width to use for the rendered image. If a reference image already exists for this
|
|||
/// test and has a different size the test will fail.
|
|||
/// </summary>
|
|||
[Tooltip("The width to use for the rendered image.")] |
|||
public int TargetWidth = 512; |
|||
|
|||
/// <summary>
|
|||
/// The height to use for the rendered image. If a reference image already exists for this
|
|||
/// test and has a different size the test will fail.
|
|||
/// </summary>
|
|||
[Tooltip("The height to use for the rendered image.")] |
|||
public int TargetHeight = 512; |
|||
|
|||
/// <summary>
|
|||
/// The permitted perceptual difference between individual pixels of the images.
|
|||
///
|
|||
/// The deltaE for each pixel of the image is compared and any differences below this
|
|||
/// threshold are ignored.
|
|||
/// </summary>
|
|||
[Tooltip("The permitted perceptual difference between individual pixels of the images.")] |
|||
public float PerPixelCorrectnessThreshold; |
|||
|
|||
/// <summary>
|
|||
/// The maximum permitted average error value across the entire image. If the average
|
|||
/// per-pixel difference across the image is above this value, the images are considered
|
|||
/// not to be equal.
|
|||
/// </summary>
|
|||
[Tooltip("The maximum permitted average error value across the entire image.")] |
|||
public float AverageCorrectnessThreshold; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: b96a4804cb6f3944c8cd3a1c0ae429d5 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#if UNITY_EDITOR
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Xml; |
|||
using NUnit.Framework; |
|||
using NUnit.Framework.Interfaces; |
|||
using UnityEditor.Graphs; |
|||
using UnityEngine; |
|||
using UnityEngine.Rendering; |
|||
using UnityEngine.TestTools.Graphics; |
|||
|
|||
namespace UnityEditor.TestTools.Graphics |
|||
{ |
|||
public class ResultsUtility |
|||
{ |
|||
public const string ActualImagesRoot = "Assets/ActualImages"; |
|||
|
|||
private static T GetEnumPropertyValue<T>(XmlDocument doc, string name) |
|||
{ |
|||
var node = doc.SelectSingleNode(string.Format("//property[@name='{0}']", name)); |
|||
if (node == null) |
|||
throw new KeyNotFoundException(); |
|||
|
|||
return (T) Enum.Parse(typeof(T), node.Attributes["value"].Value); |
|||
} |
|||
|
|||
[MenuItem("Tests/Extract images from TestResults.xml...")] |
|||
internal static void ExtractImagesFromResultsXml() |
|||
{ |
|||
var filePath = |
|||
EditorUtility.OpenFilePanel("Select TestResults.xml file", Environment.CurrentDirectory, "xml"); |
|||
if (!string.IsNullOrEmpty(filePath)) |
|||
{ |
|||
ResultsUtility.ExtractImagesFromResultsXml(filePath); |
|||
} |
|||
} |
|||
|
|||
internal static void ExtractImagesFromResultsXml(string xmlFilePath) |
|||
{ |
|||
if (!Directory.Exists(ActualImagesRoot)) |
|||
Directory.CreateDirectory(ActualImagesRoot); |
|||
|
|||
XmlDocument doc = new XmlDocument(); |
|||
doc.Load(xmlFilePath); |
|||
|
|||
var colorSpace = GetEnumPropertyValue<ColorSpace>(doc, "ColorSpace"); |
|||
var platform = GetEnumPropertyValue<RuntimePlatform>(doc, "RuntimePlatform"); |
|||
var graphicsDevice = GetEnumPropertyValue<GraphicsDeviceType>(doc, "GraphicsDevice"); |
|||
|
|||
var path = Path.Combine(ActualImagesRoot, string.Format("{0}/{1}/{2}", colorSpace, platform, graphicsDevice)); |
|||
if (!Directory.Exists(path)) |
|||
Directory.CreateDirectory(path); |
|||
|
|||
var imagesWritten = new HashSet<string>(); |
|||
|
|||
foreach (var failedTestCase in doc.SelectNodes("//test-case[@result!='Passed']").OfType<XmlElement>()) |
|||
{ |
|||
var testName = failedTestCase.Attributes["name"].Value; |
|||
|
|||
var imageProperty = (XmlElement)failedTestCase.SelectSingleNode("./properties/property[@name='Image']"); |
|||
if (imageProperty == null) |
|||
continue; |
|||
|
|||
var bytes = Convert.FromBase64String(imageProperty.Attributes["value"].Value); |
|||
var imagePath = path + "/" + testName + ".png"; |
|||
File.WriteAllBytes(imagePath, bytes); |
|||
imagesWritten.Add(imagePath); |
|||
|
|||
var diffProperty = (XmlElement) failedTestCase.SelectSingleNode("./properties/property[@name='DiffImage']"); |
|||
if (diffProperty == null) |
|||
continue; |
|||
|
|||
bytes = Convert.FromBase64String(diffProperty.Attributes["value"].Value); |
|||
imagePath = path + "/" + testName + ".diff.png"; |
|||
File.WriteAllBytes(imagePath, bytes); |
|||
imagesWritten.Add(imagePath); |
|||
} |
|||
|
|||
AssetDatabase.Refresh(); |
|||
|
|||
Utils.SetupReferenceImageImportSettings(imagesWritten); |
|||
} |
|||
|
|||
public static void ExtractImagesFromTestProperties(TestContext.TestAdapter test) |
|||
{ |
|||
if (!(test.Properties.ContainsKey("Image") || |
|||
test.Properties.ContainsKey("DiffImage"))) |
|||
return; |
|||
|
|||
var colorSpace = UseGraphicsTestCasesAttribute.Provider.ColorSpace; |
|||
var platform = UseGraphicsTestCasesAttribute.Provider.Platform; |
|||
var graphicsDevice = UseGraphicsTestCasesAttribute.Provider.GraphicsDevice; |
|||
|
|||
var dirName = Path.Combine(ActualImagesRoot, string.Format("{0}/{1}/{2}", colorSpace, platform, graphicsDevice)); |
|||
if (!Directory.Exists(dirName)) |
|||
Directory.CreateDirectory(dirName); |
|||
|
|||
var imagesWritten = new HashSet<string>(); |
|||
|
|||
if (test.Properties.ContainsKey("Image")) |
|||
{ |
|||
var bytes = Convert.FromBase64String((string)TestContext.CurrentContext.Test.Properties.Get("Image")); |
|||
var path = Path.Combine(dirName, TestContext.CurrentContext.Test.Name + ".png"); |
|||
File.WriteAllBytes(path, bytes); |
|||
imagesWritten.Add(path); |
|||
} |
|||
|
|||
if (test.Properties.ContainsKey("DiffImage")) |
|||
{ |
|||
var bytes = Convert.FromBase64String((string)TestContext.CurrentContext.Test.Properties.Get("DiffImage")); |
|||
var path = Path.Combine(dirName, TestContext.CurrentContext.Test.Name + ".diff.png"); |
|||
File.WriteAllBytes(path, bytes); |
|||
imagesWritten.Add(path); |
|||
} |
|||
|
|||
AssetDatabase.Refresh(); |
|||
|
|||
Utils.SetupReferenceImageImportSettings(imagesWritten); |
|||
} |
|||
} |
|||
} |
|||
#endif
|
|
|||
fileFormatVersion: 2 |
|||
guid: a6f7e9dc7aba30b4ab01ccd3b4fbc6f0 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using UnityEngine; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.TestTools.Graphics |
|||
{ |
|||
internal class RuntimeGraphicsTestCaseProvider : IGraphicsTestCaseProvider |
|||
{ |
|||
public ColorSpace ColorSpace |
|||
{ |
|||
get |
|||
{ |
|||
return QualitySettings.activeColorSpace; |
|||
} |
|||
} |
|||
|
|||
public RuntimePlatform Platform |
|||
{ |
|||
get |
|||
{ |
|||
return Application.platform; |
|||
} |
|||
} |
|||
|
|||
public GraphicsDeviceType GraphicsDevice |
|||
{ |
|||
get |
|||
{ |
|||
return SystemInfo.graphicsDeviceType; |
|||
} |
|||
} |
|||
|
|||
public IEnumerable<GraphicsTestCase> GetTestCases() |
|||
{ |
|||
AssetBundle referenceImagesBundle = null; |
|||
|
|||
var referenceImagesBundlePath = string.Format("{0}/referenceimages-{1}-{2}-{3}", Application.streamingAssetsPath, ColorSpace, Platform, GraphicsDevice); |
|||
if (File.Exists(referenceImagesBundlePath)) |
|||
referenceImagesBundle = AssetBundle.LoadFromFile(referenceImagesBundlePath); |
|||
|
|||
foreach (var scenePath in File.ReadAllLines(Application.streamingAssetsPath + "/SceneList.txt")) |
|||
{ |
|||
var imagePath = Path.GetFileNameWithoutExtension(scenePath); |
|||
|
|||
Texture2D referenceImage = null; |
|||
|
|||
// The bundle might not exist if there are no reference images for this configuration yet
|
|||
if (referenceImagesBundle != null) |
|||
referenceImage = referenceImagesBundle.LoadAsset<Texture2D>(imagePath); |
|||
|
|||
yield return new GraphicsTestCase(scenePath, referenceImage); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f769c839022e65b4daf8c79dec411f01 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
{ |
|||
"name": "UnityEngine.TestTools.Graphics", |
|||
"references": [], |
|||
"optionalUnityReferences": [ |
|||
"TestAssemblies" |
|||
], |
|||
"includePlatforms": [], |
|||
"excludePlatforms": [], |
|||
"allowUnsafeCode": true |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c081bc530f560634bb5c21d4b323a7f1 |
|||
AssemblyDefinitionImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using NUnit.Framework.Interfaces; |
|||
using NUnit.Framework.Internal; |
|||
using Attribute = System.Attribute; |
|||
|
|||
namespace UnityEngine.TestTools.Graphics |
|||
{ |
|||
/// <summary>
|
|||
/// Marks a test which takes <c>GraphicsTestCase</c> instances as wanting to have them generated automatically by
|
|||
/// the scene/reference-image management feature in the framework.
|
|||
/// </summary>
|
|||
public class UseGraphicsTestCasesAttribute : Attribute, ITestBuilder |
|||
{ |
|||
/// <summary>
|
|||
/// The <c>IGraphicsTestCaseProvider</c> which will be used to generate the <c>GraphicsTestCase</c> instances for the tests.
|
|||
/// </summary>
|
|||
public static IGraphicsTestCaseProvider Provider |
|||
{ |
|||
get |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
return new UnityEditor.TestTools.Graphics.EditorGraphicsTestCaseProvider(); |
|||
#else
|
|||
return new RuntimeGraphicsTestCaseProvider(); |
|||
#endif
|
|||
} |
|||
} |
|||
|
|||
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite) |
|||
{ |
|||
List<TestMethod> results = new List<TestMethod>(); |
|||
|
|||
IGraphicsTestCaseProvider provider = Provider; |
|||
|
|||
try |
|||
{ |
|||
foreach (var testCase in provider.GetTestCases()) |
|||
{ |
|||
var test = new TestMethod(method, suite) |
|||
{ |
|||
parms = new TestCaseParameters(new object[] {testCase}) |
|||
}; |
|||
test.parms.ApplyToTest(test); |
|||
test.Name = System.IO.Path.GetFileNameWithoutExtension(testCase.ScenePath); |
|||
|
|||
results.Add(test); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Console.WriteLine("Failed to generate graphics testcases!"); |
|||
Debug.LogException(ex); |
|||
throw; |
|||
} |
|||
|
|||
suite.Properties.Set("ColorSpace", provider.ColorSpace); |
|||
suite.Properties.Set("RuntimePlatform", provider.Platform); |
|||
suite.Properties.Set("GraphicsDevice", provider.GraphicsDevice); |
|||
|
|||
Console.WriteLine("Generated {0} graphics test cases.", results.Count); |
|||
return results; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 3ace43f143f96a142be353915a3a905a |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 25640715bf25cff4b901649cd3909294 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#if UNITY_EDITOR
|
|||
using System; |
|||
using UnityEngine; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEditor.TestTools.Graphics |
|||
{ |
|||
internal static class Utils |
|||
{ |
|||
public static RuntimePlatform BuildTargetToRuntimePlatform(BuildTarget target) |
|||
{ |
|||
switch (target) |
|||
{ |
|||
case BuildTarget.Android: |
|||
return RuntimePlatform.Android; |
|||
case BuildTarget.iOS: |
|||
return RuntimePlatform.IPhonePlayer; |
|||
case BuildTarget.StandaloneLinux: |
|||
case BuildTarget.StandaloneLinux64: |
|||
case BuildTarget.StandaloneLinuxUniversal: |
|||
return RuntimePlatform.LinuxPlayer; |
|||
case BuildTarget.StandaloneOSX: |
|||
return RuntimePlatform.OSXPlayer; |
|||
case BuildTarget.PS4: |
|||
return RuntimePlatform.PS4; |
|||
case BuildTarget.PSP2: |
|||
return RuntimePlatform.PSP2; |
|||
case BuildTarget.Switch: |
|||
return RuntimePlatform.Switch; |
|||
case BuildTarget.WebGL: |
|||
return RuntimePlatform.WebGLPlayer; |
|||
case BuildTarget.WSAPlayer: |
|||
throw new NotImplementedException( |
|||
"Don't know how to determine the target UWP architecture from the build settings"); |
|||
case BuildTarget.StandaloneWindows: |
|||
case BuildTarget.StandaloneWindows64: |
|||
return RuntimePlatform.WindowsPlayer; |
|||
case BuildTarget.XboxOne: |
|||
return RuntimePlatform.XboxOne; |
|||
case BuildTarget.tvOS: |
|||
return RuntimePlatform.tvOS; |
|||
} |
|||
|
|||
throw new ArgumentOutOfRangeException("target", target, "Unknown BuildTarget"); |
|||
} |
|||
|
|||
public static BuildTarget RuntimePlatformToBuildTarget(RuntimePlatform platform) |
|||
{ |
|||
switch (platform) |
|||
{ |
|||
case RuntimePlatform.Android: |
|||
return BuildTarget.Android; |
|||
case RuntimePlatform.IPhonePlayer: |
|||
return BuildTarget.iOS; |
|||
case RuntimePlatform.LinuxEditor: |
|||
case RuntimePlatform.LinuxPlayer: |
|||
return BuildTarget.StandaloneLinuxUniversal; |
|||
case RuntimePlatform.OSXEditor: |
|||
case RuntimePlatform.OSXPlayer: |
|||
return BuildTarget.StandaloneOSX; |
|||
case RuntimePlatform.PS4: |
|||
return BuildTarget.PS4; |
|||
case RuntimePlatform.PSP2: |
|||
return BuildTarget.PSP2; |
|||
case RuntimePlatform.Switch: |
|||
return BuildTarget.Switch; |
|||
#if !UNITY_2017_2_OR_NEWER
|
|||
case RuntimePlatform.TizenPlayer: |
|||
return BuildTarget.Tizen; |
|||
#endif
|
|||
case RuntimePlatform.tvOS: |
|||
return BuildTarget.tvOS; |
|||
case RuntimePlatform.WebGLPlayer: |
|||
return BuildTarget.WebGL; |
|||
case RuntimePlatform.WindowsEditor: |
|||
case RuntimePlatform.WindowsPlayer: |
|||
return BuildTarget.StandaloneWindows; |
|||
case RuntimePlatform.WSAPlayerARM: |
|||
case RuntimePlatform.WSAPlayerX64: |
|||
case RuntimePlatform.WSAPlayerX86: |
|||
return BuildTarget.WSAPlayer; |
|||
case RuntimePlatform.XboxOne: |
|||
return BuildTarget.XboxOne; |
|||
} |
|||
|
|||
throw new ArgumentOutOfRangeException("platform", platform, "Unknown RuntimePlatform"); |
|||
} |
|||
|
|||
public static void SetupReferenceImageImportSettings(IEnumerable<string> imageAssetPaths) |
|||
{ |
|||
// Make sure that all the images have compression turned off and are readable
|
|||
AssetDatabase.StartAssetEditing(); |
|||
try |
|||
{ |
|||
foreach (var path in imageAssetPaths) |
|||
{ |
|||
var importer = AssetImporter.GetAtPath(path) as TextureImporter; |
|||
if (!importer) |
|||
continue; |
|||
|
|||
if (importer.textureCompression == TextureImporterCompression.Uncompressed && importer.isReadable) |
|||
continue; |
|||
|
|||
importer.textureCompression = TextureImporterCompression.Uncompressed; |
|||
importer.isReadable = true; |
|||
importer.mipmapEnabled = false; |
|||
importer.npotScale = TextureImporterNPOTScale.None; |
|||
AssetDatabase.ImportAsset(path); |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
AssetDatabase.StopAssetEditing(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
#endif
|
撰写
预览
正在加载...
取消
保存
Reference in new issue