PageRenderTime 31ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 1ms

/Tests/TechTalk.SpecFlow.RuntimeTests/Infrastructure/TestExecutionEngineTests.cs

http://github.com/techtalk/SpecFlow
C# | 696 lines | 553 code | 141 blank | 2 comment | 7 complexity | d7d9e530d724320cbc638fe0fa587db9 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Reflection;
  6. using BoDi;
  7. using Moq;
  8. using Xunit;
  9. using TechTalk.SpecFlow.BindingSkeletons;
  10. using TechTalk.SpecFlow.Bindings;
  11. using TechTalk.SpecFlow.Bindings.Reflection;
  12. using TechTalk.SpecFlow.Configuration;
  13. using TechTalk.SpecFlow.ErrorHandling;
  14. using TechTalk.SpecFlow.Infrastructure;
  15. using TechTalk.SpecFlow.Tracing;
  16. using TechTalk.SpecFlow.UnitTestProvider;
  17. using FluentAssertions;
  18. using TechTalk.SpecFlow.Analytics;
  19. using TechTalk.SpecFlow.CucumberMessages;
  20. namespace TechTalk.SpecFlow.RuntimeTests.Infrastructure
  21. {
  22. public class TestExecutionEngineTests
  23. {
  24. private ScenarioContext scenarioContext;
  25. private SpecFlowConfiguration specFlowConfiguration;
  26. private Mock<IBindingRegistry> bindingRegistryStub;
  27. private Mock<IErrorProvider> errorProviderStub;
  28. private Mock<IContextManager> contextManagerStub;
  29. private Mock<ITestTracer> testTracerStub;
  30. private Mock<IStepDefinitionMatchService> stepDefinitionMatcherStub;
  31. private Mock<IBindingInvoker> methodBindingInvokerMock;
  32. private Dictionary<string, IStepErrorHandler> stepErrorHandlers;
  33. private Mock<IStepDefinitionSkeletonProvider> stepDefinitionSkeletonProviderMock;
  34. private Mock<ITestObjectResolver> testObjectResolverMock;
  35. private Mock<IObsoleteStepHandler> obsoleteTestHandlerMock;
  36. private Mock<ICucumberMessageSender> cucumberMessageSenderMock;
  37. private FeatureInfo featureInfo;
  38. private ScenarioInfo scenarioInfo;
  39. private ObjectContainer testThreadContainer;
  40. private ObjectContainer featureContainer;
  41. private ObjectContainer scenarioContainer;
  42. private TestObjectResolver defaultTestObjectResolver = new TestObjectResolver();
  43. private ITestPendingMessageFactory _testPendingMessageFactory;
  44. private ITestUndefinedMessageFactory _testUndefinedMessageFactory;
  45. private Mock<IAnalyticsEventProvider> _analyticsEventProvider;
  46. private Mock<IAnalyticsTransmitter> _analyticsTransmitter;
  47. private Mock<ITestRunnerManager> _testRunnerManager;
  48. private List<IHookBinding> beforeScenarioEvents;
  49. private List<IHookBinding> afterScenarioEvents;
  50. private List<IHookBinding> beforeStepEvents;
  51. private List<IHookBinding> afterStepEvents;
  52. private List<IHookBinding> beforeFeatureEvents;
  53. private List<IHookBinding> afterFeatureEvents;
  54. private List<IHookBinding> beforeTestRunEvents;
  55. private List<IHookBinding> afterTestRunEvents;
  56. private List<IHookBinding> beforeScenarioBlockEvents;
  57. private List<IHookBinding> afterScenarioBlockEvents;
  58. class DummyClass
  59. {
  60. public static DummyClass LastInstance = null;
  61. public DummyClass()
  62. {
  63. LastInstance = this;
  64. }
  65. }
  66. class AnotherDummyClass { }
  67. public TestExecutionEngineTests()
  68. {
  69. specFlowConfiguration = ConfigurationLoader.GetDefault();
  70. testThreadContainer = new ObjectContainer();
  71. featureContainer = new ObjectContainer();
  72. scenarioContainer = new ObjectContainer();
  73. beforeScenarioEvents = new List<IHookBinding>();
  74. afterScenarioEvents = new List<IHookBinding>();
  75. beforeStepEvents = new List<IHookBinding>();
  76. afterStepEvents = new List<IHookBinding>();
  77. beforeFeatureEvents = new List<IHookBinding>();
  78. afterFeatureEvents = new List<IHookBinding>();
  79. beforeTestRunEvents = new List<IHookBinding>();
  80. afterTestRunEvents = new List<IHookBinding>();
  81. beforeScenarioBlockEvents = new List<IHookBinding>();
  82. afterScenarioBlockEvents = new List<IHookBinding>();
  83. stepDefinitionSkeletonProviderMock = new Mock<IStepDefinitionSkeletonProvider>();
  84. testObjectResolverMock = new Mock<ITestObjectResolver>();
  85. testObjectResolverMock.Setup(bir => bir.ResolveBindingInstance(It.IsAny<Type>(), It.IsAny<IObjectContainer>()))
  86. .Returns((Type t, IObjectContainer container) => defaultTestObjectResolver.ResolveBindingInstance(t, container));
  87. var culture = new CultureInfo("en-US", false);
  88. contextManagerStub = new Mock<IContextManager>();
  89. scenarioInfo = new ScenarioInfo("scenario_title", "scenario_description");
  90. scenarioContext = new ScenarioContext(scenarioContainer, scenarioInfo, testObjectResolverMock.Object);
  91. scenarioContainer.RegisterInstanceAs(scenarioContext);
  92. contextManagerStub.Setup(cm => cm.ScenarioContext).Returns(scenarioContext);
  93. featureInfo = new FeatureInfo(culture, "feature_title", "", ProgrammingLanguage.CSharp);
  94. var featureContext = new FeatureContext(featureContainer, featureInfo, specFlowConfiguration);
  95. featureContainer.RegisterInstanceAs(featureContext);
  96. contextManagerStub.Setup(cm => cm.FeatureContext).Returns(featureContext);
  97. contextManagerStub.Setup(cm => cm.StepContext).Returns(new ScenarioStepContext(new StepInfo(StepDefinitionType.Given, "step_title", null, null)));
  98. bindingRegistryStub = new Mock<IBindingRegistry>();
  99. bindingRegistryStub.Setup(br => br.GetHooks(HookType.BeforeStep)).Returns(beforeStepEvents);
  100. bindingRegistryStub.Setup(br => br.GetHooks(HookType.AfterStep)).Returns(afterStepEvents);
  101. bindingRegistryStub.Setup(br => br.GetHooks(HookType.BeforeScenarioBlock)).Returns(beforeScenarioBlockEvents);
  102. bindingRegistryStub.Setup(br => br.GetHooks(HookType.AfterScenarioBlock)).Returns(afterScenarioBlockEvents);
  103. bindingRegistryStub.Setup(br => br.GetHooks(HookType.BeforeFeature)).Returns(beforeFeatureEvents);
  104. bindingRegistryStub.Setup(br => br.GetHooks(HookType.AfterFeature)).Returns(afterFeatureEvents);
  105. bindingRegistryStub.Setup(br => br.GetHooks(HookType.BeforeTestRun)).Returns(beforeTestRunEvents);
  106. bindingRegistryStub.Setup(br => br.GetHooks(HookType.AfterTestRun)).Returns(afterTestRunEvents);
  107. bindingRegistryStub.Setup(br => br.GetHooks(HookType.BeforeScenario)).Returns(beforeScenarioEvents);
  108. bindingRegistryStub.Setup(br => br.GetHooks(HookType.AfterScenario)).Returns(afterScenarioEvents);
  109. specFlowConfiguration = ConfigurationLoader.GetDefault();
  110. errorProviderStub = new Mock<IErrorProvider>();
  111. testTracerStub = new Mock<ITestTracer>();
  112. stepDefinitionMatcherStub = new Mock<IStepDefinitionMatchService>();
  113. methodBindingInvokerMock = new Mock<IBindingInvoker>();
  114. stepErrorHandlers = new Dictionary<string, IStepErrorHandler>();
  115. obsoleteTestHandlerMock = new Mock<IObsoleteStepHandler>();
  116. cucumberMessageSenderMock = new Mock<ICucumberMessageSender>();
  117. cucumberMessageSenderMock.Setup(m => m.SendTestRunStarted())
  118. .Callback(() => { });
  119. _testPendingMessageFactory = new TestPendingMessageFactory(errorProviderStub.Object);
  120. _testUndefinedMessageFactory = new TestUndefinedMessageFactory(stepDefinitionSkeletonProviderMock.Object, errorProviderStub.Object, specFlowConfiguration);
  121. _analyticsEventProvider = new Mock<IAnalyticsEventProvider>();
  122. _analyticsTransmitter = new Mock<IAnalyticsTransmitter>();
  123. _analyticsTransmitter.Setup(at => at.TransmitSpecFlowProjectRunningEvent(It.IsAny<SpecFlowProjectRunningEvent>()))
  124. .Callback(() => { });
  125. _testRunnerManager = new Mock<ITestRunnerManager>();
  126. _testRunnerManager.Setup(trm => trm.TestAssembly).Returns(Assembly.GetCallingAssembly);
  127. }
  128. private TestExecutionEngine CreateTestExecutionEngine()
  129. {
  130. return new TestExecutionEngine(
  131. new Mock<IStepFormatter>().Object,
  132. testTracerStub.Object,
  133. errorProviderStub.Object,
  134. new Mock<IStepArgumentTypeConverter>().Object,
  135. specFlowConfiguration,
  136. bindingRegistryStub.Object,
  137. new Mock<IUnitTestRuntimeProvider>().Object,
  138. contextManagerStub.Object,
  139. stepDefinitionMatcherStub.Object,
  140. stepErrorHandlers,
  141. methodBindingInvokerMock.Object,
  142. obsoleteTestHandlerMock.Object,
  143. cucumberMessageSenderMock.Object,
  144. new TestResultFactory(new TestResultPartsFactory(new TestErrorMessageFactory(), _testPendingMessageFactory, new TestAmbiguousMessageFactory(), _testUndefinedMessageFactory)),
  145. _testPendingMessageFactory,
  146. _testUndefinedMessageFactory,
  147. new Mock<ITestRunResultCollector>().Object,
  148. _analyticsEventProvider.Object,
  149. _analyticsTransmitter.Object,
  150. _testRunnerManager.Object,
  151. testObjectResolverMock.Object,
  152. testThreadContainer);
  153. }
  154. private Mock<IPickleIdStore> GetPickleIdStoreMock()
  155. {
  156. var dictionary = new Dictionary<ScenarioInfo, Guid>();
  157. var pickleIdStoreMock = new Mock<IPickleIdStore>();
  158. pickleIdStoreMock.Setup(m => m.GetPickleIdForScenario(It.IsAny<ScenarioInfo>()))
  159. .Returns<ScenarioInfo>(info =>
  160. {
  161. if (dictionary.ContainsKey(info))
  162. {
  163. return dictionary[info];
  164. }
  165. var newGuid = Guid.NewGuid();
  166. dictionary.Add(info, newGuid);
  167. return newGuid;
  168. });
  169. return pickleIdStoreMock;
  170. }
  171. private Mock<IStepDefinitionBinding> RegisterStepDefinition()
  172. {
  173. var methodStub = new Mock<IBindingMethod>();
  174. var stepDefStub = new Mock<IStepDefinitionBinding>();
  175. stepDefStub.Setup(sd => sd.Method).Returns(methodStub.Object);
  176. StepDefinitionAmbiguityReason ambiguityReason;
  177. List<BindingMatch> candidatingMatches;
  178. stepDefinitionMatcherStub.Setup(sdm => sdm.GetBestMatch(It.IsAny<StepInstance>(), It.IsAny<CultureInfo>(), out ambiguityReason, out candidatingMatches))
  179. .Returns(
  180. new BindingMatch(stepDefStub.Object, 0, new object[0], new StepContext("bla", "foo", new List<string>(), CultureInfo.InvariantCulture)));
  181. return stepDefStub;
  182. }
  183. private Mock<IStepDefinitionBinding> RegisterUndefinedStepDefinition()
  184. {
  185. var methodStub = new Mock<IBindingMethod>();
  186. var stepDefStub = new Mock<IStepDefinitionBinding>();
  187. stepDefStub.Setup(sd => sd.Method).Returns(methodStub.Object);
  188. StepDefinitionAmbiguityReason ambiguityReason;
  189. List<BindingMatch> candidatingMatches;
  190. stepDefinitionMatcherStub.Setup(sdm => sdm.GetBestMatch(It.IsAny<StepInstance>(), It.IsAny<CultureInfo>(), out ambiguityReason, out candidatingMatches))
  191. .Returns(BindingMatch.NonMatching);
  192. return stepDefStub;
  193. }
  194. private void RegisterFailingStepDefinition()
  195. {
  196. var stepDefStub = RegisterStepDefinition();
  197. TimeSpan duration;
  198. methodBindingInvokerMock.Setup(i => i.InvokeBinding(stepDefStub.Object, contextManagerStub.Object, It.IsAny<object[]>(), testTracerStub.Object, out duration))
  199. .Throws(new Exception("simulated error"));
  200. }
  201. private Mock<IHookBinding> CreateHookMock(List<IHookBinding> hookList)
  202. {
  203. var mock = new Mock<IHookBinding>();
  204. hookList.Add(mock.Object);
  205. return mock;
  206. }
  207. private Mock<IHookBinding> CreateParametrizedHookMock(List<IHookBinding> hookList, params Type[] paramTypes)
  208. {
  209. var hookMock = CreateHookMock(hookList);
  210. var bindingMethod = new BindingMethod(new BindingType("AssemblyBT", "BT", "Test.BT"), "X",
  211. paramTypes.Select((paramType, i) => new BindingParameter(new RuntimeBindingType(paramType), "p" + i)),
  212. RuntimeBindingType.Void);
  213. hookMock.Setup(h => h.Method).Returns(bindingMethod);
  214. return hookMock;
  215. }
  216. private void AssertHooksWasCalledWithParam(Mock<IHookBinding> hookMock, object paramObj)
  217. {
  218. TimeSpan duration;
  219. methodBindingInvokerMock.Verify(i => i.InvokeBinding(hookMock.Object, contextManagerStub.Object,
  220. It.Is((object[] args) => args != null && args.Length > 0 && args.Any(arg => arg == paramObj)),
  221. testTracerStub.Object, out duration), Times.Once());
  222. }
  223. [Fact]
  224. public void Should_execute_before_step()
  225. {
  226. var testExecutionEngine = CreateTestExecutionEngine();
  227. RegisterStepDefinition();
  228. var hookMock = CreateHookMock(beforeStepEvents);
  229. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  230. TimeSpan duration;
  231. methodBindingInvokerMock.Verify(i => i.InvokeBinding(hookMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration), Times.Once());
  232. }
  233. [Fact]
  234. public void Should_execute_after_step()
  235. {
  236. var testExecutionEngine = CreateTestExecutionEngine();
  237. RegisterStepDefinition();
  238. var hookMock = CreateHookMock(afterStepEvents);
  239. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  240. TimeSpan duration;
  241. methodBindingInvokerMock.Verify(i => i.InvokeBinding(hookMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration), Times.Once());
  242. }
  243. [Fact]
  244. public void Should_not_execute_step_when_there_was_an_error_earlier()
  245. {
  246. var testExecutionEngine = CreateTestExecutionEngine();
  247. var stepDefMock = RegisterStepDefinition();
  248. scenarioContext.ScenarioExecutionStatus = ScenarioExecutionStatus.TestError;
  249. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  250. TimeSpan duration;
  251. methodBindingInvokerMock.Verify(i => i.InvokeBinding(stepDefMock.Object, It.IsAny<IContextManager>(), It.IsAny<object[]>(), It.IsAny<ITestTracer>(), out duration), Times.Never());
  252. }
  253. [Fact]
  254. public void Should_not_execute_step_hooks_when_there_was_an_error_earlier()
  255. {
  256. var testExecutionEngine = CreateTestExecutionEngine();
  257. RegisterStepDefinition();
  258. scenarioContext.ScenarioExecutionStatus = ScenarioExecutionStatus.TestError;
  259. var beforeStepMock = CreateHookMock(beforeStepEvents);
  260. var afterStepMock = CreateHookMock(afterStepEvents);
  261. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  262. TimeSpan duration;
  263. methodBindingInvokerMock.Verify(i => i.InvokeBinding(beforeStepMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration), Times.Never());
  264. methodBindingInvokerMock.Verify(i => i.InvokeBinding(afterStepMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration), Times.Never());
  265. }
  266. [Fact]
  267. public void Should_execute_after_step_when_step_definition_failed()
  268. {
  269. var testExecutionEngine = CreateTestExecutionEngine();
  270. RegisterFailingStepDefinition();
  271. var hookMock = CreateHookMock(afterStepEvents);
  272. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  273. TimeSpan duration;
  274. methodBindingInvokerMock.Verify(i => i.InvokeBinding(hookMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration));
  275. }
  276. [Fact]
  277. public void Should_call_step_error_handlers()
  278. {
  279. var stepErrorHandlerMock = new Mock<IStepErrorHandler>();
  280. stepErrorHandlers.Add("eh1", stepErrorHandlerMock.Object);
  281. var testExecutionEngine = CreateTestExecutionEngine();
  282. RegisterFailingStepDefinition();
  283. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  284. stepErrorHandlerMock.Verify(seh => seh.OnStepFailure(testExecutionEngine, It.IsAny<StepFailureEventArgs>()), Times.Once());
  285. }
  286. [Fact]
  287. public void Should_call_multiple_step_error_handlers()
  288. {
  289. var stepErrorHandler1Mock = new Mock<IStepErrorHandler>();
  290. var stepErrorHandler2Mock = new Mock<IStepErrorHandler>();
  291. stepErrorHandlers.Add("eh1", stepErrorHandler1Mock.Object);
  292. stepErrorHandlers.Add("eh2", stepErrorHandler2Mock.Object);
  293. var testExecutionEngine = CreateTestExecutionEngine();
  294. RegisterFailingStepDefinition();
  295. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  296. stepErrorHandler1Mock.Verify(seh => seh.OnStepFailure(testExecutionEngine, It.IsAny<StepFailureEventArgs>()), Times.Once());
  297. stepErrorHandler2Mock.Verify(seh => seh.OnStepFailure(testExecutionEngine, It.IsAny<StepFailureEventArgs>()), Times.Once());
  298. }
  299. [Fact]
  300. public void Should_be_able_to_swallow_error_in_step_error_handlers()
  301. {
  302. var stepErrorHandlerStub = new Mock<IStepErrorHandler>();
  303. stepErrorHandlers.Add("eh1", stepErrorHandlerStub.Object);
  304. stepErrorHandlerStub.Setup(seh => seh.OnStepFailure(It.IsAny<TestExecutionEngine>(), It.IsAny<StepFailureEventArgs>()))
  305. .Callback((TestExecutionEngine _, StepFailureEventArgs args) => args.IsHandled = true);
  306. var testExecutionEngine = CreateTestExecutionEngine();
  307. RegisterFailingStepDefinition();
  308. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  309. scenarioContext.ScenarioExecutionStatus.Should().Be(ScenarioExecutionStatus.OK);
  310. }
  311. [Fact]
  312. public void Step_error_handlers_should_not_swallow_error_by_default()
  313. {
  314. var stepErrorHandlerStub = new Mock<IStepErrorHandler>();
  315. stepErrorHandlers.Add("eh1", stepErrorHandlerStub.Object);
  316. var testExecutionEngine = CreateTestExecutionEngine();
  317. RegisterFailingStepDefinition();
  318. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  319. scenarioContext.ScenarioExecutionStatus.Should().Be(ScenarioExecutionStatus.TestError);
  320. }
  321. [Fact]
  322. public void Should_cleanup_step_context_after_scenario_block_hook_error()
  323. {
  324. TimeSpan duration;
  325. var testExecutionEngine = CreateTestExecutionEngine();
  326. RegisterStepDefinition();
  327. var hookMock = CreateHookMock(beforeScenarioBlockEvents);
  328. methodBindingInvokerMock.Setup(i => i.InvokeBinding(hookMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration))
  329. .Throws(new Exception("simulated error"));
  330. try
  331. {
  332. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  333. Assert.True(false, "execution of the step should have failed because of the exeption thrown by the before scenario block hook");
  334. }
  335. catch (Exception)
  336. {
  337. }
  338. methodBindingInvokerMock.Verify(i => i.InvokeBinding(hookMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration), Times.Once());
  339. contextManagerStub.Verify(cm => cm.CleanupStepContext());
  340. }
  341. [Fact]
  342. public void Should_not_execute_afterstep_when_step_is_undefined()
  343. {
  344. var testExecutionEngine = CreateTestExecutionEngine();
  345. RegisterUndefinedStepDefinition();
  346. var afterStepMock = CreateHookMock(afterStepEvents);
  347. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "undefined", null, null);
  348. TimeSpan duration;
  349. methodBindingInvokerMock.Verify(i => i.InvokeBinding(afterStepMock.Object, contextManagerStub.Object, null, testTracerStub.Object, out duration), Times.Never());
  350. }
  351. public void Should_resolve_FeautreContext_hook_parameter()
  352. {
  353. var testExecutionEngine = CreateTestExecutionEngine();
  354. RegisterStepDefinition();
  355. var hookMock = CreateParametrizedHookMock(beforeFeatureEvents, typeof(FeatureContext));
  356. testExecutionEngine.OnFeatureStart(featureInfo);
  357. AssertHooksWasCalledWithParam(hookMock, contextManagerStub.Object.FeatureContext);
  358. }
  359. [Fact]
  360. public void Should_resolve_custom_class_hook_parameter()
  361. {
  362. var testExecutionEngine = CreateTestExecutionEngine();
  363. RegisterStepDefinition();
  364. var hookMock = CreateParametrizedHookMock(beforeFeatureEvents, typeof(DummyClass));
  365. testExecutionEngine.OnFeatureStart(featureInfo);
  366. AssertHooksWasCalledWithParam(hookMock, DummyClass.LastInstance);
  367. }
  368. [Fact]
  369. public void Should_resolve_container_hook_parameter()
  370. {
  371. var testExecutionEngine = CreateTestExecutionEngine();
  372. RegisterStepDefinition();
  373. var hookMock = CreateParametrizedHookMock(beforeTestRunEvents, typeof(IObjectContainer));
  374. testExecutionEngine.OnTestRunStart();
  375. AssertHooksWasCalledWithParam(hookMock, testThreadContainer);
  376. }
  377. [Fact]
  378. public void Should_resolve_multiple_hook_parameter()
  379. {
  380. var testExecutionEngine = CreateTestExecutionEngine();
  381. RegisterStepDefinition();
  382. var hookMock = CreateParametrizedHookMock(beforeFeatureEvents, typeof(DummyClass), typeof(FeatureContext));
  383. testExecutionEngine.OnFeatureStart(featureInfo);
  384. AssertHooksWasCalledWithParam(hookMock, DummyClass.LastInstance);
  385. AssertHooksWasCalledWithParam(hookMock, contextManagerStub.Object.FeatureContext);
  386. }
  387. [Fact]
  388. public void Should_resolve_BeforeAfterTestRun_hook_parameter_from_test_thread_container()
  389. {
  390. var testExecutionEngine = CreateTestExecutionEngine();
  391. RegisterStepDefinition();
  392. var beforeHook = CreateParametrizedHookMock(beforeTestRunEvents, typeof(DummyClass));
  393. var afterHook = CreateParametrizedHookMock(afterTestRunEvents, typeof(DummyClass));
  394. testExecutionEngine.OnTestRunStart();
  395. testExecutionEngine.OnTestRunEnd();
  396. AssertHooksWasCalledWithParam(beforeHook, DummyClass.LastInstance);
  397. AssertHooksWasCalledWithParam(afterHook, DummyClass.LastInstance);
  398. testObjectResolverMock.Verify(bir => bir.ResolveBindingInstance(typeof(DummyClass), testThreadContainer),
  399. Times.Exactly(2));
  400. }
  401. [Fact]
  402. public void Should_resolve_BeforeAfterScenario_hook_parameter_from_scenario_container()
  403. {
  404. var testExecutionEngine = CreateTestExecutionEngine();
  405. RegisterStepDefinition();
  406. var beforeHook = CreateParametrizedHookMock(beforeScenarioEvents, typeof(DummyClass));
  407. var afterHook = CreateParametrizedHookMock(afterScenarioEvents, typeof(DummyClass));
  408. testExecutionEngine.OnScenarioInitialize(scenarioInfo);
  409. testExecutionEngine.OnScenarioStart();
  410. testExecutionEngine.OnScenarioEnd();
  411. AssertHooksWasCalledWithParam(beforeHook, DummyClass.LastInstance);
  412. AssertHooksWasCalledWithParam(afterHook, DummyClass.LastInstance);
  413. testObjectResolverMock.Verify(bir => bir.ResolveBindingInstance(typeof(DummyClass), scenarioContainer),
  414. Times.Exactly(2));
  415. }
  416. [Fact]
  417. public void Should_be_possible_to_register_instance_in_scenario_container_before_firing_scenario_events()
  418. {
  419. var testExecutionEngine = CreateTestExecutionEngine();
  420. var instanceToAddBeforeScenarioEventFiring = new AnotherDummyClass();
  421. var beforeHook = CreateParametrizedHookMock(beforeScenarioEvents, typeof(DummyClass));
  422. // Setup binding method mock so it attempts to resolve an instance from the scenario container.
  423. // If this fails, then the instance was not registered before the method was invoked.
  424. TimeSpan dummyOutTimeSpan;
  425. AnotherDummyClass actualInstance = null;
  426. methodBindingInvokerMock.Setup(s => s.InvokeBinding(It.IsAny<IBinding>(), It.IsAny<IContextManager>(),
  427. It.IsAny<object[]>(),It.IsAny<ITestTracer>(), out dummyOutTimeSpan))
  428. .Callback(() => actualInstance = testExecutionEngine.ScenarioContext.ScenarioContainer.Resolve<AnotherDummyClass>());
  429. testExecutionEngine.OnScenarioInitialize(scenarioInfo);
  430. testExecutionEngine.ScenarioContext.ScenarioContainer.RegisterInstanceAs(instanceToAddBeforeScenarioEventFiring);
  431. testExecutionEngine.OnScenarioStart();
  432. actualInstance.Should().BeSameAs(instanceToAddBeforeScenarioEventFiring);
  433. AssertHooksWasCalledWithParam(beforeHook, DummyClass.LastInstance);
  434. }
  435. [Fact]
  436. public void Should_resolve_BeforeAfterScenarioBlock_hook_parameter_from_scenario_container()
  437. {
  438. var testExecutionEngine = CreateTestExecutionEngine();
  439. RegisterStepDefinition();
  440. var beforeHook = CreateParametrizedHookMock(beforeScenarioBlockEvents, typeof(DummyClass));
  441. var afterHook = CreateParametrizedHookMock(afterScenarioBlockEvents, typeof(DummyClass));
  442. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  443. testExecutionEngine.OnAfterLastStep();
  444. AssertHooksWasCalledWithParam(beforeHook, DummyClass.LastInstance);
  445. AssertHooksWasCalledWithParam(afterHook, DummyClass.LastInstance);
  446. testObjectResolverMock.Verify(bir => bir.ResolveBindingInstance(typeof(DummyClass), scenarioContainer),
  447. Times.Exactly(2));
  448. }
  449. [Fact]
  450. public void Should_resolve_BeforeAfterStep_hook_parameter_from_scenario_container()
  451. {
  452. var testExecutionEngine = CreateTestExecutionEngine();
  453. RegisterStepDefinition();
  454. var beforeHook = CreateParametrizedHookMock(beforeStepEvents, typeof(DummyClass));
  455. var afterHook = CreateParametrizedHookMock(afterStepEvents, typeof(DummyClass));
  456. testExecutionEngine.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  457. AssertHooksWasCalledWithParam(beforeHook, DummyClass.LastInstance);
  458. AssertHooksWasCalledWithParam(afterHook, DummyClass.LastInstance);
  459. testObjectResolverMock.Verify(bir => bir.ResolveBindingInstance(typeof(DummyClass), scenarioContainer),
  460. Times.Exactly(2));
  461. }
  462. [Fact]
  463. public void Should_resolve_BeforeAfterFeature_hook_parameter_from_feature_container()
  464. {
  465. var testExecutionEngine = CreateTestExecutionEngine();
  466. RegisterStepDefinition();
  467. var beforeHook = CreateParametrizedHookMock(beforeFeatureEvents, typeof(DummyClass));
  468. var afterHook = CreateParametrizedHookMock(afterFeatureEvents, typeof(DummyClass));
  469. testExecutionEngine.OnFeatureStart(featureInfo);
  470. testExecutionEngine.OnFeatureEnd();
  471. AssertHooksWasCalledWithParam(beforeHook, DummyClass.LastInstance);
  472. AssertHooksWasCalledWithParam(afterHook, DummyClass.LastInstance);
  473. testObjectResolverMock.Verify(bir => bir.ResolveBindingInstance(typeof(DummyClass), featureContainer),
  474. Times.Exactly(2));
  475. }
  476. [Fact]
  477. public void Should_TryToSend_ProjectRunningEvent()
  478. {
  479. var testExecutionEngine = CreateTestExecutionEngine();
  480. testExecutionEngine.OnTestRunStart();
  481. _analyticsTransmitter.Verify(at => at.TransmitSpecFlowProjectRunningEvent(It.IsAny<SpecFlowProjectRunningEvent>()), Times.Once);
  482. }
  483. [Theory]
  484. [InlineData(1, 3)]
  485. [InlineData(3, 1)]
  486. public void Should_execute_all_ISkippedStepHandlers_for_each_skipped_step(int numberOfHandlers, int numberOfSkippedSteps)
  487. {
  488. var sut = CreateTestExecutionEngine();
  489. scenarioContext.ScenarioExecutionStatus = ScenarioExecutionStatus.TestError;
  490. var skippedStepHandlerMocks = new List<Mock<ISkippedStepHandler>>();
  491. for (int i = 0; i < numberOfHandlers; i++)
  492. {
  493. var mockHandler = new Mock<ISkippedStepHandler>();
  494. mockHandler.Setup(b => b.Handle(It.IsAny<ScenarioContext>())).Verifiable();
  495. skippedStepHandlerMocks.Add(mockHandler);
  496. scenarioContext.ScenarioContainer.RegisterInstanceAs(mockHandler.Object, i.ToString());
  497. }
  498. for (int i = 0; i < numberOfSkippedSteps; i++)
  499. {
  500. RegisterStepDefinition();
  501. sut.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  502. }
  503. foreach (var handler in skippedStepHandlerMocks)
  504. {
  505. handler.Verify(action => action.Handle(It.IsAny<ScenarioContext>()), Times.Exactly(numberOfSkippedSteps));
  506. }
  507. }
  508. [Fact]
  509. public void Should_not_change_ScenarioExecutionStatus_on_dummy_ISkippedStepHandler()
  510. {
  511. var sut = CreateTestExecutionEngine();
  512. scenarioContext.ScenarioExecutionStatus = ScenarioExecutionStatus.TestError;
  513. var mockHandler = new Mock<ISkippedStepHandler>();
  514. mockHandler.Setup(b => b.Handle(It.IsAny<ScenarioContext>())).Callback(() => Console.WriteLine("ISkippedStepHandler"));
  515. scenarioContext.ScenarioContainer.RegisterInstanceAs(mockHandler.Object);
  516. RegisterStepDefinition();
  517. sut.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  518. scenarioContext.ScenarioExecutionStatus.Should().Be(ScenarioExecutionStatus.TestError);
  519. }
  520. [Fact]
  521. public void Should_not_call_ISkippedStepHandler_on_UndefinedStepDefinition()
  522. {
  523. var sut = CreateTestExecutionEngine();
  524. scenarioContext.ScenarioExecutionStatus = ScenarioExecutionStatus.TestError;
  525. var mockHandler = new Mock<ISkippedStepHandler>();
  526. mockHandler.Setup(b => b.Handle(It.IsAny<ScenarioContext>())).Verifiable();
  527. scenarioContext.ScenarioContainer.RegisterInstanceAs(mockHandler.Object);
  528. RegisterUndefinedStepDefinition();
  529. sut.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  530. mockHandler.Verify(action => action.Handle(It.IsAny<ScenarioContext>()), Times.Never);
  531. }
  532. [Fact]
  533. public void Should_not_call_ISkippedStepHandler_on_succesfull_test_run()
  534. {
  535. var sut = CreateTestExecutionEngine();
  536. var mockHandler = new Mock<ISkippedStepHandler>();
  537. mockHandler.Setup(b => b.Handle(It.IsAny<ScenarioContext>())).Verifiable();
  538. scenarioContext.ScenarioContainer.RegisterInstanceAs(mockHandler.Object);
  539. RegisterStepDefinition();
  540. sut.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  541. mockHandler.Verify(action => action.Handle(It.IsAny<ScenarioContext>()), Times.Never);
  542. }
  543. [Fact]
  544. public void Should_not_call_ISkippedStepHandler_if_only_last_step_is_failing()
  545. {
  546. var sut = CreateTestExecutionEngine();
  547. var mockHandler = new Mock<ISkippedStepHandler>();
  548. mockHandler.Setup(b => b.Handle(It.IsAny<ScenarioContext>())).Callback(() => Console.WriteLine("ISkippedStepHandler"));
  549. scenarioContext.ScenarioContainer.RegisterInstanceAs(mockHandler.Object);
  550. RegisterFailingStepDefinition();
  551. sut.Step(StepDefinitionKeyword.Given, null, "foo", null, null);
  552. mockHandler.Verify(action => action.Handle(It.IsAny<ScenarioContext>()), Times.Never);
  553. }
  554. }
  555. }