diff --git a/src/Microsoft.DotNet.XHarness.Tests.Runners/AndroidApplicationEntryPoint.cs b/src/Microsoft.DotNet.XHarness.Tests.Runners/AndroidApplicationEntryPoint.cs index 33cb4cd1a..e55198bf6 100644 --- a/src/Microsoft.DotNet.XHarness.Tests.Runners/AndroidApplicationEntryPoint.cs +++ b/src/Microsoft.DotNet.XHarness.Tests.Runners/AndroidApplicationEntryPoint.cs @@ -36,10 +36,7 @@ public override async Task RunAsync() logger.MinimumLogLevel = MinimumLogLevel.Info; var testAssemblies = GetTestAssemblies(); - var runner = await CreateRunner(logger); - - // if we have ignore files, ignore those tests - await runner.Run(testAssemblies).ConfigureAwait(false); + var runner = await InternalRunAsync(logger); TestRunner.Jargon jargon = Core.TestRunner.Jargon.NUnitV3; switch (options.XmlVersion) diff --git a/src/Microsoft.DotNet.XHarness.Tests.Runners/ApplicationEntryPoint.cs b/src/Microsoft.DotNet.XHarness.Tests.Runners/ApplicationEntryPoint.cs index f03b7fb69..e3743769f 100644 --- a/src/Microsoft.DotNet.XHarness.Tests.Runners/ApplicationEntryPoint.cs +++ b/src/Microsoft.DotNet.XHarness.Tests.Runners/ApplicationEntryPoint.cs @@ -29,10 +29,25 @@ public enum TestRunnerType /// Assemblies: Provide a list of the assembly information to run. /// assemblies can be loaded from disk or from memory, is up to the /// implementor. + /// + /// Clients that register to the class events and want to update the UI + /// are responsable to do so in the main UI thread. The application entry + /// point does not guarantee that the tests are executed in the ui thread. + /// /// public abstract class ApplicationEntryPoint { + /// + /// Event raised when the test run has started. + /// + public event EventHandler TestsStarted; + + /// + /// Event raised when the test run has completed. + /// + public event EventHandler TestsCompleted; + protected abstract int? MaxParallelThreads { get; } /// /// Must be implemented and return a class that returns the information @@ -73,7 +88,7 @@ public abstract class ApplicationEntryPoint /// public MinimumLogLevel MinimumLogLevel { get; set; } = MinimumLogLevel.Info; - protected async Task CreateRunner(LogWriter logger) + protected async Task InternalRunAsync (LogWriter logger) { logger.MinimumLogLevel = MinimumLogLevel; TestRunner runner; @@ -102,6 +117,17 @@ protected async Task CreateRunner(LogWriter logger) runner.SkipTests(skippedTests); } } + + var testAssemblies = GetTestAssemblies(); + // notify the clients we are starting + TestsStarted?.Invoke(this, new EventArgs()); + + await runner.Run(testAssemblies).ConfigureAwait(false); + + var result = new TestRunResult(runner); + // notify the client we are done and the results, but do not expose + // the runner. + TestsCompleted?.Invoke(this, result); return runner; } } diff --git a/src/Microsoft.DotNet.XHarness.Tests.Runners/TestRunResult.cs b/src/Microsoft.DotNet.XHarness.Tests.Runners/TestRunResult.cs new file mode 100644 index 000000000..42e4f2b4f --- /dev/null +++ b/src/Microsoft.DotNet.XHarness.Tests.Runners/TestRunResult.cs @@ -0,0 +1,55 @@ +using Microsoft.DotNet.XHarness.Tests.Runners.Core; + +namespace Microsoft.DotNet.XHarness.Tests.Runners +{ + public struct TestRunResult + { + /// + /// Retrieve the number of executed tests in a run. + /// + public long ExecutedTests { get; private set; } + + /// + /// Retrieve the number of failed tests in a run. + /// + public long FailedTests { get; private set; } + + /// + /// Retrieve the number of not executed tests due to the filters in a + /// run. + /// + public long FilteredTests { get; private set; } + + /// + /// Retrieve the number of inconclusive tests in a run. + /// + public long InconclusiveTests { get; private set; } + + /// + /// Retrieve the number of passed tests in a run. + /// + public long PassedTests { get; private set; } + + /// + /// Retrieve the number of skipped tests in a run. + /// + public long SkippedTests { get; private set; } + + /// + /// Retrieve the total number of tests in a run. This value + /// includes all skipped and filtered tests and might no be equal + /// to the value returned by ExecutedTests. + /// + public long TotalTests { get; private set; } + + internal TestRunResult(TestRunner runner) { + ExecutedTests = runner.ExecutedTests; + FailedTests = runner.FailedTests; + FilteredTests = runner.FilteredTests; + InconclusiveTests = runner.InconclusiveTests; + PassedTests = runner.PassedTests; + SkippedTests = runner.SkippedTests; + TotalTests = runner.TotalTests; + } + } +} diff --git a/src/Microsoft.DotNet.XHarness.Tests.Runners/iOSApplicationEntryPoint.cs b/src/Microsoft.DotNet.XHarness.Tests.Runners/iOSApplicationEntryPoint.cs index 14bdb44ec..1c8e13f13 100644 --- a/src/Microsoft.DotNet.XHarness.Tests.Runners/iOSApplicationEntryPoint.cs +++ b/src/Microsoft.DotNet.XHarness.Tests.Runners/iOSApplicationEntryPoint.cs @@ -31,11 +31,9 @@ public override async Task RunAsync() // we will write the normal console output using the LogWriter var logger = (writer == null || options.EnableXml) ? new LogWriter(Device) : new LogWriter(Device, writer); logger.MinimumLogLevel = MinimumLogLevel.Info; - var testAssemblies = GetTestAssemblies(); - var runner = await CreateRunner(logger); // if we have ignore files, ignore those tests - await runner.Run(testAssemblies).ConfigureAwait(false); + var runner = await InternalRunAsync(logger); TestRunner.Jargon jargon = Core.TestRunner.Jargon.NUnitV3; switch (options.XmlVersion)