/// <summary> /// Asserts test details for tests contained within the "BoostUnitTestSample.cpp" source file /// </summary> /// <param name="tests">The discovered test case enumeration</param> /// <param name="source">The source for which "BoostUnitTestSample.cpp" was compiled to</param> /// <param name="codeFilePath">The fully qualified path for the on-disk version of "BoostUnitTestSample.cpp"</param> private void AssertBoostUnitTestSampleTestDetails(IEnumerable <VSTestCase> tests, string source, string codeFilePath) { VSTestCase test123 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Suite1/BoostUnitTest123"), source); AssertSourceDetails(test123, codeFilePath, 16); VSTestCase test1234 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Suite1/BoostUnitTest1234"), source); AssertSourceDetails(test1234, codeFilePath, 20); VSTestCase test12345 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("BoostUnitTest12345"), source); AssertSourceDetails(test12345, codeFilePath, 26); VSTestCase testint = AssertTestDetails(tests, QualifiedNameBuilder.FromString("my_test<int>"), source); AssertSourceDetails(testint, codeFilePath, 33); VSTestCase testlong = AssertTestDetails(tests, QualifiedNameBuilder.FromString("my_test<long>"), source); AssertSourceDetails(testlong, codeFilePath, 33); VSTestCase testchar = AssertTestDetails(tests, QualifiedNameBuilder.FromString("my_test<char>"), source); AssertSourceDetails(testchar, codeFilePath, 33); }
/// <summary> /// Parses a TestCase node. /// </summary> /// <param name="node">The XPathNavigator pointing to a TestCase node.</param> /// <param name="parent">The parent TestSuite to which TestUnits are attached to.</param> /// <param name="collection">The TestResultCollection which will host the result.</param> private static void ParseTestCaseReport(XPathNavigator node, TestSuite parent, TestResultCollection collection) { QualifiedNameBuilder fullname = new QualifiedNameBuilder(parent); fullname.Push(node.GetAttribute(Xml.Name, string.Empty)); TestCase testCase = null; // If the test is already available, reuse it TestResult current = collection[fullname.ToString()]; if (current != null) { testCase = current.Unit as TestCase; } // Else construct and add it to the appropriate parent if (testCase == null) { testCase = new TestCase(fullname.Peek(), parent); } TestResult result = ParseTestResult(node, testCase, collection); // Aggregate results. Common use-case in BOOST_DATA_TEST_CASE. collection[fullname.ToString()] = Aggregate(result, current); }
/// <summary> /// Parses a TestCase log node. /// </summary> /// <param name="node">The TestCase Xml node to parse.</param> /// <param name="path">The QualifiedNameBuilder which hosts the current fully qualified path.</param> /// <param name="collection">The test result collection which will host the result.</param> private static void ParseTestCaseLog(XmlNode node, QualifiedNameBuilder path, IDictionary <string, TestResult> collection) { // Temporarily push TestCase on TestSuite name builder to acquire the fully qualified name of the TestCase path.Push(node.Attributes[Xml.Name].Value); var currentPath = path.ToString(); // Acquire result record of this TestCase TestResult result = null; if (!collection.TryGetValue(currentPath, out result)) { result = new TestResult(collection); collection[currentPath] = result; } // Reset path to original value path.Pop(); XmlNode testingTime = node.SelectSingleNode(Xml.TestingTime); if (testingTime != null) { // Boost test testing time is listed in microseconds result.Duration += ulong.Parse(testingTime.InnerText, CultureInfo.InvariantCulture); } ParseTestCaseLogEntries(node.ChildNodes, result); }
/// <summary> /// Asserts test details for tests contained within the "BoostFixtureTestSuite.cpp" source file /// </summary> /// <param name="tests">The discovered test case enumeration</param> /// <param name="source">The source for which "BoostFixtureTestSuite.cpp" was compiled to</param> /// <param name="codeFilePath">The fully qualified path for the on-disk version of "BoostFixtureTestSuite.cpp"</param> private void AssertBoostFixtureTestSuiteTestDetails(IEnumerable <VSTestCase> tests, string source, string codeFilePath) { VSTestCase test1 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("FixtureSuite1/BoostTest1"), source); AssertSourceDetails(test1, codeFilePath, 30); VSTestCase test2 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("FixtureSuite1/BoostTest2"), source); AssertSourceDetails(test2, codeFilePath, 35); VSTestCase test3 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("BoostTest3"), source); AssertSourceDetails(test3, codeFilePath, 43); VSTestCase test4 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("FixtureSuite2/Fixturetest_case1"), source); AssertSourceDetails(test4, codeFilePath, 50); VSTestCase testint = AssertTestDetails(tests, QualifiedNameBuilder.FromString("FixtureSuite2/TemplatedTest<int>"), source); AssertSourceDetails(testint, codeFilePath, 57); VSTestCase testlong = AssertTestDetails(tests, QualifiedNameBuilder.FromString("FixtureSuite2/TemplatedTest<long>"), source); AssertSourceDetails(testlong, codeFilePath, 57); VSTestCase testchar = AssertTestDetails(tests, QualifiedNameBuilder.FromString("FixtureSuite2/TemplatedTest<char>"), source); AssertSourceDetails(testchar, codeFilePath, 57); }
/// <summary> /// Asserts general test properties /// </summary> /// <param name="tests">The enumeration of discovered tests</param> /// <param name="qualifiedName">The qualified test name which is to be tested</param> /// <param name="source">The source from which the test should have been discovered</param> /// <param name="info">Optional source file information related to the test under question</param> private void AssertVSTestCaseProperties(IEnumerable <VSTestCase> tests, QualifiedNameBuilder qualifiedName, string source, SourceFileInfo info) { VSTestCase test = tests.FirstOrDefault((_test) => (_test.FullyQualifiedName == qualifiedName.ToString())); Assert.That(test, Is.Not.Null); Assert.That(test.DisplayName, Is.EqualTo(qualifiedName.Peek())); Assert.That(test.Source, Is.EqualTo(source)); Assert.That(test.ExecutorUri, Is.EqualTo(BoostTestExecutor.ExecutorUri)); if (info != null) { Assert.That(test.CodeFilePath, Is.EqualTo(info.File)); Assert.That(test.LineNumber, Is.EqualTo(info.LineNumber)); } Assert.That(test.Traits.Count(), Is.EqualTo(1)); Trait trait = test.Traits.First(); Assert.That(trait.Name, Is.EqualTo(VSTestModel.TestSuiteTrait)); string suite = qualifiedName.Pop().ToString(); if (string.IsNullOrEmpty(suite)) { suite = qualifiedName.MasterTestSuite; } Assert.That(trait.Value, Is.EqualTo(suite)); }
private void AssertBoostUnitTestSampleRequiringUseOfFilters(IEnumerable <VSTestCase> tests, string source, string codeFilePath) { VSTestCase test1 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Suite1/BoostUnitTest123"), source); AssertSourceDetails(test1, codeFilePath, 16); VSTestCase test2 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Suite1/BoostUnitTest1234"), source); AssertSourceDetails(test2, codeFilePath, 20); VSTestCase test3 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("BoostUnitTest12345"), source); AssertSourceDetails(test3, codeFilePath, 26); VSTestCase testint = AssertTestDetails(tests, QualifiedNameBuilder.FromString("my_test<int>"), source); AssertSourceDetails(testint, codeFilePath, 40); VSTestCase testlong = AssertTestDetails(tests, QualifiedNameBuilder.FromString("my_test<long>"), source); AssertSourceDetails(testlong, codeFilePath, 40); VSTestCase testchar = AssertTestDetails(tests, QualifiedNameBuilder.FromString("my_test<char>"), source); AssertSourceDetails(testchar, codeFilePath, 40); VSTestCase testConditional = AssertTestDetails(tests, QualifiedNameBuilder.FromString("BoostUnitTestConditional"), source); AssertSourceDetails(testConditional, codeFilePath, 54); VSTestCase testMultiline = AssertTestDetails(tests, QualifiedNameBuilder.FromString("some_test"), source); AssertSourceDetails(testMultiline, codeFilePath, 72); }
/// <summary> /// Parses a TestSuite log node. /// </summary> /// <param name="node">The TestSuite Xml node to parse.</param> /// <param name="path">The QualifiedNameBuilder which hosts the current fully qualified path.</param> /// <param name="collection">The test result collection which will host the result.</param> private static void ParseTestSuiteLog(XmlNode node, QualifiedNameBuilder path, IDictionary <string, TestResult> collection) { path.Push(node.Attributes[Xml.Name].Value); ParseTestUnitsLog(node.ChildNodes, path, collection); path.Pop(); }
/// <summary> /// Creates a Visual Studio TestCase based on the provided information /// </summary> /// <param name="fullyQualifiedName">The fully qualified name of the test case</param> /// <param name="source">The test case source</param> /// <returns>A Visual Studio TestCase intended for BoostTestExecutor execution</returns> private VSTestCase CreateTestCase(string fullyQualifiedName, string source) { VSTestCase test = new VSTestCase(fullyQualifiedName, BoostTestExecutor.ExecutorUri, source); test.Traits.Add(VSTestModel.TestSuiteTrait, QualifiedNameBuilder.FromString(fullyQualifiedName).Pop().ToString()); return(test); }
/// <summary> /// Asserts general test details for the test with the requested fully qualified name /// </summary> /// <param name="tests">The discovered test case enumeration</param> /// <param name="fqn">The fully qualified name of the test case to test</param> /// <param name="source">The expected test case source</param> /// <returns>The test case which has been tested</returns> private VSTestCase AssertTestDetails(IEnumerable <VSTestCase> tests, QualifiedNameBuilder fqn, string source) { VSTestCase vsTest = tests.FirstOrDefault(test => test.FullyQualifiedName == fqn.ToString()); Assert.That(vsTest, Is.Not.Null); AssertTestDetails(vsTest, fqn, source); return(vsTest); }
private static SyntaxNode GetUpdatedNode(SyntaxNode node, SyntaxGenerator generator, string name) { return(node switch { // Many usages (constructing a type, casting to a type, etc.) will use a qualified name syntax // to refer to the type. var nameSyntax when nameSyntax.IsNameSyntax() => QualifiedNameBuilder.BuildQualifiedNameSyntax(generator, name), // Accessing a static member of a type will use a member access expression to refer to the type. var maeSyntax when maeSyntax.IsMemberAccessExpression() => QualifiedNameBuilder.BuildMemberAccessExpression(generator, name), // Because the node is retrieved by location, it may sometimes be necessary to check children. _ => GetUpdatedNode(node.ChildNodes().FirstOrDefault(), generator, name) });
/// <summary> /// Asserts general test details for the provided test case /// </summary> /// <param name="vsTest">The test case to test</param> /// <param name="fqn">The expected test case fully qualified name</param> /// <param name="source">The expected test case source</param> private void AssertTestDetails(VSTestCase vsTest, QualifiedNameBuilder fqn, string source) { Assert.That(vsTest, Is.Not.Null); Assert.That(vsTest.DisplayName, Is.EqualTo(fqn.Peek())); Assert.That(vsTest.ExecutorUri, Is.EqualTo(BoostTestExecutor.ExecutorUri)); Assert.That(vsTest.Source, Is.EqualTo(source)); string suite = fqn.Pop().ToString(); if (string.IsNullOrEmpty(suite)) { suite = QualifiedNameBuilder.DefaultMasterTestSuiteName; } Assert.That(vsTest.Traits.Where((trait) => (trait.Name == VSTestModel.TestSuiteTrait) && (trait.Value == suite)).Count(), Is.EqualTo(1)); }
/// <summary> /// Parses child TestUnit nodes. /// </summary> /// <param name="nodes">The collection of Xml nodes which are valid TestUnit nodes.</param> /// <param name="path">The QualifiedNameBuilder which hosts the current fully qualified path.</param> /// <param name="collection">The test result collection which will host the result.</param> private static void ParseTestUnitsLog(XmlNodeList nodes, QualifiedNameBuilder path, IDictionary <string, TestResult> collection) { foreach (XmlNode child in nodes) { if (child.NodeType == XmlNodeType.Element) { if (child.Name == Xml.TestSuite) { ParseTestSuiteLog(child, path, collection); } else if (child.Name == Xml.TestCase) { ParseTestCaseLog(child, path, collection); } } } }
public void DiscoverTestsUsingRunSettings() { using (DummySolution solution = new DummySolution(Source, new string[] { BoostUnitTestSampleRequiringUseOfFilters })) { DefaultTestContext context = new DefaultTestContext(); context.RegisterSettingProvider(BoostTestAdapterSettings.XmlRootName, new BoostTestAdapterSettingsProvider()); context.LoadEmbeddedSettings("BoostTestAdapterNunit.Resources.Settings.conditionalIncludesDisabled.runsettings"); IEnumerable <VSTestCase> vsTests = Discover(solution, context); Assert.That(vsTests.Count(), Is.EqualTo(9)); AssertBoostUnitTestSampleRequiringUseOfFilters(vsTests, solution); VSTestCase testConditional = AssertTestDetails(vsTests, QualifiedNameBuilder.FromString("BoostUnitTestShouldNotAppear3"), Source); AssertSourceDetails(testConditional, solution.SourceFileResourcePaths.First().Path, 47); } }
/// <summary> /// Asserts test details for tests contained within the "BoostFixtureTestCase.cpp" source file /// </summary> /// <param name="tests">The discovered test case enumeration</param> /// <param name="source">The source for which "BoostFixtureTestCase.cpp" was compiled to</param> /// <param name="codeFilePath">The fully qualified path for the on-disk version of "BoostFixtureTestCase.cpp"</param> private void AssertBoostFixtureTestCaseTestDetails(IEnumerable <VSTestCase> tests, string source, string codeFilePath) { VSTestCase test1 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Suit1/BoostUnitTest1"), source); AssertSourceDetails(test1, codeFilePath, 19); VSTestCase test2 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Suit1/Fixturetest_case1"), source); AssertSourceDetails(test2, codeFilePath, 24); VSTestCase test3 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Suit1/Fixturetest_case2"), source); AssertSourceDetails(test3, codeFilePath, 30); VSTestCase test4 = AssertTestDetails(tests, QualifiedNameBuilder.FromString("Fixturetest_case3"), source); AssertSourceDetails(test4, codeFilePath, 37); }
public void DiscoveryFileMapWithInvalidDiscovery() { using (var listing = TestHelper.CopyEmbeddedResourceToTempDirectory("BoostTestAdapterNunit.Resources.TestLists", "sample.test.list.xml")) using (var invalid_listing = TestHelper.CopyEmbeddedResourceToTempDirectory("BoostTestAdapterNunit.Resources.TestLists", "invalid.test.list.xml")) { ExternalBoostTestRunnerSettings settings = new ExternalBoostTestRunnerSettings { DiscoveryMethodType = DiscoveryMethodType.DiscoveryFileMap }; settings.DiscoveryFileMap["test_2.dll"] = invalid_listing.Path; settings.DiscoveryFileMap["test_1.dll"] = listing.Path; ExternalDiscoverer discoverer = new ExternalDiscoverer(settings, DummyVSProvider.Default); DefaultTestContext context = new DefaultTestContext(); ConsoleMessageLogger logger = new ConsoleMessageLogger(); DefaultTestCaseDiscoverySink sink = new DefaultTestCaseDiscoverySink(); const string mappedSource = "C:\\test_1.dll"; const string invalidSource = "C:\\test_2.dll"; discoverer.DiscoverTests(new string[] { mappedSource, invalidSource }, context, sink); // A total of 7 tests should be discovered as described in the Xml descriptor Assert.That(sink.Tests.Count(), Is.EqualTo(7)); // All of the discovered tests should originate from C:\test_1.dll. // No mapping to C:\test_2.dll exist so no tests should be discovered from that source. Assert.That(sink.Tests.Count((test) => test.Source == mappedSource), Is.EqualTo(7)); const string masterTestSuite = "Test runner test"; AssertVSTestCaseProperties(sink.Tests, QualifiedNameBuilder.FromString(masterTestSuite, "test1"), mappedSource, new SourceFileInfo("test_runner_test.cpp", 26)); AssertVSTestCaseProperties(sink.Tests, QualifiedNameBuilder.FromString(masterTestSuite, "test2"), mappedSource, new SourceFileInfo("test_runner_test.cpp", 35)); AssertVSTestCaseProperties(sink.Tests, QualifiedNameBuilder.FromString(masterTestSuite, "SampleSuite/SampleNestedSuite/test3"), mappedSource, new SourceFileInfo("test_runner_test.cpp", 48)); AssertVSTestCaseProperties(sink.Tests, QualifiedNameBuilder.FromString(masterTestSuite, "TemplateSuite/my_test<char>"), mappedSource, new SourceFileInfo("test_runner_test.cpp", 79)); AssertVSTestCaseProperties(sink.Tests, QualifiedNameBuilder.FromString(masterTestSuite, "TemplateSuite/my_test<int>"), mappedSource, new SourceFileInfo("test_runner_test.cpp", 79)); AssertVSTestCaseProperties(sink.Tests, QualifiedNameBuilder.FromString(masterTestSuite, "TemplateSuite/my_test<float>"), mappedSource, new SourceFileInfo("test_runner_test.cpp", 79)); AssertVSTestCaseProperties(sink.Tests, QualifiedNameBuilder.FromString(masterTestSuite, "TemplateSuite/my_test<double>"), mappedSource, new SourceFileInfo("test_runner_test.cpp", 79)); } }
/// <summary> /// Given a fully qualified name of a <b>test case</b>, generates the respective test unit hierarchy. /// </summary> /// <param name="fullyQualifiedName">The fully qualified name of the <b>test case</b></param> /// <returns>The test case hierarchy represented by the provided fully qualified name</returns> /// <remarks>The parameter 'fullyQualifiedName' will be modified and emptied in due process</remarks> private static TestCase FromFullyQualifiedName(QualifiedNameBuilder fullyQualifiedName) { // Reverse the fully qualified name stack i.e. Master Test Suite should be first element and Test Case should be last element Stack <string> hierarchy = new Stack <string>(); while (fullyQualifiedName.Peek() != null) { hierarchy.Push(fullyQualifiedName.Peek()); fullyQualifiedName.Pop(); } TestSuite parent = null; // Treat each entry (except for the last) as a test suite while (hierarchy.Count > 1) { parent = new TestSuite(hierarchy.Peek(), parent); hierarchy.Pop(); } // Treat the last entry as a test case return((hierarchy.Count == 1) ? new TestCase(hierarchy.Peek(), parent) : null); }
/// <summary> /// Given a fully qualified name of a <b>test case</b>, generates the respective test unit hierarchy. /// </summary> /// <param name="fullyQualifiedName">The fully qualified name of the <b>test case</b></param> /// <returns>The test case hierarcy represented by the provided fully qualified name</returns> public static TestCase FromFullyQualifiedName(string fullyQualifiedName) { return(FromFullyQualifiedName(QualifiedNameBuilder.FromString(fullyQualifiedName))); }
public override IEnumerable <TestRun> BatchTests(IEnumerable <VSTestCase> tests) { BoostTestRunnerSettings adaptedSettings = this.Settings.TestRunnerSettings.Clone(); // Disable timeout since this batching strategy executes more than one test at a time adaptedSettings.Timeout = -1; // Group by source IEnumerable <IGrouping <string, VSTestCase> > sources = tests.GroupBy(test => test.Source); foreach (IGrouping <string, VSTestCase> source in sources) { IBoostTestRunner runner = GetTestRunner(source.Key); if (runner == null) { continue; } // Group by test suite var suiteGroups = source.GroupBy(test => test.Traits.First(trait => (trait.Name == VSTestModel.TestSuiteTrait)).Value); foreach (var suiteGroup in suiteGroups) { BoostTestRunnerCommandLineArgs args = BuildCommandLineArgs(source.Key); foreach (VSTestCase test in suiteGroup) { // List all tests by name but ensure that the first test is fully qualified so that remaining tests are taken relative to this test suite args.Tests.Add((args.Tests.Count == 0) ? test.FullyQualifiedName : QualifiedNameBuilder.FromString(test.FullyQualifiedName).Peek()); } yield return(new TestRun(runner, suiteGroup, args, adaptedSettings)); } } }
/// <summary> /// Creates a new TestCase object. /// </summary> /// <param name="sourceExe">Name of the project executable</param> /// <param name="sourceInfo">.cpp file path and TestCase line number</param> /// <param name="suite">The suite in which testcase is present</param> /// <param name="testCaseName">Name of the testcase</param> /// <param name="isEnabled">The enabling status of the testcase</param> /// <returns>The created TestCase object</returns> public static TestCase CreateTestCase(string sourceExe, SourceFileInfo sourceInfo, QualifiedNameBuilder suite, string testCaseName, bool isEnabled = true) { suite.Push(testCaseName); string qualifiedName = suite.ToString(); suite.Pop(); var testCase = new TestCase(qualifiedName, BoostTestExecutor.ExecutorUri, sourceExe) { CodeFilePath = sourceInfo.File, LineNumber = sourceInfo.LineNumber, DisplayName = testCaseName, }; GroupViaTraits(suite.ToString(), testCase, isEnabled); return(testCase); }
private static void DiscoverBoostTests(CppSourceFile cppSourceFile, string source, ITestCaseDiscoverySink discoverySink) { string[] code = cppSourceFile.SourceCode.TrimEnd(new[] { ' ', '\n', '\r' }).Split('\n'); SourceFileInfo sourceInfo = new SourceFileInfo(cppSourceFile.FileName, 0); QualifiedNameBuilder suite = new QualifiedNameBuilder(); // Push the equivalent of the Master Test Suite suite.Push(QualifiedNameBuilder.DefaultMasterTestSuiteName); var templateLists = new Dictionary <string, IEnumerable <string> >(); for (sourceInfo.LineNumber = 1; sourceInfo.LineNumber <= code.Length; ++sourceInfo.LineNumber) { string line = code[sourceInfo.LineNumber - 1]; string[] splitMacro = SplitMacro(line); string desiredMacro = splitMacro[0].Trim(); switch (desiredMacro) { case Constants.TypedefListIdentifier: case Constants.TypedefMplListIdentifier: case Constants.TypedefBoostMplListIdentifier: { var templateList = ParseTemplateList(splitMacro); templateLists.Add(templateList.Key, templateList.Value); break; } case Constants.TestCaseTemplateIdentifier: { var templateTest = ParseTemplateTestCase(splitMacro, templateLists, sourceInfo, code, ref line); foreach (string testCaseDataType in templateTest.Value) { string testCaseNameWithDataType = templateTest.Key + '<' + testCaseDataType + '>'; var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseNameWithDataType); TestCaseUtils.AddTestCase(testCase, discoverySink); } break; } case Constants.FixtureTestSuiteIdentifier: case Constants.AutoTestSuiteIdentifier: { string suiteName = ParseBeginTestSuite(splitMacro, sourceInfo, code, ref line); suite.Push(suiteName); break; } case Constants.FixtureTestCaseIdentifier: case Constants.AutoTestCaseIdentifier: case Constants.DataTestCaseIdentifier: { string testCaseName = ParseTestCase(splitMacro, sourceInfo, code, ref line); var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseName); TestCaseUtils.AddTestCase(testCase, discoverySink); break; } case Constants.FixtureDataTestCaseIdentifier: { string testCaseName = ParseDataTestCaseF(splitMacro, sourceInfo, code, ref line); var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseName); TestCaseUtils.AddTestCase(testCase, discoverySink); break; } case Constants.AutoTestSuiteEndIdentifier: { suite.Pop(); break; } default: break; } } }