No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TestPlayerBuildModifierAttribute.cs 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using System;
  2. namespace UnityEditor.TestTools
  3. {
  4. /// <summary>
  5. /// You can use the ```TestPlayerBuildModifier``` attribute to accomplish a couple of different scenarios.
  6. /// ## Modify the Player build options for Play Mode tests
  7. ///
  8. /// It is possible to change the [BuildPlayerOptions](https://docs.unity3d.com/ScriptReference/BuildPlayerOptions.html) for the test **Player**, to achieve custom behavior when running **Play Mode** tests. Modifying the build options allows for changing the target location of the build as well as changing [BuildOptions](https://docs.unity3d.com/ScriptReference/BuildOptions.html).
  9. ///
  10. /// To modify the `BuildPlayerOptions`, do the following:
  11. ///
  12. /// * Implement the `ITestPlayerBuildModifier`
  13. /// * Reference the implementation type in a `TestPlayerBuildModifier` attribute on an assembly level.
  14. ///
  15. /// <example>
  16. /// <code>
  17. /// using UnityEditor;
  18. /// using UnityEditor.TestTools;
  19. ///
  20. /// [assembly:TestPlayerBuildModifier(typeof(BuildModifier))]
  21. /// public class BuildModifier : ITestPlayerBuildModifier
  22. /// {
  23. /// public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions)
  24. /// {
  25. /// if (playerOptions.target == BuildTarget.iOS)
  26. /// {
  27. /// playerOptions.options |= BuildOptions.SymlinkLibraries; // Enable symlink libraries when running on iOS
  28. /// }
  29. ///
  30. /// playerOptions.options |= BuildOptions.AllowDebugging; // Enable allow Debugging flag on the test Player.
  31. /// return playerOptions;
  32. /// }
  33. /// }
  34. /// </code>
  35. /// </example>
  36. ///
  37. ///
  38. /// &gt; **Note:** When building the Player, it includes all `TestPlayerBuildModifier` attributes across all loaded assemblies, independent of the currently used test filter. As the implementation references the `UnityEditor` namespace, the code is typically implemented in an Editor only assembly, as the `UnityEditor` namespace is not available otherwise.
  39. ///
  40. /// ## Split build and run
  41. /// It is possible to use the Unity Editor for building the Player with tests, without [running the tests](./workflow-run-playmode-test-standalone.md). This allows for running the Player on e.g. another machine. In this case, it is necessary to modify the Player to build and implement a custom handling of the test result.
  42. /// By using `TestPlayerBuildModifier`, you can alter the `BuildOptions` to not start the Player after the build as well as build the Player at a specific location. Combined with [PostBuildCleanup](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup), you can automatically exit the Editor on completion of the build.
  43. ///
  44. ///
  45. /// <example>
  46. /// <code>
  47. /// using System;
  48. /// using System.IO;
  49. /// using System.Linq;
  50. /// using Tests;
  51. /// using UnityEditor;
  52. /// using UnityEditor.TestTools;
  53. /// using UnityEngine;
  54. /// using UnityEngine.TestTools;
  55. ///
  56. /// [assembly:TestPlayerBuildModifier(typeof(HeadlessPlayModeSetup))]
  57. /// [assembly:PostBuildCleanup(typeof(HeadlessPlayModeSetup))]
  58. ///
  59. /// namespace Tests
  60. /// {
  61. /// public class HeadlessPlayModeSetup : ITestPlayerBuildModifier, IPostBuildCleanup
  62. /// {
  63. /// private static bool s_RunningPlayerTests;
  64. /// public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions)
  65. /// {
  66. /// // Do not launch the player after the build completes.
  67. /// playerOptions.options &amp;= ~BuildOptions.AutoRunPlayer;
  68. ///
  69. /// // Set the headlessBuildLocation to the output directory you desire. It does not need to be inside the project.
  70. /// var headlessBuildLocation = Path.GetFullPath(Path.Combine(Application.dataPath, ".//..//PlayModeTestPlayer"));
  71. /// var fileName = Path.GetFileName(playerOptions.locationPathName);
  72. /// if (!string.IsNullOrEmpty(fileName))
  73. /// {
  74. /// headlessBuildLocation = Path.Combine(headlessBuildLocation, fileName);
  75. /// }
  76. /// playerOptions.locationPathName = headlessBuildLocation;
  77. ///
  78. /// // Instruct the cleanup to exit the Editor if the run came from the command line.
  79. /// // The variable is static because the cleanup is being invoked in a new instance of the class.
  80. /// s_RunningPlayerTests = true;
  81. /// return playerOptions;
  82. /// }
  83. ///
  84. /// public void Cleanup()
  85. /// {
  86. /// if (s_RunningPlayerTests &amp;&amp; IsRunningTestsFromCommandLine())
  87. /// {
  88. /// // Exit the Editor on the next update, allowing for other PostBuildCleanup steps to run.
  89. /// EditorApplication.update += () =&gt; { EditorApplication.Exit(0); };
  90. /// }
  91. /// }
  92. ///
  93. /// private static bool IsRunningTestsFromCommandLine()
  94. /// {
  95. /// var commandLineArgs = Environment.GetCommandLineArgs();
  96. /// return commandLineArgs.Any(value =&gt; value == "-runTests");
  97. /// }
  98. /// }
  99. /// }
  100. /// </code>
  101. /// </example>
  102. ///
  103. /// If the Editor is still running after the Play Mode tests have run, the Player tries to report the results back, using [PlayerConnection](https://docs.unity3d.com/ScriptReference/Networking.PlayerConnection.PlayerConnection.html), which has a reference to the IP address of the Editor machine, when built.
  104. ///
  105. /// To implement a custom way of reporting the results of the test run, let one of the assemblies in the Player include a `TestRunCallbackAttribute`. At `RunFinished`, it is possible to get the full test report as XML from the [NUnit](http://www.nunit.org/) test result by calling `result.ToXml(true)`. You can save the result and then save it on the device or send it to another machine as needed.
  106. ///
  107. /// </summary>
  108. [AttributeUsage(AttributeTargets.Assembly)]
  109. public class TestPlayerBuildModifierAttribute : Attribute
  110. {
  111. private Type m_Type;
  112. /// <summary>
  113. /// Initializes and returns an instance of TestPlayerBuildModifierAttribute or throws an <see cref="ArgumentException"/>.
  114. /// </summary>
  115. /// <param name="type">A target type that implements ITestPlayerBuildModifier.</param>
  116. /// <exception cref="ArgumentException">Throws a <see cref="ArgumentException"/> if the type provided does not implemented the `ITestPlayerBuildModifier` interface. </exception>
  117. public TestPlayerBuildModifierAttribute(Type type)
  118. {
  119. var interfaceType = typeof(ITestPlayerBuildModifier);
  120. if (!interfaceType.IsAssignableFrom(type))
  121. {
  122. throw new ArgumentException(string.Format("Type provided to {0} does not implement {1}", GetType().Name, interfaceType.Name));
  123. }
  124. m_Type = type;
  125. }
  126. internal ITestPlayerBuildModifier ConstructModifier()
  127. {
  128. return Activator.CreateInstance(m_Type) as ITestPlayerBuildModifier;
  129. }
  130. }
  131. }