Skip to content

Commit

Permalink
Add tree navigation of unit tests as referenced by issues nunit#14, n…
Browse files Browse the repository at this point in the history
  • Loading branch information
bstadick committed Jan 22, 2022
1 parent 92649e3 commit 605a724
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 31 deletions.
63 changes: 59 additions & 4 deletions src/nunit.xamarin/View/ResultsView.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ***********************************************************************

using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework.Interfaces;
using NUnit.Runner.ViewModel;
using Xamarin.Forms;

Expand All @@ -31,6 +34,15 @@ namespace NUnit.Runner.View
/// </summary>
public partial class ResultsView : ContentPage
{
#region Private Fields

/// <summary>
/// Holds the results view <see cref="ResultsViewModel"/>.
/// </summary>
private readonly ResultsViewModel _model;

#endregion

#region Constructors

/// <summary>
Expand All @@ -39,8 +51,9 @@ public partial class ResultsView : ContentPage
/// <param name="model">The result view model that contains the test results.</param>
internal ResultsView(ResultsViewModel model)
{
model.Navigation = Navigation;
BindingContext = model;
_model = model;
_model.Navigation = Navigation;
BindingContext = _model;
InitializeComponent();
}

Expand All @@ -55,10 +68,52 @@ internal ResultsView(ResultsViewModel model)
/// <param name="e">The event arguments.</param>
private async void ViewTest(object sender, SelectedItemChangedEventArgs e)
{
// Cast selected item to correct type
if (!(e.SelectedItem is ResultViewModel result))
{
return;
}

// Unselect item to allow for reentry to item after navigating back
if(sender is ListView view)
{
view.SelectedItem = null;
}

// Navigate to new test result view
if (e.SelectedItem is ResultViewModel result)
await NavigateToTest(result.TestResult);
}

/// <summary>
/// Navigates to the given test result.
/// </summary>
/// <param name="result">The test result to navigate to.</param>
/// <returns>A <see cref="Task"/> to await.</returns>
private async Task NavigateToTest(ITestResult result)
{
while (true)
{
await Navigation.PushAsync(new TestView(new TestViewModel(result.TestResult)));
if (result.HasChildren)
{
if (result.Children.Count() == 1)
{
// If only one child exists, skip to its child to simplify navigation
result = result.Children.First();
continue;
}
else
{
// Navigate to the child test suite
await Navigation.PushAsync(new ResultsView(new ResultsViewModel(result.Children, _model.IsAllResults)));
}
}
else
{
// Navigate to the child test result (leaf)
await Navigation.PushAsync(new TestView(new TestViewModel(result)));
}

break;
}
}

Expand Down
38 changes: 11 additions & 27 deletions src/nunit.xamarin/ViewModel/ResultsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,48 +49,32 @@ internal class ResultsViewModel : BaseViewModel
#region Constructors

/// <summary>
/// Constructs a <see cref="ResultsViewModel"/> with a collection of <see cref="ITestResult"/> and select filtering.
/// Constructs a <see cref="ResultsViewModel"/> with a <see cref="ITestResult"/> and select filtering.
/// </summary>
/// <param name="results">The collection of the results in a test run.</param>
/// <param name="result">The result in a test run.</param>
/// <param name="viewAll">
/// <see langword="true" /> to add all tests, otherwise only shows those that did not pass.
/// </param>
public ResultsViewModel(IEnumerable<ITestResult> results, bool viewAll)
{
Results = new ObservableCollection<ResultViewModel>();
IsAllResults = viewAll;
foreach (ITestResult result in results)
{
AddTestResults(result, viewAll);
}
}

#endregion

#region Private Methods
public ResultsViewModel(ITestResult result, bool viewAll) : this(new List<ITestResult> { result }, viewAll) { }

/// <summary>
/// Recursively adds the test results to the <see cref="Results" /> collection.
/// Constructs a <see cref="ResultsViewModel"/> with a collection of <see cref="ITestResult"/> and select filtering.
/// </summary>
/// <param name="result">The test or test suite results to add.</param>
/// <param name="results">The collection of the results in a test run.</param>
/// <param name="viewAll">
/// <see langword="true" /> to add all tests, otherwise only shows those that did not pass.
/// </param>
private void AddTestResults(ITestResult result, bool viewAll)
public ResultsViewModel(IEnumerable<ITestResult> results, bool viewAll)
{
if (result.Test.IsSuite)
Results = new ObservableCollection<ResultViewModel>();
IsAllResults = viewAll;
foreach (ITestResult result in results)
{
// Recursively add test results
foreach (ITestResult childResult in result.Children)
if (viewAll || result.ResultState.Status != TestStatus.Passed)
{
AddTestResults(childResult, viewAll);
Results.Add(new ResultViewModel(result));
}
}
else if (viewAll || result.ResultState.Status != TestStatus.Passed)
{
// Add result if all results is selected or if result is not passed
Results.Add(new ResultViewModel(result));
}
}

#endregion
Expand Down
1 change: 1 addition & 0 deletions src/nunit.xamarin/ViewModel/TestViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ internal class TestViewModel : ResultViewModel
/// <summary>
/// Gets the test results stack trace.
/// </summary>
/// <remarks>The StackTrace may not always be populated in the test results.</remarks>
public string StackTrace { get; }

/// <summary>
Expand Down

0 comments on commit 605a724

Please sign in to comment.