PageRenderTime 28ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/Tests/TechTalk.SpecFlow.GeneratorTests/UnitTestProvider/XUnit2TestGeneratorProviderTests.cs

http://github.com/techtalk/SpecFlow
C# | 404 lines | 312 code | 61 blank | 31 comment | 23 complexity | 7acb2f141add09dbcc5b30c3f28ee655 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. using System.CodeDom;
  2. using System.Globalization;
  3. using System.IO;
  4. using System.Linq;
  5. using FluentAssertions;
  6. using Microsoft.CSharp;
  7. using TechTalk.SpecFlow.Generator.CodeDom;
  8. using TechTalk.SpecFlow.Generator.Interfaces;
  9. using TechTalk.SpecFlow.Generator.UnitTestProvider;
  10. using TechTalk.SpecFlow.Parser;
  11. using Xunit;
  12. namespace TechTalk.SpecFlow.GeneratorTests.UnitTestProvider
  13. {
  14. public class XUnit2TestGeneratorProviderTests
  15. {
  16. private const string XUnitInlineDataAttribute = "Xunit.InlineDataAttribute";
  17. private const string SampleFeatureFile = @"
  18. Feature: Sample feature file
  19. Scenario: Simple scenario
  20. Given there is something
  21. When I do something
  22. Then something should happen";
  23. [Fact]
  24. public void XUnit2TestGeneratorProvider_OnlyVariantName_ShouldSetInlineDataAttributesCorrectly()
  25. {
  26. // ARRANGE
  27. const string sampleFeatureFile = @"
  28. Feature: Sample feature file
  29. @mytag
  30. Scenario Outline: Simple Scenario Outline
  31. Given there is something
  32. """"""
  33. long string
  34. """"""
  35. When I do <what>
  36. | foo | bar |
  37. | 1 | 2 |
  38. Then something should happen
  39. Examples:
  40. | what |
  41. | something |
  42. | something else |
  43. ";
  44. var document = ParseDocumentFromString(sampleFeatureFile);
  45. var sampleTestGeneratorProvider = new XUnit2TestGeneratorProvider(new CodeDomHelper(CodeDomProviderLanguage.CSharp), new ProjectSettings() { DefaultNamespace = "Target"});
  46. var converter = sampleTestGeneratorProvider.CreateUnitTestConverter();
  47. // ACT
  48. var code = converter.GenerateUnitTestFixture(document, "TestClassName", "Target.Namespace");
  49. // ASSERT
  50. var inlineDataAttributes = code.Class()
  51. .Members()
  52. .Single(m => m.Name == "SimpleScenarioOutline")
  53. .CustomAttributes()
  54. .Where(a => a.Name == XUnitInlineDataAttribute)
  55. .ToArray();
  56. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "something");
  57. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "something else");
  58. }
  59. [Fact]
  60. public void XUnit2TestGeneratorProvider_ExamplesFirstColumnIsDifferentAndMultipleColumns_ShouldSetDescriptionCorrectly()
  61. {
  62. // ARRANGE
  63. const string sampleFeatureFileMultipleColumns = @"
  64. Feature: Sample feature file
  65. Scenario: Simple scenario
  66. Given there is something
  67. When I do something
  68. Then something should happen
  69. @mytag
  70. Scenario Outline: Simple Scenario Outline
  71. Given there is something
  72. """"""
  73. long string
  74. """"""
  75. When I do <what>
  76. | foo | bar |
  77. | 1 | 2 |
  78. Then something should happen
  79. Examples:
  80. | what | what else |
  81. | something | thing |
  82. | something else | different thing |
  83. ";
  84. var document = ParseDocumentFromString(sampleFeatureFileMultipleColumns);
  85. var sampleTestGeneratorProvider = new XUnit2TestGeneratorProvider(new CodeDomHelper(CodeDomProviderLanguage.CSharp), new ProjectSettings() { DefaultNamespace = "Target" });
  86. var converter = sampleTestGeneratorProvider.CreateUnitTestConverter();
  87. // ACT
  88. var code = converter.GenerateUnitTestFixture(document, "TestClassName", "Target.Namespace");
  89. // ASSERT
  90. var inlineDataAttributes = code.Class()
  91. .Members()
  92. .Single(m => m.Name == "SimpleScenarioOutline")
  93. .CustomAttributes()
  94. .Where(a => a.Name == XUnitInlineDataAttribute)
  95. .ToArray();
  96. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "something");
  97. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "something else");
  98. }
  99. [Fact]
  100. public void XUnit2TestGeneratorProvider_ExampleIdentifier_ShouldSetInlineDataAttributesCorrectly()
  101. {
  102. // ARRANGE
  103. const string sampleFeatureFileWithMultipleExampleSets = @"
  104. Feature: Sample feature file
  105. Scenario: Simple scenario
  106. Given there is something
  107. When I do something
  108. Then something should happen
  109. @mytag
  110. Scenario Outline: Simple Scenario Outline
  111. Given there is something
  112. """"""
  113. long string
  114. """"""
  115. When I do <what>
  116. | foo | bar |
  117. | 1 | 2 |
  118. Then something should happen
  119. Examples:
  120. | what |
  121. | something |
  122. | something else |
  123. Examples:
  124. | what |
  125. | another |
  126. | and another |
  127. ";
  128. var document = ParseDocumentFromString(sampleFeatureFileWithMultipleExampleSets);
  129. var sampleTestGeneratorProvider = new XUnit2TestGeneratorProvider(new CodeDomHelper(CodeDomProviderLanguage.CSharp), new ProjectSettings() { DefaultNamespace = "Target" });
  130. var converter = sampleTestGeneratorProvider.CreateUnitTestConverter();
  131. // ACT
  132. var code = converter.GenerateUnitTestFixture(document, "TestClassName", "Target.Namespace");
  133. // ASSERT
  134. var inlineDataAttributes = code.Class()
  135. .Members()
  136. .Single(m => m.Name == "SimpleScenarioOutline")
  137. .CustomAttributes()
  138. .Where(a => a.Name == XUnitInlineDataAttribute)
  139. .ToArray();
  140. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "something");
  141. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "something else");
  142. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "another");
  143. inlineDataAttributes.Should().ContainSingle(attribute => attribute.ArgumentValues().First() as string == "and another");
  144. }
  145. [Fact]
  146. public void XUnit2TestGeneratorProvider_ShouldSetDisplayNameForTheoryAttribute()
  147. {
  148. // Arrange
  149. var provider = new XUnit2TestGeneratorProvider(new CodeDomHelper(new CSharpCodeProvider()), new ProjectSettings() { DefaultNamespace = "Target" });
  150. var context = new Generator.TestClassGenerationContext(
  151. unitTestGeneratorProvider: null,
  152. document: new SpecFlowDocument(
  153. feature: new SpecFlowFeature(
  154. tags: null,
  155. location: null,
  156. language: null,
  157. keyword: null,
  158. name: "",
  159. description: null,
  160. children: null
  161. ),
  162. comments: null,
  163. sourceFilePath: null),
  164. ns: null,
  165. testClass: null,
  166. testRunnerField: null,
  167. testClassInitializeMethod: null,
  168. testClassCleanupMethod: null,
  169. testInitializeMethod: null,
  170. testCleanupMethod: null,
  171. scenarioInitializeMethod: null,
  172. scenarioStartMethod:null,
  173. scenarioCleanupMethod: null,
  174. featureBackgroundMethod: null,
  175. generateRowTests: false);
  176. var codeMemberMethod = new CodeMemberMethod();
  177. // Act
  178. provider.SetRowTest(context, codeMemberMethod, "Foo");
  179. // Assert
  180. var modifiedAttribute = codeMemberMethod.CustomAttributes.OfType<CodeAttributeDeclaration>()
  181. .FirstOrDefault(a => a.Name == "Xunit.SkippableTheoryAttribute");
  182. modifiedAttribute.Should().NotBeNull();
  183. var attribute = modifiedAttribute.Arguments
  184. .OfType<CodeAttributeArgument>()
  185. .FirstOrDefault(a => a.Name == "DisplayName");
  186. attribute.Should().NotBeNull();
  187. var primitiveExpression = attribute.Value as CodePrimitiveExpression;
  188. primitiveExpression.Should().NotBeNull();
  189. primitiveExpression.Value.Should().Be("Foo");
  190. }
  191. [Fact]
  192. public void XUnit2TestGeneratorProvider_ShouldSetSkipAttributeForTheory()
  193. {
  194. // Arrange
  195. var provider = new XUnit2TestGeneratorProvider(new CodeDomHelper(new CSharpCodeProvider()), new ProjectSettings() { DefaultNamespace = "Target" });
  196. // Act
  197. var codeMemberMethod = new CodeMemberMethod
  198. {
  199. CustomAttributes =
  200. new CodeAttributeDeclarationCollection(
  201. new[] { new CodeAttributeDeclaration(XUnit2TestGeneratorProvider.THEORY_ATTRIBUTE) })
  202. };
  203. provider.SetTestMethodIgnore(null, codeMemberMethod);
  204. // Assert
  205. var modifiedAttribute = codeMemberMethod.CustomAttributes.OfType<CodeAttributeDeclaration>()
  206. .FirstOrDefault(a => a.Name == XUnit2TestGeneratorProvider.THEORY_ATTRIBUTE);
  207. modifiedAttribute.Should().NotBeNull();
  208. var attribute = modifiedAttribute.Arguments
  209. .OfType<CodeAttributeArgument>()
  210. .FirstOrDefault(a => a.Name == XUnit2TestGeneratorProvider.THEORY_ATTRIBUTE_SKIP_PROPERTY_NAME);
  211. attribute.Should().NotBeNull();
  212. var primitiveExpression = attribute.Value as CodePrimitiveExpression;
  213. primitiveExpression.Should().NotBeNull();
  214. primitiveExpression.Value.Should().Be(XUnit2TestGeneratorProvider.SKIP_REASON);
  215. }
  216. /*
  217. * Based on w1ld's `Should_set_skip_attribute_for_theory`,
  218. * refactor as appropriate.
  219. */
  220. [Fact]
  221. public void XUnit2TestGeneratorProvider_ShouldSetDisplayNameForFactAttribute()
  222. {
  223. // Arrange
  224. var provider = new XUnit2TestGeneratorProvider(new CodeDomHelper(new CSharpCodeProvider()), new ProjectSettings() { DefaultNamespace = "Target" });
  225. var context = new Generator.TestClassGenerationContext(
  226. unitTestGeneratorProvider: null,
  227. document: new Parser.SpecFlowDocument(
  228. feature: new SpecFlowFeature(
  229. tags: null,
  230. location: null,
  231. language: null,
  232. keyword: null,
  233. name: "",
  234. description: null,
  235. children: null
  236. ),
  237. comments: null,
  238. sourceFilePath: null),
  239. ns: null,
  240. testClass: null,
  241. testRunnerField: null,
  242. testClassInitializeMethod: null,
  243. testClassCleanupMethod: null,
  244. testInitializeMethod: null,
  245. testCleanupMethod: null,
  246. scenarioInitializeMethod: null,
  247. scenarioStartMethod: null,
  248. scenarioCleanupMethod: null,
  249. featureBackgroundMethod: null,
  250. generateRowTests: false);
  251. var codeMemberMethod = new CodeMemberMethod();
  252. // Act
  253. provider.SetTestMethod(context, codeMemberMethod, "Foo");
  254. // Assert
  255. var modifiedAttribute = codeMemberMethod.CustomAttributes.OfType<CodeAttributeDeclaration>()
  256. .FirstOrDefault(a => a.Name == "Xunit.SkippableFactAttribute");
  257. modifiedAttribute.Should().NotBeNull();
  258. var attribute = modifiedAttribute.Arguments
  259. .OfType<CodeAttributeArgument>()
  260. .FirstOrDefault(a => a.Name == "DisplayName");
  261. attribute.Should().NotBeNull();
  262. var primitiveExpression = attribute.Value as CodePrimitiveExpression;
  263. primitiveExpression.Should().NotBeNull();
  264. primitiveExpression.Value.Should().Be("Foo");
  265. }
  266. [Fact]
  267. public void XUnit2TestGeneratorProvider_ShouldInitializeTestOutputHelperFieldInConstructor()
  268. {
  269. // ARRANGE
  270. var document = ParseDocumentFromString(SampleFeatureFile);
  271. var provider = new XUnit2TestGeneratorProvider(new CodeDomHelper(CodeDomProviderLanguage.CSharp), new ProjectSettings() { DefaultNamespace = "Target" });
  272. var converter = provider.CreateUnitTestConverter();
  273. // ACT
  274. var code = converter.GenerateUnitTestFixture(document, "TestClassName", "Target.Namespace");
  275. code.Should().NotBeNull();
  276. // ASSERT
  277. var classConstructor = code.Class().Members().Single(m => m.Name == ".ctor");
  278. classConstructor.Should().NotBeNull();
  279. classConstructor.Parameters.Count.Should().Be(3);
  280. classConstructor.Parameters[2].Type.BaseType.Should().Be("Xunit.Abstractions.ITestOutputHelper");
  281. classConstructor.Parameters[2].Name.Should().Be("testOutputHelper");
  282. var initOutputHelper = classConstructor.Statements.OfType<CodeAssignStatement>().First();
  283. initOutputHelper.Should().NotBeNull();
  284. ((CodeFieldReferenceExpression)initOutputHelper.Left).FieldName.Should().Be("_testOutputHelper");
  285. ((CodeVariableReferenceExpression)initOutputHelper.Right).VariableName.Should().Be("testOutputHelper");
  286. }
  287. [Fact]
  288. public void XUnit2TestGeneratorProvider_Should_add_testOutputHelper_field_in_class()
  289. {
  290. // ARRANGE
  291. var document = ParseDocumentFromString(SampleFeatureFile);
  292. var provider = new XUnit2TestGeneratorProvider(new CodeDomHelper(CodeDomProviderLanguage.CSharp), new ProjectSettings() { DefaultNamespace = "Target" });
  293. var converter = provider.CreateUnitTestConverter();
  294. // ACT
  295. var code = converter.GenerateUnitTestFixture(document, "TestClassName", "Target.Namespace");
  296. // ASSERT
  297. code.Should().NotBeNull();
  298. var loggerInstance = code.Class().Members.OfType<CodeMemberField>().First(m => m.Name == @"_testOutputHelper");
  299. loggerInstance.Type.BaseType.Should().Be("Xunit.Abstractions.ITestOutputHelper");
  300. loggerInstance.Attributes.Should().Be(MemberAttributes.Private | MemberAttributes.Final);
  301. }
  302. [Fact]
  303. public void XUnit2TestGeneratorProvider_Should_register_testOutputHelper_on_scenario_setup()
  304. {
  305. // ARRANGE
  306. var document = ParseDocumentFromString(SampleFeatureFile);
  307. var provider = new XUnit2TestGeneratorProvider(new CodeDomHelper(CodeDomProviderLanguage.CSharp), new ProjectSettings() { DefaultNamespace = "Target" });
  308. var converter = provider.CreateUnitTestConverter();
  309. // ACT
  310. var code = converter.GenerateUnitTestFixture(document, "TestClassName", "Target.Namespace");
  311. // ASSERT
  312. code.Should().NotBeNull();
  313. var scenarioStartMethod = code.Class().Members().Single(m => m.Name == @"ScenarioInitialize");
  314. scenarioStartMethod.Statements.Count.Should().Be(2);
  315. var expression = scenarioStartMethod.Statements[1].Should().BeOfType<CodeExpressionStatement>()
  316. .Which.Expression.Should().BeOfType<CodeMethodInvokeExpression>().Which;
  317. expression.Parameters[0].Should().BeOfType<CodeVariableReferenceExpression>()
  318. .Which.VariableName.Should().Be("_testOutputHelper");
  319. var method = expression.Method;
  320. method.TargetObject.Should().BeOfType<CodePropertyReferenceExpression>()
  321. .Which.PropertyName.Should().Be("ScenarioContainer");
  322. method.MethodName.Should().Be("RegisterInstanceAs");
  323. method.TypeArguments.Should().NotBeNullOrEmpty();
  324. method.TypeArguments[0].BaseType.Should().Be("Xunit.Abstractions.ITestOutputHelper");
  325. }
  326. public SpecFlowDocument ParseDocumentFromString(string documentSource, CultureInfo parserCultureInfo = null)
  327. {
  328. var parser = new SpecFlowGherkinParser(parserCultureInfo ?? new CultureInfo("en-US"));
  329. using (var reader = new StringReader(documentSource))
  330. {
  331. var document = parser.Parse(reader, null);
  332. document.Should().NotBeNull();
  333. return document;
  334. }
  335. }
  336. }
  337. }