Skip to content

Commit

Permalink
Add test progress bar and status and fix test summary count in regard…
Browse files Browse the repository at this point in the history
…s to tests with warnings referenced by issue nunit#31 and nunit#75.
  • Loading branch information
bstadick committed Jan 23, 2022
1 parent 0b05cb9 commit 6245840
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/nunit.xamarin/Helpers/ResultSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public Color OverallResultColor
/// </summary>
public int RunCount
{
get { return PassCount + FailureCount + ErrorCount + InconclusiveCount; }
get { return PassCount + FailureCount + ErrorCount + InconclusiveCount + WarningCount; }
}

/// <summary>
Expand Down
88 changes: 79 additions & 9 deletions src/nunit.xamarin/Helpers/TestPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@
// ***********************************************************************

using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using NUnit.Framework.Api;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Runner.Annotations;
using NUnit.Runner.Services;

namespace NUnit.Runner.Helpers
{
/// <summary>
/// Contains all assemblies for a test run, and controls execution of tests and collection of results.
/// </summary>
internal class TestPackage
internal class TestPackage : INotifyPropertyChanged
{
#region Private Fields

Expand All @@ -45,6 +49,33 @@ internal class TestPackage

#endregion

#region Public Properties

/// <summary>
/// Gets or sets the user options for the test suite.
/// </summary>
public TestOptions Options { get; set; }

/// <summary>
/// Gets the progress listener for running tests.
/// </summary>
public RunnerTestListener ProgressListener { get; private set; }

#endregion

#region Constructors

/// <summary>
/// Constructs a <see cref="TestPackage"/>.
/// </summary>
/// <param name="options">The test options for the test package.</param>
public TestPackage(TestOptions options)
{
Options = options;
}

#endregion

#region Public Methods

/// <summary>
Expand All @@ -67,34 +98,73 @@ public async Task<TestRunResult> ExecuteTests(ITestFilter filter = null)
ITestFilter testFilter = filter ?? TestFilter.Empty;
TestRunResult resultPackage = new TestRunResult();

// Initialize test runner for each test assembly
NUnitTestAssemblyRunner runner = new NUnitTestAssemblyRunner(new DefaultTestAssemblyBuilder());
foreach ((Assembly assembly, Dictionary<string, object> options) in _testAssemblies)
{
NUnitTestAssemblyRunner runner = await LoadTestAssemblyAsync(assembly, options).ConfigureAwait(false);
ITestResult result = await Task.Run(() => runner.Run(TestListener.NULL, testFilter))
.ConfigureAwait(false);
resultPackage.AddResult(result);
await LoadTestAssemblyAsync(runner, assembly, options).ConfigureAwait(false);
}

// Configure the progress listener
long testCount = runner.CountTestCases(testFilter);
ProgressListener = new RunnerTestListener(Options?.ProgressListener, testCount);
ProgressListener.PropertyChanged += ProgressListenerOnPropertyChanged;

// Execute test runners
ITestResult result = await Task.Run(() => runner.Run(ProgressListener, testFilter))
.ConfigureAwait(false);
resultPackage.AddResult(result);

// Return the results
resultPackage.CompleteTestRun();
return resultPackage;
}

#endregion

#region Implementation of INotifyPropertyChanged

/// <inheritdoc cref="INotifyPropertyChanged.PropertyChanged" />
public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Calls the <see cref="PropertyChanged" /> event for the given property.
/// </summary>
/// <param name="propertyName">The name of the property that has changed.</param>
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

#endregion

#region Private Methods

/// <summary>
/// Loads the test assembly to be ran.
/// </summary>
/// <param name="runner">The unit test runner.</param>
/// <param name="assembly">The test assembly.</param>
/// <param name="options">An optional dictionary of options for loading the assembly.</param>
/// <returns></returns>
private static async Task<NUnitTestAssemblyRunner> LoadTestAssemblyAsync(Assembly assembly,
/// <returns>A <see cref="Task"/> to await.</returns>
private static async Task LoadTestAssemblyAsync(NUnitTestAssemblyRunner runner,
Assembly assembly,
Dictionary<string, object> options)
{
NUnitTestAssemblyRunner runner = new NUnitTestAssemblyRunner(new DefaultTestAssemblyBuilder());
await Task.Run(() => runner.Load(assembly, options ?? new Dictionary<string, object>()));
return runner;
}

/// <summary>
/// Handler for when the <see cref="ProgressListener"/> properties have changed.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The event arguments.</param>
private void ProgressListenerOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
// Notify that the underlying ProgressListener property has updated
OnPropertyChanged(nameof(ProgressListener));
}

#endregion
Expand Down
173 changes: 173 additions & 0 deletions src/nunit.xamarin/Services/RunnerTestListener.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// ***********************************************************************
// Copyright (c) 2022 NUnit Project
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

using System.ComponentModel;
using System.Runtime.CompilerServices;
using NUnit.Framework.Interfaces;
using NUnit.Runner.Annotations;

namespace NUnit.Runner.Services
{
/// <summary>
/// Creates a custom <see cref="ITestListener"/> to track progress internally.
/// </summary>
internal class RunnerTestListener : ITestListener, INotifyPropertyChanged
{
#region Private Fields

/// <summary>
/// Holds the user test listener.
/// </summary>
private readonly ITestListener _listener;

/// <summary>
/// Holds the number of tests ran.
/// </summary>
private long _ranCount;

/// <summary>
/// Holds the currently running test.
/// </summary>
private string _currentTest;

#endregion

#region Public Properties

/// <summary>
/// Gets the test progress as a percentage between [0, 1].
/// </summary>
public double Progress
{
get { return TestCount != 0 ? RanCount / (double)TestCount : 0; }
}

/// <summary>
/// Gets the number of tests to run.
/// </summary>
public long TestCount { get; }

/// <summary>
/// Gets the number of tests ran.
/// </summary>
public long RanCount
{
get { return _ranCount; }
private set
{
_ranCount = value;
OnPropertyChanged();
OnPropertyChanged(nameof(Progress));
}
}

/// <summary>
/// Gets the currently running test name.
/// </summary>
public string CurrentTest
{
get { return string.IsNullOrWhiteSpace(_currentTest) ? string.Empty : _currentTest; }
private set
{
_currentTest = string.IsNullOrWhiteSpace(value) ? string.Empty : value;
OnPropertyChanged();
}
}

#endregion

#region Constructors

/// <summary>
/// Constructs a <see cref="RunnerTestListener"/> to track test progress.
/// </summary>
/// <param name="listener">The user provided test listener to invoke.</param>
/// <param name="testCount">The number of tests being ran.</param>
public RunnerTestListener(ITestListener listener, long testCount)
{
_listener = listener;
TestCount = testCount;
}

#endregion

#region Implementation of ITestListener

/// <inheritdoc cref="TestStarted"/>
public void TestStarted(ITest test)
{
// Update currently running test
if (!test.HasChildren)
{
CurrentTest = test.FullName;
}

_listener?.TestStarted(test);
}

/// <inheritdoc cref="TestFinished"/>
public void TestFinished(ITestResult result)
{
// Update test progress
if (!result.HasChildren)
{
RanCount++;
CurrentTest = string.Empty;
}

_listener?.TestFinished(result);
}

/// <inheritdoc cref="TestOutput"/>
public void TestOutput(TestOutput output)
{
_listener?.TestOutput(output);
}

/// <inheritdoc cref="SendMessage"/>
public void SendMessage(TestMessage message)
{
_listener?.SendMessage(message);
}

#endregion

#region Implementation of INotifyPropertyChanged

/// <inheritdoc cref="INotifyPropertyChanged.PropertyChanged" />
public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// Calls the <see cref="PropertyChanged" /> event for the given property.
/// </summary>
/// <param name="propertyName">The name of the property that has changed.</param>
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

#endregion
}
}
6 changes: 6 additions & 0 deletions src/nunit.xamarin/Services/TestOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using System;
using System.IO;
using System.Threading.Tasks;
using NUnit.Framework.Interfaces;
using NUnit.Runner.Helpers;

namespace NUnit.Runner.Services
Expand Down Expand Up @@ -54,6 +55,11 @@ public class TestOptions
/// </summary>
public bool AddCurrentAssemblyForTest { get; set; }

/// <summary>
/// Gets or sets the test progress listener.
/// </summary>
public ITestListener ProgressListener { get; set; }

/// <summary>
/// Gets information about the tcp listener host and port.
/// </summary>
Expand Down
Loading

0 comments on commit 6245840

Please sign in to comment.