/// <summary> /// Run all tests with the <c>PageTestAttribute</c>. /// </summary> /// <param name="source">The source page object.</param> /// <param name="pageObjectStatistics">Whether to write the result tree.</param> /// <param name="filter">The test method filter predicate.</param> /// <param name="writeTree">Whether to write the result tree.</param> /// <returns>This page object.</returns> private static Tree TestBottomUp(this IPageObject source, Func <MethodInfo, Type, bool> filter, bool writeTree, PageObjectStatistics pageObjectStatistics) { Trace.WriteLine($"Run tests for {source.GetType().FullName}"); // run tests for every child foreach (var child in source.Children()) { TestBottomUp(child, filter, false, pageObjectStatistics); } // run tests for this page object return(Test(source, filter, writeTree, pageObjectStatistics)); }
/// <summary> /// Run tests for this page object. /// </summary> /// <param name="source">The source page object.</param> /// <param name="filter">The test method filter predicate.</param> /// <param name="writeTree">Whether to write the result tree.</param> /// <param name="pageObjectStatistics">The page object statistics.</param> /// <returns>This page object.</returns> private static Tree Test(this IPageObject source, Func <MethodInfo, Type, bool> filter, bool writeTree, PageObjectStatistics pageObjectStatistics) { filter = filter ?? ((e, f) => true); Tree result = null; bool success = true; try { foreach (Type classWithTests in source.TestClasses()) { Trace.WriteLine($"Found page test class for current class {source.GetType().ToString()}: {classWithTests.ToString()}"); // create and initialize page test class var instance = (IPageObjectTestsInternal)Activator.CreateInstance(classWithTests); instance.Init(source); // check if tests should be executed if (instance.Runnable) { Trace.WriteLine("Runnable returned true; running tests..."); } else { Trace.WriteLine("Runnable returned false; skipping tests"); continue; } // get page test methods, and order them from top to bottom // ordering does not respect inheritance var methods = classWithTests.GetMethods().Where(m => m.GetCustomAttributes(typeof(PageTestAttribute), false).Length > 0); var methodsByLine = methods.OrderBy(asd => asd.GetCustomAttribute <PageTestAttribute>(true).Line); var matchingMethodsByLine = methodsByLine.Where(f => filter(f, classWithTests)); int testMethodsCount = matchingMethodsByLine.Count(); if (testMethodsCount > 0) { Trace.WriteLine($"Found {testMethodsCount} test methods"); } else { Trace.WriteLine("No test method found; skipping test class"); continue; } Trace.WriteLine($"Execute function {nameof(IPageObjectTests.BeforeFirstTest)}..."); instance.BeforeFirstTest(); // check if tests should be executed if (!instance.ReadyToRun) { throw new TestNotReadyToRunException(classWithTests.FullName); } else { Trace.WriteLine("Tests are ready to run..."); } // create class statistics object TestClassStatistic testClassStatistic = new TestClassStatistic(classWithTests); // execute test methods try { foreach (var testMethod in matchingMethodsByLine) { Test(testClassStatistic, instance, testMethod); } Trace.WriteLine($"Execute function {nameof(IPageObjectTests.AfterLastTest)}..."); instance.AfterLastTest(); } finally { success = false; pageObjectStatistics.Add(source, testClassStatistic); } } } finally { result = Root(source).Tree; foreach (var pair in pageObjectStatistics.Stats) { // merge trees result += pair.Value; result += new Edge { To = pair.Value.Root.Id, From = new Node() { Id = pair.Key.FullName }.Id }; } if (!success || writeTree) { result.WriteGraph(); } } return(result); }