/// <summary> /// Asserts general test case details /// </summary> /// <param name="testCase">The test case to test</param> /// <param name="qualifiedName">The expected qualified name of the test case</param> /// <param name="sourceFile">The expected source file path of the test case or null if not available</param> /// <param name="lineNumber">The expected line number of the test case or -1 if not available</param> private void AssertTestDetails(TestCase testCase, QualifiedNameBuilder qualifiedName, string sourceFile, int lineNumber) { Assert.That(testCase.DisplayName, Is.EqualTo(qualifiedName.Peek())); Assert.That(testCase.FullyQualifiedName, Is.EqualTo(qualifiedName.ToString())); string suite = qualifiedName.Pop().ToString(); if (!string.IsNullOrEmpty(suite)) { AssertTestSuite(testCase, suite); } else { // The default 'Master Test Suite' trait value should be available AssertTrait(testCase, VSTestModel.TestSuiteTrait); } if (!string.IsNullOrEmpty(sourceFile)) { Assert.That(testCase.CodeFilePath, Is.EqualTo(sourceFile)); } if (lineNumber > -1) { Assert.That(testCase.LineNumber, Is.EqualTo(lineNumber)); } }
/// <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 TestResultCollection which will host the result.</param> private static void ParseTestCaseLog(XmlNode node, QualifiedNameBuilder path, TestResultCollection collection) { // Temporarily push TestCase on TestSuite name builder to acquire the fully qualified name of the TestCase path.Push(node.Attributes[Xml.Name].Value); // Acquire result record of this TestCase TestResult result = collection[path.ToString()]; if (result == null) { result = new TestResult(collection); collection[path.ToString()] = 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 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)); }
public void CorrectTestsDiscoveryForFIXTURE_TEST_CASE() { using (DummySolution solution = new DummySolution(DefaultSource, "BoostFixtureTestCase.cpp")) { #region excercise /** The BoostFixtureTestCase.cpp file consists of 4 test cases: BoostUnitTest1, Fixturetest_case1, Fixturetest_case1 and Fixturetest_case1, * BOOST_AUTO_TEST_SUITE -> Suit1 * -->BoostUnitTest1 * -->Fixturetest_case1 * -->Fixturetest_case2 * -> Master Suite * -->Fixturetest_case3 */ IList <TestCase> testList = DiscoverTests(solution); #endregion excercise #region verify AssertTestDetails(testList[0], QualifiedNameBuilder.FromString("Suit1/BoostUnitTest1")); AssertTestDetails(testList[1], QualifiedNameBuilder.FromString("Suit1/Fixturetest_case1")); AssertTestDetails(testList[2], QualifiedNameBuilder.FromString("Suit1/Fixturetest_case2")); AssertTestDetails(testList[3], QualifiedNameBuilder.FromString("Fixturetest_case3")); #endregion verify } }
public void MultilineBoostMacroDefinitions() { using (DummySolution solution = new DummySolution(DefaultSource, "BoostMultiLineDefinitions.cpp")) { IList <TestCase> testList = DiscoverTests(solution); AssertTestDetails(testList[0], QualifiedNameBuilder.FromString("AutoSuite/TestA")); AssertTestDetails(testList[1], QualifiedNameBuilder.FromString("AutoSuite/TestB")); AssertTestDetails(testList[2], QualifiedNameBuilder.FromString("AutoSuite/TestC")); AssertTestDetails(testList[3], QualifiedNameBuilder.FromString("AutoSuite/FixtureSuite/TestD")); } }
public void BOOST_DATA_TEST_CASEDiscovery() { using (DummySolution solution = new DummySolution(DefaultSource, "BoostDataTestCase.cpp")) { IList <TestCase> testList = DiscoverTests(solution); Assert.That(testList.Count, Is.EqualTo(3)); AssertTestDetails(testList[0], QualifiedNameBuilder.FromString("data_test_suite/data_1")); AssertTestDetails(testList[1], QualifiedNameBuilder.FromString("data_test_suite/data_2")); AssertTestDetails(testList[2], QualifiedNameBuilder.FromString("data_3")); } }
/// <summary> /// Factory method which creates a QualifiedNameBuilder /// from an already existing qualified name string. /// </summary> /// <param name="masterSuite">The local name of the master test suite</param> /// <param name="name">The qualified name</param> /// <returns>A QualifiedNameBuilder from the provided string.</returns> public static QualifiedNameBuilder FromString(string masterSuite, string name) { Utility.Code.Require(masterSuite, "masterSuite"); Utility.Code.Require(name, "name"); QualifiedNameBuilder builder = new QualifiedNameBuilder(); builder.Push(masterSuite); foreach (string part in name.Split(new string[] { Separator }, StringSplitOptions.RemoveEmptyEntries)) { builder.Push(part); } return(builder); }
public void CorrectDiscoveryGenericBoostTests() { using (DummySolution solution = new DummySolution(DefaultSource, "BoostUnitTestSample.cpp")) { #region excercise IList <TestCase> tests = DiscoverTests(solution); #endregion excercise #region verify AssertTestDetails(tests.Last(), QualifiedNameBuilder.FromString("my_test<char>"), solution.SourceFileResourcePaths.First().Path, 33); #endregion verify } }
/// <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; }
public void CorrectTestsDiscoveryForFIXTURE_TEST_SUITE() { using (DummySolution solution = new DummySolution(DefaultSource, "BoostFixtureTestSuite.cpp")) { #region exercise /** The BoostFixtureSuiteTest.cpp file consists of 3 test cases: FixtureTest1, FixtureTest2 and BoostTest, * BOOST_FIXTURE_TEST_SUITE -> FixtureSuite1 * -->BoostTest1 * -->BoostTest2 * -> Master Suite * -->BoostTest3 * BOOST_FIXTURE_TEST_SUITE -> FixtureSuite2 * -->Fixturetest_case1 * -->TemplatedTest<int> (BOOST_AUTO_TEST_CASE_TEMPLATE) * -->TemplatedTest<long> (BOOST_AUTO_TEST_CASE_TEMPLATE) * -->TemplatedTest<char> (BOOST_AUTO_TEST_CASE_TEMPLATE) */ IList <TestCase> testList = DiscoverTests(solution); #endregion exercise #region verification AssertTestDetails(testList[0], QualifiedNameBuilder.FromString("FixtureSuite1/BoostTest1")); AssertTestDetails(testList[1], QualifiedNameBuilder.FromString("FixtureSuite1/BoostTest2")); AssertTestDetails(testList[2], QualifiedNameBuilder.FromString("BoostTest3")); AssertTestDetails(testList[3], QualifiedNameBuilder.FromString("FixtureSuite2/Fixturetest_case1")); AssertTestDetails(testList[4], QualifiedNameBuilder.FromString("FixtureSuite2/TemplatedTest<int>")); AssertTestDetails(testList[5], QualifiedNameBuilder.FromString("FixtureSuite2/TemplatedTest<long>")); AssertTestDetails(testList[6], QualifiedNameBuilder.FromString("FixtureSuite2/TemplatedTest<char>")); #endregion verification } }
/// <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> /// Factory method which creates a QualifiedNameBuilder /// from an already existing qualified name string. /// </summary> /// <param name="masterSuite">The local name of the master test suite</param> /// <param name="name">The qualified name</param> /// <returns>A QualifiedNameBuilder from the provided string.</returns> public static QualifiedNameBuilder FromString(string masterSuite, string name) { Utility.Code.Require(masterSuite, "masterSuite"); Utility.Code.Require(name, "name"); QualifiedNameBuilder builder = new QualifiedNameBuilder(); builder.Push(masterSuite); foreach (string part in name.Split(new string[] { Separator }, StringSplitOptions.RemoveEmptyEntries)) { builder.Push(part); } return builder; }
/// <summary> /// Constructor /// </summary> /// <param name="source">The source test module which contains the discovered tests</param> /// <param name="sink">The ITestCaseDiscoverySink which will have tests registered with</param> public BoostTestCaseDiscoverer(string source, ITestCaseDiscoverySink sink) { Source = source; Sink = sink; TestSuite = new QualifiedNameBuilder(); }
/// <summary> /// Asserts general test case details /// </summary> /// <param name="testCase">The test case to test</param> /// <param name="qualifiedName">The expected qualified name of the test case</param> private void AssertTestDetails(TestCase testCase, QualifiedNameBuilder qualifiedName) { AssertTestDetails(testCase, qualifiedName, null, -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 TestResultCollection which will host the result.</param> private static void ParseTestUnitsLog(XmlNodeList nodes, QualifiedNameBuilder path, TestResultCollection 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); } } } }
/// <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 TestResultCollection which will host the result.</param> private static void ParseTestSuiteLog(XmlNode node, QualifiedNameBuilder path, TestResultCollection collection) { path.Push(node.Attributes[Xml.Name].Value); ParseTestUnitsLog(node.ChildNodes, path, collection); path.Pop(); }
/// <summary> /// Discovers Boost Test from the provided C++ source file. Notifies test discovery via the provided discoverySink. /// </summary> /// <param name="cppSourceFile">The C++ source file to scan for Boost Tests</param> /// <param name="source">The associated test source EXE</param> /// <param name="discoverySink">The discoverySink to which identified tests will be notified to</param> 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, List<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(); // serge: BOOST multiline test macros are supported now /* * Currently the below is not able to handle BOOST UTF signatures spread over multiple lines. */ switch (desiredMacro) { case Constants.TypedefListIdentifier: case Constants.TypedefMplListIdentifier: case Constants.TypedefBoostMplListIdentifier: { var dataTypes = new List<string>(); int i; for (i = 1; i < splitMacro.Length - 2; ++i) { dataTypes.Add(splitMacro[i].Trim()); } templateLists.Add(splitMacro[i].Trim(), dataTypes); break; } case Constants.TestCaseTemplateIdentifier: { int newLineNumber = ScrollLines(sourceInfo.LineNumber, code, ref line); if (sourceInfo.LineNumber != newLineNumber) { // recalc splitMacro splitMacro = SplitMacro(line); sourceInfo.LineNumber = newLineNumber; } string listName = splitMacro[3].Trim(); //third parameter is the corresponding boost::mpl::list name if (templateLists.ContainsKey(listName)) { foreach (var dataType in templateLists[listName]) { string testCaseName = splitMacro[1].Trim(); //first parameter is the test case name string testCaseNameWithDataType = testCaseName + "<" + dataType + ">"; var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseNameWithDataType); TestCaseUtils.AddTestCase(testCase, discoverySink); } } break; } case Constants.FixtureTestSuiteIdentifier: case Constants.AutoTestSuiteIdentifier: { int newLineNumber = ScrollLines(sourceInfo.LineNumber, code, ref line); if (sourceInfo.LineNumber != newLineNumber) { // recalc splitMacro splitMacro = SplitMacro(line); sourceInfo.LineNumber = newLineNumber; } suite.Push(splitMacro[1].Trim()); break; } case Constants.FixtureTestCaseIdentifier: case Constants.AutoTestCaseIdentifier: { int newLineNumber = ScrollLines(sourceInfo.LineNumber, code, ref line); if (sourceInfo.LineNumber != newLineNumber) { // recalc splitMacro splitMacro = SplitMacro(line); sourceInfo.LineNumber = newLineNumber; } string testCaseName = splitMacro[1].Trim(); var testCase = TestCaseUtils.CreateTestCase(source, sourceInfo, suite, testCaseName); TestCaseUtils.AddTestCase(testCase, discoverySink); break; } case Constants.AutoTestSuiteEndIdentifier: { suite.Pop(); break; } default: break; } } }
/// <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> /// Based on the parent test unit hierarchy and the provided test unit, generates a fully-qualified test case symbol name for the provided test unit. /// </summary> /// <param name="suiteNameBuilder">The parent test unit hierarchy.</param> /// <param name="unitName">The test unit.</param> /// <returns>The fully-qualified <b>test case</b> symbol name for the provided test unit.</returns> private static string BuildTestCaseSymbolName(QualifiedNameBuilder suiteNameBuilder, string unitName) { var fullyQualifiedName = unitName; string testUnitLocator = suiteNameBuilder.ToString(); // If the test is located within a test suite, qualify accordingly if (!string.IsNullOrEmpty(testUnitLocator)) { fullyQualifiedName = string.Format( CultureInfo.InvariantCulture, "{0}::{1}", testUnitLocator.Replace("/", "::"), unitName ); } var symbolName = string.Format( CultureInfo.InvariantCulture, "{0}::test_method", fullyQualifiedName ); return symbolName; }
/// <summary> /// Asserts general test case details /// </summary> /// <param name="testCase">The test case to test</param> /// <param name="qualifiedName">The expected qualified name of the test case</param> private void AssertTestDetails(TestCase testCase, QualifiedNameBuilder qualifiedName) { AssertTestDetails(testCase, qualifiedName, null, -1); }
/// <summary> /// Searches in a list of SymbolInfo the one that identifies a Test. /// </summary> /// <param name="suiteNameBuilder">Qualified name builder.</param> /// <param name="unitName">The name of the unit to be searched.</param> /// <param name="syms">The list of the symbols.</param> /// <returns>A SymbolInfo if <paramref name="unitName"/> is a test method.</returns> private static SymbolInfo GetTestSymbol(QualifiedNameBuilder suiteNameBuilder, string unitName, IEnumerable<SymbolInfo> syms) { try { var fullyQualifiedName = unitName; if (!string.IsNullOrEmpty(suiteNameBuilder.ToString())) fullyQualifiedName = string.Format( CultureInfo.InvariantCulture, "{0}::{1}", suiteNameBuilder.ToString().Replace("/", "::"), unitName ); var symbolName = string.Format( CultureInfo.InvariantCulture, "{0}::test_method", fullyQualifiedName ); return syms.FirstOrDefault(s => s.Name == symbolName); } catch (Exception) { throw; } }
public void DiscoverTests(IEnumerable<string> sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink) { Code.Require(sources, "sources"); Code.Require(discoverySink, "discoverySink"); BoostTestAdapterSettings settings = BoostTestAdapterSettingsProvider.GetSettings(discoveryContext); _listContentHelper.Timeout = settings.DiscoveryTimeoutMilliseconds; foreach (var source in sources) { try { var output = _listContentHelper.GetListContentOutput(source); using (var dbgHelp = _listContentHelper.CreateDebugHelper(source)) { QualifiedNameBuilder suiteNameBuilder = new QualifiedNameBuilder(); suiteNameBuilder.Push(QualifiedNameBuilder.DefaultMasterTestSuiteName); var previousLineIndentation = -1; var lines = output.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (var l in lines) { var unitName = l.Trim(); if (unitName.EndsWith("*", StringComparison.Ordinal)) unitName = unitName.Substring(0, unitName.Length - 1); var currentLineIndentation = l.TrimEnd().LastIndexOf(' ') + 1; // pop levels from the name builder to reach the current one while (currentLineIndentation <= previousLineIndentation) { suiteNameBuilder.Pop(); previousLineIndentation -= 4; } // Retrieve all the symbols that contains <unitname> in their name. // If no symbols can be retrieved, we skip the current unitName because // we cannot assume what kind of unit (test or suit) it is. IEnumerable<SymbolInfo> syms; if (!dbgHelp.LookupSymbol(unitName, out syms)) continue; // Check if the unit is a Test or a Suite. var testSymbol = GetTestSymbol(suiteNameBuilder, unitName, syms); if (testSymbol == null) { // Suite suiteNameBuilder.Push(unitName); previousLineIndentation = currentLineIndentation; } else { // Test var isEnabled = l.Contains("*"); var testCase = TestCaseUtils.CreateTestCase( source, new SourceFileInfo(testSymbol.FileName, testSymbol.LineNumber), suiteNameBuilder, unitName, isEnabled); TestCaseUtils.AddTestCase(testCase, discoverySink); } } } } catch (Exception ex) { Logger.Error("Exception caught while discovering tests for {0} ({1} - {2})", source, ex.Message, ex.HResult); Logger.Error(ex.StackTrace); } } }
/// <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; }
/// <summary> /// Asserts general test case details /// </summary> /// <param name="testCase">The test case to test</param> /// <param name="qualifiedName">The expected qualified name of the test case</param> /// <param name="sourceFile">The expected source file path of the test case or null if not available</param> /// <param name="lineNumber">The expected line number of the test case or -1 if not available</param> private void AssertTestDetails(TestCase testCase, QualifiedNameBuilder qualifiedName, string sourceFile, int lineNumber) { Assert.That(testCase.DisplayName, Is.EqualTo(qualifiedName.Peek())); Assert.That(testCase.FullyQualifiedName, Is.EqualTo(qualifiedName.ToString())); string suite = qualifiedName.Pop().ToString(); if (!string.IsNullOrEmpty(suite)) { AssertTestSuite(testCase, suite); } else { // The default 'Master Test Suite' trait value should be available AssertTrait(testCase, VSTestModel.TestSuiteTrait); } if (!string.IsNullOrEmpty(sourceFile)) { Assert.That(testCase.CodeFilePath, Is.EqualTo(sourceFile)); } if (lineNumber > -1) { Assert.That(testCase.LineNumber, Is.EqualTo(lineNumber)); } }
/// <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)); }
public void DiscoverTests(IEnumerable<string> sources, IDiscoveryContext discoveryContext, IMessageLogger logger, ITestCaseDiscoverySink discoverySink) { Code.Require(sources, "sources"); Code.Require(discoverySink, "discoverySink"); BoostTestAdapterSettings settings = BoostTestAdapterSettingsProvider.GetSettings(discoveryContext); _listContentHelper.Timeout = settings.DiscoveryTimeoutMilliseconds; foreach (var source in sources) { try { var output = _listContentHelper.GetListContentOutput(source); using (var dbgHelp = _listContentHelper.CreateDebugHelper(source)) { QualifiedNameBuilder suiteNameBuilder = new QualifiedNameBuilder(); suiteNameBuilder.Push(QualifiedNameBuilder.DefaultMasterTestSuiteName); var previousLineIndentation = -1; var lines = output.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); foreach (var l in lines) { var isEnabled = false; // Sanitize test unit name var unitName = l.Trim(); if (unitName.EndsWith("*", StringComparison.Ordinal)) { unitName = unitName.Substring(0, unitName.Length - 1).TrimEnd(); isEnabled = true; } // Identify indentation level var currentLineIndentation = 0; while (char.IsWhiteSpace(l[currentLineIndentation])) { ++currentLineIndentation; } // Pop levels from the name builder to reach the current one while (currentLineIndentation <= previousLineIndentation) { suiteNameBuilder.Pop(); previousLineIndentation -= _indentation; } // Try to locate a test case symbol for the test unit. If one is not found, assume it is a test suite. var testSymbol = dbgHelp.LookupSymbol(BuildTestCaseSymbolName(suiteNameBuilder, unitName)); if (testSymbol == null) { // Suite suiteNameBuilder.Push(unitName); previousLineIndentation = currentLineIndentation; } else { // Test var testCase = TestCaseUtils.CreateTestCase( source, new SourceFileInfo(testSymbol.FileName, testSymbol.LineNumber), suiteNameBuilder, unitName, isEnabled); TestCaseUtils.AddTestCase(testCase, discoverySink); } } } } catch (Exception ex) { Logger.Error("Exception caught while discovering tests for {0} ({1} - {2})", source, ex.Message, ex.HResult); Logger.Error(ex.StackTrace); } } }
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; } } }