BeforeAfterTestCommandBase.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using System;
  2. using System.Collections;
  3. using System.Linq;
  4. using NUnit.Framework.Interfaces;
  5. using NUnit.Framework.Internal;
  6. using NUnit.Framework.Internal.Commands;
  7. using UnityEngine.TestRunner.NUnitExtensions;
  8. using UnityEngine.TestRunner.NUnitExtensions.Runner;
  9. using UnityEngine.TestTools.Logging;
  10. using UnityEngine.TestTools.TestRunner;
  11. namespace UnityEngine.TestTools
  12. {
  13. internal abstract class BeforeAfterTestCommandBase<T> : DelegatingTestCommand, IEnumerableTestMethodCommand
  14. {
  15. private string m_BeforeErrorPrefix;
  16. private string m_AfterErrorPrefix;
  17. private bool m_SkipYieldAfterActions;
  18. protected BeforeAfterTestCommandBase(TestCommand innerCommand, string beforeErrorPrefix, string afterErrorPrefix, bool skipYieldAfterActions = false)
  19. : base(innerCommand)
  20. {
  21. m_BeforeErrorPrefix = beforeErrorPrefix;
  22. m_AfterErrorPrefix = afterErrorPrefix;
  23. m_SkipYieldAfterActions = skipYieldAfterActions;
  24. }
  25. protected T[] BeforeActions = new T[0];
  26. protected T[] AfterActions = new T[0];
  27. protected abstract IEnumerator InvokeBefore(T action, Test test, UnityTestExecutionContext context);
  28. protected abstract IEnumerator InvokeAfter(T action, Test test, UnityTestExecutionContext context);
  29. protected abstract BeforeAfterTestCommandState GetState(UnityTestExecutionContext context);
  30. public IEnumerable ExecuteEnumerable(ITestExecutionContext context)
  31. {
  32. var unityContext = (UnityTestExecutionContext)context;
  33. var state = GetState(unityContext);
  34. if (state == null)
  35. {
  36. // We do not expect a state to exist in playmode
  37. state = ScriptableObject.CreateInstance<BeforeAfterTestCommandState>();
  38. }
  39. state.ApplyTestResult(context.CurrentResult);
  40. while (state.NextBeforeStepIndex < BeforeActions.Length)
  41. {
  42. var action = BeforeActions[state.NextBeforeStepIndex];
  43. IEnumerator enumerator;
  44. try
  45. {
  46. enumerator = InvokeBefore(action, Test, unityContext);
  47. }
  48. catch (Exception ex)
  49. {
  50. state.TestHasRun = true;
  51. context.CurrentResult.RecordPrefixedException(m_BeforeErrorPrefix, ex);
  52. break;
  53. }
  54. ActivePcHelper.SetEnumeratorPC(enumerator, state.NextBeforeStepPc);
  55. using (var logScope = new LogScope())
  56. {
  57. while (true)
  58. {
  59. try
  60. {
  61. if (!enumerator.MoveNext())
  62. {
  63. break;
  64. }
  65. }
  66. catch (Exception ex)
  67. {
  68. state.TestHasRun = true;
  69. context.CurrentResult.RecordPrefixedException(m_BeforeErrorPrefix, ex);
  70. state.StoreTestResult(context.CurrentResult);
  71. break;
  72. }
  73. state.NextBeforeStepPc = ActivePcHelper.GetEnumeratorPC(enumerator);
  74. state.StoreTestResult(context.CurrentResult);
  75. if (m_SkipYieldAfterActions)
  76. {
  77. break;
  78. }
  79. else
  80. {
  81. yield return enumerator.Current;
  82. }
  83. }
  84. if (logScope.AnyFailingLogs())
  85. {
  86. state.TestHasRun = true;
  87. context.CurrentResult.RecordPrefixedError(m_BeforeErrorPrefix, new UnhandledLogMessageException(logScope.FailingLogs.First()).Message);
  88. state.StoreTestResult(context.CurrentResult);
  89. }
  90. }
  91. state.NextBeforeStepIndex++;
  92. state.NextBeforeStepPc = 0;
  93. }
  94. if (!state.TestHasRun)
  95. {
  96. if (innerCommand is IEnumerableTestMethodCommand)
  97. {
  98. var executeEnumerable = ((IEnumerableTestMethodCommand)innerCommand).ExecuteEnumerable(context);
  99. foreach (var iterator in executeEnumerable)
  100. {
  101. state.StoreTestResult(context.CurrentResult);
  102. yield return iterator;
  103. }
  104. }
  105. else
  106. {
  107. context.CurrentResult = innerCommand.Execute(context);
  108. state.StoreTestResult(context.CurrentResult);
  109. }
  110. state.TestHasRun = true;
  111. }
  112. while (state.NextAfterStepIndex < AfterActions.Length)
  113. {
  114. state.TestAfterStarted = true;
  115. var action = AfterActions[state.NextAfterStepIndex];
  116. IEnumerator enumerator;
  117. try
  118. {
  119. enumerator = InvokeAfter(action, Test, unityContext);
  120. }
  121. catch (Exception ex)
  122. {
  123. context.CurrentResult.RecordPrefixedException(m_AfterErrorPrefix, ex);
  124. state.StoreTestResult(context.CurrentResult);
  125. break;
  126. }
  127. ActivePcHelper.SetEnumeratorPC(enumerator, state.NextAfterStepPc);
  128. using (var logScope = new LogScope())
  129. {
  130. while (true)
  131. {
  132. try
  133. {
  134. if (!enumerator.MoveNext())
  135. {
  136. break;
  137. }
  138. }
  139. catch (Exception ex)
  140. {
  141. context.CurrentResult.RecordPrefixedException(m_AfterErrorPrefix, ex);
  142. state.StoreTestResult(context.CurrentResult);
  143. break;
  144. }
  145. state.NextAfterStepPc = ActivePcHelper.GetEnumeratorPC(enumerator);
  146. state.StoreTestResult(context.CurrentResult);
  147. if (m_SkipYieldAfterActions)
  148. {
  149. break;
  150. }
  151. else
  152. {
  153. yield return enumerator.Current;
  154. }
  155. }
  156. if (logScope.AnyFailingLogs())
  157. {
  158. state.TestHasRun = true;
  159. context.CurrentResult.RecordPrefixedError(m_AfterErrorPrefix, new UnhandledLogMessageException(logScope.FailingLogs.First()).Message);
  160. state.StoreTestResult(context.CurrentResult);
  161. }
  162. }
  163. state.NextAfterStepIndex++;
  164. state.NextAfterStepPc = 0;
  165. }
  166. state.Reset();
  167. }
  168. public override TestResult Execute(ITestExecutionContext context)
  169. {
  170. throw new NotImplementedException("Use ExecuteEnumerable");
  171. }
  172. private static TestCommandPcHelper pcHelper;
  173. internal static TestCommandPcHelper ActivePcHelper
  174. {
  175. get
  176. {
  177. if (pcHelper == null)
  178. {
  179. pcHelper = new TestCommandPcHelper();
  180. }
  181. return pcHelper;
  182. }
  183. set
  184. {
  185. pcHelper = value;
  186. }
  187. }
  188. }
  189. }