TestCommandBuilder.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System;
  2. using System.Collections;
  3. using System.Linq;
  4. using NUnit.Framework;
  5. using NUnit.Framework.Interfaces;
  6. using NUnit.Framework.Internal;
  7. using NUnit.Framework.Internal.Commands;
  8. using UnityEngine.TestTools;
  9. namespace UnityEngine.TestRunner.NUnitExtensions.Runner
  10. {
  11. internal static class TestCommandBuilder
  12. {
  13. public static TestCommand BuildTestCommand(TestMethod test, ITestFilter filter)
  14. {
  15. if (test.RunState != RunState.Runnable &&
  16. !(test.RunState == RunState.Explicit && filter.IsExplicitMatch(test)))
  17. {
  18. return new SkipCommand(test);
  19. }
  20. var testReturnsIEnumerator = test.Method.ReturnType.Type == typeof(IEnumerator);
  21. TestCommand command;
  22. if (!testReturnsIEnumerator)
  23. {
  24. command = new TestMethodCommand(test);
  25. }
  26. else
  27. {
  28. command = new EnumerableTestMethodCommand(test);
  29. }
  30. command = new UnityLogCheckDelegatingCommand(command);
  31. foreach (var wrapper in test.Method.GetCustomAttributes<IWrapTestMethod>(true))
  32. {
  33. command = wrapper.Wrap(command);
  34. if (command == null)
  35. {
  36. var message = String.Format("IWrapTestMethod implementation '{0}' returned null as command.",
  37. wrapper.GetType().FullName);
  38. return new FailCommand(test, ResultState.Failure, message);
  39. }
  40. if (testReturnsIEnumerator && !(command is IEnumerableTestMethodCommand))
  41. {
  42. command = TryReplaceWithEnumerableCommand(command);
  43. if (command != null)
  44. {
  45. continue;
  46. }
  47. var message = String.Format("'{0}' is not supported on {1} as it does not handle returning IEnumerator.",
  48. wrapper.GetType().FullName,
  49. GetTestBuilderName(test));
  50. return new FailCommand(test, ResultState.Failure, message);
  51. }
  52. }
  53. command = new UnityEngine.TestTools.TestActionCommand(command);
  54. command = new UnityEngine.TestTools.SetUpTearDownCommand(command);
  55. if (!testReturnsIEnumerator)
  56. {
  57. command = new ImmediateEnumerableCommand(command);
  58. }
  59. foreach (var wrapper in test.Method.GetCustomAttributes<IWrapSetUpTearDown>(true))
  60. {
  61. command = wrapper.Wrap(command);
  62. if (command == null)
  63. {
  64. var message = String.Format("IWrapSetUpTearDown implementation '{0}' returned null as command.",
  65. wrapper.GetType().FullName);
  66. return new FailCommand(test, ResultState.Failure, message);
  67. }
  68. if (testReturnsIEnumerator && !(command is IEnumerableTestMethodCommand))
  69. {
  70. command = TryReplaceWithEnumerableCommand(command);
  71. if (command != null)
  72. {
  73. continue;
  74. }
  75. var message = String.Format("'{0}' is not supported on {1} as it does not handle returning IEnumerator.",
  76. wrapper.GetType().FullName,
  77. GetTestBuilderName(test));
  78. return new FailCommand(test, ResultState.Failure, message);
  79. }
  80. }
  81. command = new EnumerableSetUpTearDownCommand(command);
  82. command = new OuterUnityTestActionCommand(command);
  83. IApplyToContext[] changes = test.Method.GetCustomAttributes<IApplyToContext>(true);
  84. if (changes.Length > 0)
  85. {
  86. command = new EnumerableApplyChangesToContextCommand(command, changes);
  87. }
  88. return command;
  89. }
  90. private static string GetTestBuilderName(TestMethod testMethod)
  91. {
  92. return new[]
  93. {
  94. testMethod.Method.GetCustomAttributes<ITestBuilder>(true).Select(attribute => attribute.GetType().Name),
  95. testMethod.Method.GetCustomAttributes<ISimpleTestBuilder>(true).Select(attribute => attribute.GetType().Name)
  96. }.SelectMany(v => v).FirstOrDefault();
  97. }
  98. private static TestCommand TryReplaceWithEnumerableCommand(TestCommand command)
  99. {
  100. switch (command.GetType().Name)
  101. {
  102. case nameof(RepeatAttribute.RepeatedTestCommand):
  103. return new EnumerableRepeatedTestCommand(command as RepeatAttribute.RepeatedTestCommand);
  104. case nameof(RetryAttribute.RetryCommand):
  105. return new EnumerableRetryTestCommand(command as RetryAttribute.RetryCommand);
  106. default:
  107. return null;
  108. }
  109. }
  110. }
  111. }