Are you involved in testing or QA on projects in Unity? In these slides, you'll get an overview of the state of Unity for all things testing-related, and have the opportunity to share your stories of success, failure, pain, and glory. Learn from your fellow developers and give feedback on how Unity could help you hold your projects to a higher standard of quality. You will also get an introduction to the newest features in the Test Framework.
Speakers:
Christian Warnecke - Unity
Richard Fine - Unity
Watch the session on YouTube: https://youtu.be/wTiF2D0_vKA
5. What’s new?
5
— Big push towards more flexibility and customization
— Migrated to a package so we can ship updates faster
– This means you get the source code, too!
9. Splitting Build and Run
9
— Customize the test player build process to:
– Disable auto-run
– Save to a known location, instead of temporary
— Add custom result reporting to save results to a file
10. Splitting Build and Run - Build
10
[assembly:TestPlayerBuildModifier(typeof(SetupPlaymodeTestPlayer))]
public class SetupPlaymodeTestPlayer : ITestPlayerBuildModifier {
public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions) {
playerOptions.options &= ~(BuildOptions.AutoRunPlayer | BuildOptions.ConnectToHost);
var buildLocation = Path.GetFullPath("TestPlayers");
var fileName = Path.GetFileName(playerOptions.locationPathName);
if (!string.IsNullOrEmpty(fileName))
buildLocation = Path.Combine(buildLocation, fileName);
playerOptions.locationPathName = buildLocation;
return playerOptions;
}
}
11. Splitting Build and Run - Save results in run
11
[assembly:TestRunCallback(typeof(ResultSerializer))]
public class ResultSerializer : ITestRunCallback {
public void RunStarted(ITest testsToRun) { }
public void TestStarted(ITest test) { }
public void TestFinished(ITestResult result) { }
public void RunFinished(ITestResult testResults) {
var path = Path.Combine(Application.persistentDataPath, "testresults.xml");
using (var xw = XmlWriter.Create(path, new XmlWriterSettings{Indent = true}))
testResults.ToXml(true).WriteTo(xw);
System.Console.WriteLine($"***nnTEST RESULTS WRITTEN TOnnt{path}nn***");
Application.Quit(testResults.FailCount > 0 ? 1 : 0);
}
}
12. Launching specific tests from a menu item
12
— Method wired up to menu item as usual ([MenuItem] etc)
— Create instance of a ScriptableObject callback object
— Register/deregister the callbacks in OnEnable/OnDisable
— Set up filters
— Execute
— When finished, display message, open results window, etc
13. Launching specific tests from a menu item
13
public class RunTestsFromMenu : ScriptableObject, ICallbacks {
[MenuItem(“Tools/Run useful tests”)] public static void DoRunTests() {
CreateInstance<RunTestsFromMenu>().StartTestRun();
}
private void StartTestRun() {
hideFlags = HideFlags.HideAndDontSave;
CreateInstance<TestRunnerApi>().Execute(new ExecutionSettings {
filters = new [] { new Filter{ categoryNames = new[] { “UsefulTests” }}}
});
}
public void OnEnable() { CreateInstance<TestRunnerApi>().RegisterCallbacks(this); }
public void OnDisable() { CreateInstance<TestRunnerApi>().UnregisterCallbacks(this); }
/* ...RunStarted, TestStarted, TestFinished... */
public void RunFinished(ITestResultAdaptor result) {
…
DestroyImmediate(this);
}
}
14. Running tests before the build
14
— Implement IPreprocessBuildWithReport
— Register a callback to get test results
— Use TestRunnerApi to run specific (Editor) tests
– Filtering by category is a good idea!
– Run synchronously!
— Check for what the results were
— Throw BuildFailedException if anything failed
15. Running tests before the build - result collector
15
public class ResultCollector : ICallbacks {
public ITestResultAdaptor Result { get; private set; }
public void RunStarted(ITestAdaptor testsToRun) { }
public void TestStarted(ITestAdaptor test) { }
public void TestFinished(ITestResultAdaptor result) { }
public void RunFinished(ITestResultAdaptor result)
{
Result = result;
}
}
16. Running tests before the build - preprocessor
16
public class RunValidationTestsBeforeBuild : IPreprocessBuildWithReport {
public void OnPreprocessBuild(BuildReport report) {
var results = new ResultCollector();
var api = ScriptableObject.CreateInstance<TestRunnerApi>();
api.RegisterCallbacks(results);
api.Execute(new ExecutionSettings {
runSynchronously = true,
filters = new[] { new Filter {
categoryNames = new[] { $"PreBuildValidationTests" },
testMode = TestMode.EditMode
} }
});
if (resultCollector.results.FailCount > 0)
throw new BuildFailedException($"One or more of the validation tests did not pass.");
}
}