/// <summary> /// Reflect, read and prepare the tags for the group metadata. Performs /// the work if this is the first time the metadata has been seen. /// </summary> /// <param name="group">The test group.</param> private void CreateClassTags(TestGroup group) { // 1. Full class name //_groupTags.AddTag(group.FullName); // 2. Class name _groupTags.AddTag(group.Name); // 3. All [Tag] attributes on the type foreach (string tag in group.Tags) { _groupTags.AddTag(tag); } }
/// <summary> /// Initializes a new instance of the TagManager class. /// </summary> /// <param name="group">The test group eing filter.</param> /// <param name="methods">The set of methods to run.</param> public TagManager(TestGroup group) { _group = group; _groupTags = new Tags(); _methodTags = new Dictionary<TestMethod, Tags>(); _tagsToMethods = new Dictionary<string, List<TestMethod>>(); Universe = new List<TestMethod>(group.Methods); CreateClassTags(_group); foreach (TestMethod method in group.Methods) { CreateMethodTags(method); } }
/// <summary> /// Initializes a new instance of the TagManager class. /// </summary> /// <param name="group">The test group eing filter.</param> /// <param name="methods">The set of methods to run.</param> public TagManager(TestGroup group) { _group = group; _groupTags = new Tags(); _methodTags = new Dictionary <TestMethod, Tags>(); _tagsToMethods = new Dictionary <string, List <TestMethod> >(); Universe = new List <TestMethod>(group.Methods); CreateClassTags(_group); foreach (TestMethod method in group.Methods) { CreateMethodTags(method); } }
private static TestGroup CreateGroup(TypeInfo type) { TestGroup group = new TestGroup(); group.Name = type.Name; group.Tags.Add(type.Name); group.Tags.Add(type.FullName); if (type.GetCustomAttribute<FunctionalTestAttribute>(true) != null) { group.Tags.Add("Functional"); } foreach (TagAttribute attr in type.GetCustomAttributes<TagAttribute>(true)) { group.Tags.Add(attr.Tag); } return group; }
/// <summary> /// Run the unit tests. /// </summary> public void RunAsync() { // Ensure there's an interface to display the test results. if (this.Reporter == null) { throw new ArgumentNullException("Reporter"); } // Setup the progress/failure counters this.Progress = 0; this.Failures = 0; // Save the test setting changes this.Settings.Save(); // Filter out any test methods based on the current settings FilterTests(); // Write out the test status message which may be modified by the // filters Reporter.Status(this.Settings.TestRunStatusMessage); // Enumerators that track the current group and method to execute // (which allows reentrancy into the test loop below to resume at // the correct location). IEnumerator <TestGroup> groups = this.Groups.OrderBy(g => g.Name).GetEnumerator(); IEnumerator <TestMethod> methods = null; // Keep a reference to the current group so we can pass it to the // Reporter's EndGroup (we don't need one for the test method, // however, because we close over in the continuation). TestGroup currentGroup = null; // Setup the UI this.Reporter.StartRun(this); // The primary test loop is a "recursive" closure that will pass // itself as the continuation to async tests. // // Note: It's really important for performance to note that any // calls to testLoop only occur in the tail position. Action testLoop = null; testLoop = () => { if (methods != null && methods.MoveNext()) { // If we were in the middle of a test group and there // are more methods to execute, let's move to the next // test method. // Update the progress this.Progress++; Reporter.Progress(this); // Start the test method Reporter.StartTest(methods.Current); if (methods.Current.Excluded) { // Ignore excluded tests and immediately recurse. Reporter.EndTest(methods.Current); testLoop(); } else { // Execute the test method methods.Current.Test.Start( new ActionContinuation { OnSuccess = () => { // Mark the test as passing, update the // UI, and continue with the next test. methods.Current.Passed = true; Reporter.EndTest(methods.Current); testLoop(); }, OnError = (message) => { // Mark the test as failing, update the // UI, and continue with the next test. methods.Current.Passed = false; methods.Current.ErrorInfo = message; this.Failures++; Reporter.Error(message); Reporter.EndTest(methods.Current); testLoop(); } }); } } else if (groups.MoveNext()) { // If we've finished a test group and there are more, // then move to the next one. // Finish the UI for the last group. if (currentGroup != null) { Reporter.EndGroup(currentGroup); currentGroup = null; } // Setup the UI for this next group currentGroup = groups.Current; Reporter.StartGroup(currentGroup); // Get the methods and immediately recurse which will // start executing them. methods = groups.Current.Methods.OrderBy(m => m.Name).GetEnumerator(); testLoop(); } else { // Otherwise if we've finished the entire test run // Finish the UI for the last group and update the // progress after the very last test method. Reporter.EndGroup(currentGroup); Reporter.Progress(this); // Finish the UI for the test run. Reporter.EndRun(this); // Send the test results if there's a server waiting // for them. if (!string.IsNullOrEmpty(this.Settings.TestResultsServerUrl)) { SendTestResults(); } } }; // Start running the tests testLoop(); }
public void EndGroup(TestGroup group) { Dispatcher.BeginInvoke(() => { _currentGroup = null; }); }
public void StartGroup(TestGroup group) { Dispatcher.BeginInvoke(() => { _currentGroup = new GroupDescription { Name = group.Name }; _groups.Add(_currentGroup); }); }