Progress bar and test state UI

This commit is contained in:
Kevin Pilch-Bisson
2015-08-09 10:23:49 -07:00
parent e9ff5d9325
commit 5c2e9be8c1
5 changed files with 133 additions and 15 deletions
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using xunit.runner.wpf.ViewModel;
namespace xunit.runner.wpf.Converters
{
public class TestStateConverter : IValueConverter
{
private static ImageSource passedSource;
private static ImageSource failedSource;
private static ImageSource skippedSource;
static TestStateConverter()
{
passedSource = LoadResourceImage("Passed.ico");
failedSource = LoadResourceImage("Failed.ico");
skippedSource = LoadResourceImage("Skipped.ico");
}
private static BitmapImage LoadResourceImage(string resourceName)
{
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri("pack://application:,,,/xunit.runner.wpf;component/Artwork/" + resourceName);
image.EndInit();
return image;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var state = (TestState)value;
if (targetType == typeof(Brush))
{
switch (state)
{
case TestState.Failed:
return Brushes.Red;
case TestState.Skipped:
return Brushes.Yellow;
case TestState.Passed:
return Brushes.Green;
default:
return Brushes.Gray;
}
}
else if (targetType == typeof(ImageSource))
{
switch (state)
{
case TestState.Failed:
return failedSource;
case TestState.Skipped:
return skippedSource;
case TestState.Passed:
return passedSource;
default:
return null;
}
}
else
{
throw new NotSupportedException();
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
+15 -8
View File
@@ -4,6 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:xunit.runner.wpf"
xmlns:converters="clr-namespace:xunit.runner.wpf.Converters"
xmlns:vm="clr-namespace:xunit.runner.wpf.ViewModel"
mc:Ignorable="d"
DataContext="{Binding Main, Source={StaticResource Locator}}"
@@ -13,6 +14,10 @@
Height="600"
Width="525">
<Window.Resources>
<converters:TestStateConverter x:Key="TestStateConverter" />
</Window.Resources>
<Grid local:CommandBindings.Registration="{Binding CommandBindings}">
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
@@ -147,12 +152,14 @@
<DataTemplate DataType="vm:TestCaseViewModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding State}"
Grid.Column="0" />
<Image Width="16"
Margin="2"
Source="{Binding Path=State, Mode=OneWay, Converter={StaticResource TestStateConverter}}"
Grid.Column="0" />
<TextBlock Text="{Binding DisplayName}"
Grid.Column="1" />
</Grid>
@@ -171,11 +178,11 @@
</GroupBox>
</Grid>
<ProgressBar
Minimum="0"
Maximum="{Binding MaximumProgress}"
Value="{Binding Path=TestsCompleted}"
Grid.Column="1"
<ProgressBar Foreground="{Binding Path=CurrentRunState, Converter={StaticResource TestStateConverter}, Mode=OneWay}"
Minimum="0"
Maximum="{Binding MaximumProgress}"
Value="{Binding Path=TestsCompleted}"
Grid.Column="1"
Grid.Row="1"
Margin="3" />
</Grid>
+22 -7
View File
@@ -76,6 +76,13 @@ namespace xunit.runner.wpf.ViewModel
set { Set(ref maximumProgress, value); }
}
private TestState currentRunState;
public TestState CurrentRunState
{
get { return currentRunState; }
set { Set(ref currentRunState, value); }
}
private string searchQuery = string.Empty;
public string SearchQuery
{
@@ -204,7 +211,7 @@ namespace xunit.runner.wpf.ViewModel
private readonly Func<bool> isCancelRequested;
private readonly IEnumerable<TestCaseViewModel> testCases;
public event EventHandler TestFinished;
public event EventHandler<TestStateEventArgs> TestFinished;
public TestRunVisitor(IEnumerable<TestCaseViewModel> testCases, Func<bool> isCancelRequested)
{
@@ -216,7 +223,7 @@ namespace xunit.runner.wpf.ViewModel
{
var testCase = testCases.Single(tc => tc.DisplayName == testFailed.TestCase.DisplayName);
testCase.State = TestState.Failed;
TestFinished?.Invoke(this, EventArgs.Empty);
TestFinished?.Invoke(this, TestStateEventArgs.Failed);
return !isCancelRequested();
}
@@ -224,7 +231,7 @@ namespace xunit.runner.wpf.ViewModel
{
var testCase = testCases.Single(tc => tc.DisplayName == testPassed.TestCase.DisplayName);
testCase.State = TestState.Passed;
TestFinished?.Invoke(this, EventArgs.Empty);
TestFinished?.Invoke(this, TestStateEventArgs.Passed);
return !isCancelRequested();
}
@@ -232,7 +239,7 @@ namespace xunit.runner.wpf.ViewModel
{
var testCase = testCases.Single(tc => tc.DisplayName == testSkipped.TestCase.DisplayName);
testCase.State = TestState.Skipped;
TestFinished?.Invoke(this, EventArgs.Empty);
TestFinished?.Invoke(this, TestStateEventArgs.Skipped);
return !isCancelRequested();
}
}
@@ -312,9 +319,13 @@ namespace xunit.runner.wpf.ViewModel
}
}
private void TestRunVisitor_TestFinished(object sender, EventArgs e)
private void TestRunVisitor_TestFinished(object sender, TestStateEventArgs e)
{
TestsCompleted++;
if (e.State > CurrentRunState)
{
CurrentRunState = e.State;
}
}
private bool CanExecuteCancel() => IsBusy && !IsCancelRequested;
@@ -325,13 +336,17 @@ namespace xunit.runner.wpf.ViewModel
}
}
/// <summary>
/// Note: More severe states are higher numbers.
/// <see cref="MainViewModel.TestRunVisitor_TestFinished(object, TestStateEventArgs)"/>
/// </summary>
public enum TestState
{
All = 0,
NotRun,
Passed,
Failed,
Skipped,
NotRun
Failed,
}
public class TestComparer : IComparer<TestCaseViewModel>
@@ -0,0 +1,17 @@
using System;
namespace xunit.runner.wpf.ViewModel
{
public class TestStateEventArgs : EventArgs
{
public static TestStateEventArgs Failed { get; } = new TestStateEventArgs(TestState.Failed);
public static TestStateEventArgs Passed { get; } = new TestStateEventArgs(TestState.Passed);
public static TestStateEventArgs Skipped { get; } = new TestStateEventArgs(TestState.Skipped);
private TestStateEventArgs(TestState state)
{
this.State = state;
}
public TestState State { get; }
}
}
+2
View File
@@ -91,11 +91,13 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="CommandBindings.cs" />
<Compile Include="Converters\TestStateConverter.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="FilteredCollectionView.cs" />
<Compile Include="ViewModel\MainViewModel.cs" />
<Compile Include="ViewModel\TestCaseViewModel.cs" />
<Compile Include="ViewModel\TestAssemblyViewModel.cs" />
<Compile Include="ViewModel\TestStateEventArgs.cs" />
<Compile Include="ViewModel\ViewModelLocator.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>