/// <summary> /// Select all tests in the TreeView that are tagged by the tagExpression /// </summary> /// <param name="root">Root node of the TreeView</param> /// <param name="tagExpression">Tag expression</param> /// <param name="browser">Browser running the tests</param> public void SelectTaggedTests(TreeNode root, string tagExpression, BrowserVersions browser) { if (root == null) { throw new ArgumentNullException("root", "Root cannot be null!"); } EnsureLoaded(); // Get the tests that should be tagged bool selectAllTests = string.IsNullOrEmpty(tagExpression); IList <MethodInfo> taggedTests = null; if (!selectAllTests) { taggedTests = GetTestsByTag(tagExpression, browser); } // Select the nodes foreach (TreeNode classNode in root.ChildNodes) { foreach (TreeNode methodNode in classNode.ChildNodes) { MethodInfo testCase = GetTestCase(classNode.Value, methodNode.Value); bool selected = selectAllTests || taggedTests.Contains(testCase); methodNode.Checked = selected; } } }
/// <summary> /// Evaluate an expression /// </summary> /// <returns>Test methods described by the expression</returns> public List <MethodInfo> Evaluate( string tagExpression, BrowserVersions browser, List <MethodInfo> testMethods, Dictionary <MethodInfo, BrowserVersions> testFailures, Dictionary <string, List <MethodInfo> > tags) { if (tagExpression == null) { throw new ArgumentNullException("tagExpression", "tagExpression cannot be null!"); } else if (tagExpression.Length == 0) { throw new ArgumentException("tagExpression cannot be empty!", "tagExpression"); } _tagExpression = tagExpression; _browser = browser; _testFailures = testFailures; _testMethods = testMethods; _tags = tags; _position = 0; List <MethodInfo> expression = ReadExpression(); if (_position >= 0 && _position < _tagExpression.Length) { throw new FormatException(string.Format("Expected end of tag expression \"{0}\" at position {1}!", _tagExpression, _position)); } return(expression); }
internal void OnLoadCompleteInternal() { // Only auto-select or auto-run on the first request if (!_aspNetService.GetIsPostBack(this)) { // Get query string values QueryStringParameters queryParams = new QueryStringParameters(); queryParams.LoadFromQueryString(_aspNetService.GetQueryString(this)); BrowserVersions browser = BrowserUtility.GetBrowser(_aspNetService.GetBrowserName(this), _aspNetService.GetBrowserMajorVersion(this)); LogDetail = queryParams.LogDetail; this.WriteLogToDiskCheckBox.Checked = queryParams.WriteLog; this.ShowConsoleCheckBox.Checked = queryParams.ShowConsole; // Auto-select tests with a given tag if (!String.IsNullOrEmpty(queryParams.Tag)) { _testcaseManager.SelectTaggedTests(this.TestCasesTreeView, queryParams.Tag, browser); } else if (queryParams.Run) { _testcaseManager.SelectAllTests(this.TestCasesTreeView, browser); } // Optionally remove unselected tests if (queryParams.Filter) { _testcaseManager.FilterIgnoredTests(this.TestCasesTreeView); } // Auto-run the selected tests (or all tests if none are selected) if (queryParams.Run) { RunTestCases(); } } // Change UI depending if showing console or not. if (this.ShowConsoleCheckBox.Checked) { this.TestsPanel.CssClass = "tests"; this.FooterPanel.Visible = true; } else { this.TestsPanel.CssClass = "testsNoConsole"; this.FooterPanel.Visible = false; } }
/// <summary> /// WebTestFailureTag attribute used to associate test cases with failures /// in specific sets of browsers so they can be properly tracked. /// </summary> /// <param name="browsers">Browsers the test cases fail in</param> /// <param name="description">Description of the failure</param> public WebTestFailureTagAttribute(BrowserVersions browsers, string description) { if (description == null) { throw new ArgumentNullException("description", "Description cannot be null!"); } else if (description.Length == 0) { throw new ArgumentException("Description cannot be empty!", "description"); } _browsers = browsers; _description = description; }
/// <summary> /// Ignore any tests that fail in the given browsers /// </summary> /// <param name="root">Root node of the TreeView</param> /// <param name="browsers">Browsers to skip failures</param> public void IgnoreFailures(TreeNode root, BrowserVersions browsers) { if (root == null) { throw new ArgumentNullException("root", "Root cannot be null!"); } EnsureLoaded(); // Select the nodes foreach (TreeNode @class in root.ChildNodes) { foreach (TreeNode method in @class.ChildNodes) { MethodInfo testCase = GetTestCase(@class.Value, method.Value); BrowserVersions failures; if (this._testFailures.TryGetValue(testCase, out failures) && ((browsers & failures) > 0)) { method.Checked = false; } } } }
/// <summary> /// Get the test methods that correspond to a tag expression /// </summary> /// <param name="tagExpression">Tag expression</param> /// <param name="browser">Browser running the tests</param> /// <returns>Test methods for the tag expression</returns> public IList <MethodInfo> GetTestsByTag(string tagExpression, BrowserVersions browser) { if (tagExpression == null) { throw new ArgumentNullException("tagExpression", "Tag expression cannot be null!"); } else if (tagExpression.Length == 0) { throw new ArgumentException("Tag expression cannot be empty!", "tagExpression"); } EnsureLoaded(); // Try to use the cached methods List <MethodInfo> methods; string cacheKey = string.Format("{0} + {1}", tagExpression, browser); if (_cachedTagExpressions.TryGetValue(cacheKey, out methods)) { return(methods); } // Evaluate the tag WebTestTagExpressionEvaluator webTestTagExpressionEvaluator = new WebTestTagExpressionEvaluator(); methods = webTestTagExpressionEvaluator.Evaluate( tagExpression, browser, _testMethods, _testFailures, _tags); // Cache the expression and return it _cachedTagExpressions.Add(cacheKey, methods); return(methods); }
/// <summary> /// Load the test cases /// </summary> private void EnsureLoaded() { // Make sure we only load this once and ignore simultaneous requests lock (_syncRoot) { // If it's already been loaded, ignore subsequent loads if (_appCodeAssembly != null) { return; } Type[] testTypes = GetTestTypes(out _appCodeAssembly); _testClasses = new List <Type>(); _testClassesByName = new Dictionary <string, Type>(StringComparer.OrdinalIgnoreCase); _testMethods = new List <MethodInfo>(); _testMethodsByClass = new Dictionary <Type, List <MethodInfo> >(); foreach (Type type in testTypes) { // Add the type _testClasses.Add(type); _testClassesByName.Add(type.FullName, type); // Add the methods associated with the type List <MethodInfo> methodsForType = new List <MethodInfo>(); _testMethodsByClass.Add(type, methodsForType); foreach (MethodInfo method in type.GetMethods()) { if (!method.IsDefined(typeof(WebTestMethodAttribute), true)) { continue; } _testMethods.Add(method); methodsForType.Add(method); } } // Sort the list of types alphabetically _testClasses.Sort(delegate(Type a, Type b) { return(string.CompareOrdinal( a != null ? a.FullName : null, b != null ? b.FullName : null)); }); // Compute the tags and known failures lookups _tags = new Dictionary <string, List <MethodInfo> >(StringComparer.OrdinalIgnoreCase); _cachedTagExpressions = new Dictionary <string, List <MethodInfo> >(StringComparer.OrdinalIgnoreCase); _testFailures = new Dictionary <MethodInfo, BrowserVersions>(); // Compute the tags for each class Dictionary <Type, List <string> > classTags = new Dictionary <Type, List <string> >(); Dictionary <Type, BrowserVersions> classFailures = new Dictionary <Type, BrowserVersions>(); foreach (Type type in _testClasses) { // Add the tags List <string> tagsForClass = new List <string>(); classTags.Add(type, tagsForClass); // Include the class name as one of it's tags so they can // be easily isolated during development without adding addtional // temporary tags tagsForClass.Add(type.FullName); foreach (Attribute attribute in type.GetCustomAttributes(typeof(WebTestTagAttribute), true)) { WebTestTagAttribute testTag = attribute as WebTestTagAttribute; if (testTag != null) { tagsForClass.Add(testTag.Tag); } } // Add the known failures BrowserVersions failures = BrowserVersions.None; foreach (Attribute attribute in type.GetCustomAttributes(typeof(WebTestFailureTagAttribute), true)) { WebTestFailureTagAttribute failureTag = attribute as WebTestFailureTagAttribute; if (failureTag != null) { failures |= failureTag.Browsers; } } classFailures.Add(type, failures); } // Compute the tags and known failures for each method foreach (MethodInfo method in _testMethods) { // Start the list of tags with all those declared on its type List <string> methodTags = new List <string>(classTags[method.ReflectedType]); // Include the method's name and full name as one of it's tags so they can // be easily isolated during development without adding addtional // temporary tags. Also include Class.Method as well to make it easy to // isolate common tests. methodTags.Add(method.Name); methodTags.Add(string.Format("{0}.{1}", method.ReflectedType.FullName, method.Name)); // Add the tags declared on the method foreach (Attribute attribute in method.GetCustomAttributes(typeof(WebTestTagAttribute), true)) { WebTestTagAttribute testTag = attribute as WebTestTagAttribute; if (testTag != null) { methodTags.Add(testTag.Tag); } } // Associate this method with each of its tags foreach (string tag in methodTags) { List <MethodInfo> methods; if (!_tags.TryGetValue(tag, out methods)) { methods = new List <MethodInfo>(); _tags.Add(tag, methods); } methods.Add(method); } // Add the known failures on the method and class BrowserVersions failures = classFailures[method.ReflectedType]; foreach (Attribute attribute in method.GetCustomAttributes(typeof(WebTestFailureTagAttribute), true)) { WebTestFailureTagAttribute failureTag = attribute as WebTestFailureTagAttribute; if (failureTag != null) { failures |= failureTag.Browsers; } } _testFailures.Add(method, failures); } } }
/// <summary> /// Ignore any tests that fail in the given browsers /// </summary> /// <param name="tree">TreeView</param> /// <param name="browsers">Browsers to skip failures</param> public void IgnoreFailures(TreeView tree, BrowserVersions browsers) { IgnoreFailures(GetTreeRoot(tree), browsers); }
/// <summary> /// Select all tests in the TreeView that are tagged by the tagExpression /// </summary> /// <param name="tree">TreeView</param> /// <param name="tagExpression">Tag expression</param> /// <param name="browser">Browser running the tests</param> public void SelectTaggedTests(TreeView tree, string tagExpression, BrowserVersions browser) { SelectTaggedTests(GetTreeRoot(tree), tagExpression, browser); }
/// <summary> /// Select all the tests in the TreeView /// </summary> /// <param name="root">Root node of the TreeView</param> /// <param name="browser">Browser running the tests</param> public void SelectAllTests(TreeNode root, BrowserVersions browser) { SelectTaggedTests(root, null, browser); }
/// <summary> /// Select all the tests in the TreeView /// </summary> /// <param name="tree">TreeView</param> /// <param name="browser">Browser running the tests</param> public void SelectAllTests(TreeView tree, BrowserVersions browser) { SelectAllTests(GetTreeRoot(tree), browser); }