/// <summary> /// Run test method /// </summary> /// <param name="method">Test method</param> /// <param name="counter">Test result counter</param> public void RunMethod(MethodInfo method, TestResultCounter counter) { // Run method in separate thread var type = method.DeclaringType; var thread = new Thread(() => { // Set running runner currentRunner.Value = this; // Override http context using (HttpManager.OverrideContext("", "GET")) { // Create test instance object instance = null; try { instance = Activator.CreateInstance(type); } catch (Exception ex) { WriteErrorMessage($"create instance of {type.Name} failed: {ex}"); return; } // Call test method try { TriggerEvent(h => h.OnTestStarting, new TestStartingInfo(this, method, instance)); method.FastInvoke(instance); throw new AssertPassedException(); } catch (AssertPassedException) { // Test passed ++counter.Passed; TriggerEvent(h => h.OnTestPassed, new TestPassedInfo(this, method, instance)); } catch (AssertSkipedException ex) { // Test skipped ++counter.Skipped; TriggerEvent(h => h.OnTestSkipped, new TestSkippedInfo(this, method, instance, ex)); } catch (Exception ex) { // Test failed ++counter.Failed; TriggerEvent(h => h.OnTestFailed, new TestFailedInfo(this, method, instance, ex)); } // If test instance is disposable, dispose it try { (instance as IDisposable)?.Dispose(); } catch (Exception ex) { WriteErrorMessage($"dispose instance of {type.Name} failed: {ex}"); return; } } }); thread.Start(); thread.Join(); }
/// <summary> /// Run all tests in assembly<br/> /// 运行程序集中包含的所有测试<br/> /// </summary> public void Run() { // Triggering starting event TriggerEvent(h => h.OnAllTestStarting, new AllTestStartingInfo(this)); // Create result counter var counter = new TestResultCounter(); // Find all types in assembly have TestsAttribute foreach (var type in Assembly.GetTypes()) { if (type.GetCustomAttribute <TestsAttribute>() == null) { continue; } // Find and run public methods foreach (var method in type.FastGetMethods( BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { RunMethod(method, counter); } } // Triggering completed event TriggerEvent(h => h.OnAllTestCompleted, new AllTestCompletedInfo(this, counter)); }