/// <summary> /// Converts an NUnit test into a TestCase for Visual Studio, /// using the best method available according to the exact /// type passed and caching results for efficiency. /// </summary> public TestCase ConvertTestCase(NUnitDiscoveryTestCase testNode) { // Return cached value if we have one string id = testNode.Id; if (_vsTestCaseMap.ContainsKey(id)) { return(_vsTestCaseMap[id]); } // Convert to VS TestCase and cache the result var testCase = MakeTestCaseFromDiscoveryNode(testNode); _vsTestCaseMap.Add(id, testCase); return(testCase); }
public static void AddTraitsFromTestNode(this TestCase testCase, NUnitDiscoveryTestCase testNCase, IDictionary <string, CachedTestCaseInfo> traitsCache, ITestLogger logger, IAdapterSettings adapterSettings) { var ancestor = testNCase.Parent; var key = ancestor?.Id; var categoryList = new CategoryList(testCase, adapterSettings); // Reading ancestor properties of a test-case node. And adding to the cache. while (ancestor != null && !string.IsNullOrEmpty(key)) { AddingToCache(testCase, traitsCache, key, categoryList, ancestor, categoryList.ProcessTestCaseProperties); ancestor = ancestor.Parent; key = ancestor?.Id; } // No Need to store test-case properties in cache. categoryList.ProcessTestCaseProperties(testNCase, false); categoryList.UpdateCategoriesToVs(); }
public static void AddTraitsFromTestNode(this TestCase testCase, NUnitDiscoveryTestCase testNCase, IDictionary <string, CachedTestCaseInfo> traitsCache, ITestLogger logger, IAdapterSettings adapterSettings) { var ancestor = testNCase.Parent as INUnitDiscoverySuiteBase; var key = ancestor?.Id; var categoryList = new CategoryList(testCase, adapterSettings); // Reading ancestor properties of a test-case node. And adding to the cache. while (ancestor != null && !string.IsNullOrEmpty(key)) { if (traitsCache.ContainsKey(key)) { categoryList.AddRange(traitsCache[key].Traits.Where(o => o.Name == NunitTestCategoryLabel).Select(prop => prop.Value).ToList()); if (traitsCache[key].Explicit) { testCase.SetPropertyValue(CategoryList.NUnitExplicitProperty, true); } var traitsList = traitsCache[key].Traits.Where(o => o.Name != NunitTestCategoryLabel).ToList(); if (traitsList.Count > 0) { testCase.Traits.AddRange(traitsList); } } else { categoryList.ProcessTestCaseProperties(ancestor, true, key, traitsCache); // Adding entry to dictionary, so that we will not make SelectNodes call again. if (categoryList.LastNodeListCount == 0 && !traitsCache.ContainsKey(key)) { traitsCache[key] = new CachedTestCaseInfo(); } } ancestor = ancestor.Parent; key = ancestor?.Id; } // No Need to store test-case properties in cache. categoryList.ProcessTestCaseProperties(testNCase, false); categoryList.UpdateCategoriesToVs(); }
public void SetUp() { var xDoc = XDocument.Parse(FakeTestData.TestXml); var parent = Substitute.For <INUnitDiscoveryCanHaveTestFixture>(); parent.Parent.Returns(null as INUnitDiscoverySuiteBase); var className = xDoc.Root.Attribute("classname").Value; var tf = DiscoveryConverter.ExtractTestFixture(parent, xDoc.Root, className); var tcs = DiscoveryConverter.ExtractTestCases(tf, xDoc.Root); Assert.That(tcs.Count(), Is.EqualTo(1), "Setup: More than one test case in fake data"); fakeTestNode = tcs.Single(); var settings = Substitute.For <IAdapterSettings>(); settings.ConsoleOut.Returns(0); settings.UseTestNameInConsoleOutput.Returns(false); settings.CollectSourceInformation.Returns(true); var discoveryConverter = Substitute.For <IDiscoveryConverter>(); testConverter = new TestConverter(new TestLogger(new MessageLoggerStub()), FakeTestData.AssemblyPath, settings, discoveryConverter); }
/// <summary> /// Makes a TestCase from an NUnit test, adding /// navigation data if it can be found. /// </summary> private TestCase MakeTestCaseFromDiscoveryNode(NUnitDiscoveryTestCase testNode) { string fullyQualifiedName = testNode.FullName; if (adapterSettings.UseParentFQNForParametrizedTests) { var parent = testNode.Parent; if (parent != null && parent.IsParameterizedMethod) { var parameterizedTestFullName = parent.FullName; // VS expected FullyQualifiedName to be the actual class+type name,optionally with parameter types // in parenthesis, but they must fit the pattern of a value returned by object.GetType(). // It should _not_ include custom name or param values (just their types). // However, the "fullname" from NUnit's file generation is the custom name of the test, so // this code must convert from one to the other. // Reference: https://github.com/microsoft/vstest-docs/blob/master/RFCs/0017-Managed-TestCase-Properties.md // Using the nUnit-provided "fullname" will cause failures at test execution time due to // the FilterExpressionWrapper not being able to parse the test names passed-in as filters. // To resolve this issue, for parameterized tests (which are the only tests that allow custom names), // the parent node's "fullname" value is used instead. This is the name of the actual test method // and will allow the filtering to work as expected. // Note that this also means you can no longer select a single tests of these to run. // When you do that, all tests within the parent node will be executed if (!string.IsNullOrEmpty(parameterizedTestFullName)) { fullyQualifiedName = parameterizedTestFullName; } } } var testCase = new TestCase( fullyQualifiedName, new Uri(NUnitTestAdapter.ExecutorUri), _sourceAssembly) { DisplayName = CreateDisplayName(fullyQualifiedName, testNode.Name), CodeFilePath = null, LineNumber = 0 }; if (adapterSettings.UseNUnitIdforTestCaseId) { testCase.Id = EqtHash.GuidFromString(testNode.Id); } if (CollectSourceInformation && _navigationDataProvider != null) { if (!CheckCodeFilePathOverride()) { var navData = _navigationDataProvider.GetNavigationData(testNode.ClassName, testNode.MethodName); if (navData.IsValid) { testCase.CodeFilePath = navData.FilePath; testCase.LineNumber = navData.LineNumber; } } } else { _ = CheckCodeFilePathOverride(); } testCase.AddTraitsFromTestNode(testNode, TraitsCache, _logger, adapterSettings); return(testCase); bool CheckCodeFilePathOverride() { var codeFilePath = testNode.Properties.FirstOrDefault(p => p.Name == "_CodeFilePath"); if (codeFilePath == null) { return(false); } testCase.CodeFilePath = codeFilePath.Value; var lineNumber = testNode.Properties.FirstOrDefault(p => p.Name == "_LineNumber"); testCase.LineNumber = lineNumber != null?Convert.ToInt32(lineNumber.Value) : 1; return(true); } }