Merge pull request #36 from Pilchie/assembly-reload

Fix assembly reloading
This commit is contained in:
Dustin Campbell
2015-10-14 13:11:10 -07:00
3 changed files with 121 additions and 79 deletions
+67 -52
View File
@@ -63,7 +63,7 @@
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
@@ -82,11 +82,12 @@
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Content="Search:"
Grid.Row="0" />
<TextBox Grid.Row="1"
Text="{Binding FilterString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="Assemblies:"
Grid.Row="2" />
<ListBox Height="175"
@@ -95,14 +96,35 @@
Grid.Row="3">
<ListBox.ItemTemplate>
<DataTemplate DataType="vm:TestAssemblyViewModel">
<TextBlock Text="{Binding DisplayName}" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding DisplayName}" />
<TextBlock Text=" Discovering tests..."
FontStyle="Italic"
Foreground="Gray">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding State}" Value="{x:Static vm:AssemblyState.Loading}">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Reload" Command="{Binding AssemblyReloadCommand}" />
@@ -113,7 +135,7 @@
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Label Content="Traits:"
Grid.Row="4" />
<ListBox Grid.Row="5"
@@ -176,58 +198,51 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--<ToolBarTray Grid.Row="0"
ToolBarTray.IsLocked="True"
Background="Transparent"
RenderOptions.BitmapScalingMode="NearestNeighbor">
<ToolBar>-->
<StackPanel Orientation="Horizontal">
<ToggleButton IsChecked="{Binding IncludePassedTests}"
BorderThickness="0"
Background="Transparent"
Margin="0,4,2,4"
Grid.Column="0">
<StackPanel Orientation="Horizontal">
<Image Source="Artwork\Passed_large.png" />
<TextBlock Margin="4,0"
FontSize="16"
Text="{Binding TestsPassed, StringFormat={}{0:#\,0}}"
VerticalAlignment="Center" />
</StackPanel>
</ToggleButton>
<ToggleButton IsChecked="{Binding IncludePassedTests}"
BorderThickness="0"
Background="Transparent"
Margin="0,4,2,4"
Grid.Column="0">
<StackPanel Orientation="Horizontal">
<Image Source="Artwork\Passed_large.png" />
<TextBlock Margin="4,0"
FontSize="16"
Text="{Binding TestsPassed, StringFormat={}{0:#\,0}}"
VerticalAlignment="Center" />
</StackPanel>
</ToggleButton>
<ToggleButton IsChecked="{Binding IncludeFailedTests}"
BorderThickness="0"
Background="Transparent"
Margin="2,4"
Grid.Column="1">
<StackPanel Orientation="Horizontal">
<Image Source="Artwork\Failed_large.png" />
<TextBlock Margin="4,0"
FontSize="16"
Text="{Binding TestsFailed, StringFormat={}{0:#\,0}}"
VerticalAlignment="Center" />
</StackPanel>
</ToggleButton>
<ToggleButton IsChecked="{Binding IncludeFailedTests}"
BorderThickness="0"
Background="Transparent"
Margin="2,4"
Grid.Column="1">
<StackPanel Orientation="Horizontal">
<Image Source="Artwork\Failed_large.png" />
<TextBlock Margin="4,0"
FontSize="16"
Text="{Binding TestsFailed, StringFormat={}{0:#\,0}}"
VerticalAlignment="Center" />
</StackPanel>
</ToggleButton>
<ToggleButton IsChecked="{Binding IncludeSkippedTests}"
BorderThickness="0"
Background="Transparent"
Margin="2,4,0,4"
Grid.Column="2">
<StackPanel Orientation="Horizontal">
<Image Source="Artwork\Skipped_large.png" />
<TextBlock Margin="4,0"
FontSize="16"
Text="{Binding TestsSkipped, StringFormat={}{0:#\,0}}"
VerticalAlignment="Center" />
</StackPanel>
</ToggleButton>
</StackPanel>
<!--</ToolBar>
</ToolBarTray>-->
<ToggleButton IsChecked="{Binding IncludeSkippedTests}"
BorderThickness="0"
Background="Transparent"
Margin="2,4,0,4"
Grid.Column="2">
<StackPanel Orientation="Horizontal">
<Image Source="Artwork\Skipped_large.png" />
<TextBlock Margin="4,0"
FontSize="16"
Text="{Binding TestsSkipped, StringFormat={}{0:#\,0}}"
VerticalAlignment="Center" />
</StackPanel>
</ToggleButton>
</StackPanel>
<ListBox ItemsSource="{Binding TestCases}"
<ListBox ItemsSource="{Binding FilteredTestCases}"
SelectionMode="Extended"
Grid.Row="1">
<ListBox.ItemTemplate>
+41 -22
View File
@@ -28,6 +28,10 @@ namespace xunit.runner.wpf.ViewModel
private bool isBusy;
private SearchQuery searchQuery = new SearchQuery();
public ObservableCollection<TestAssemblyViewModel> Assemblies { get; } = new ObservableCollection<TestAssemblyViewModel>();
public FilteredCollectionView<TestCaseViewModel, SearchQuery> FilteredTestCases { get; }
public ObservableCollection<TraitViewModel> Traits => this.traitCollectionView.Collection;
public MainViewModel()
{
if (IsInDesignMode)
@@ -39,10 +43,10 @@ namespace xunit.runner.wpf.ViewModel
this.testUtil = new xunit.runner.wpf.Impl.RemoteTestUtil(Dispatcher.CurrentDispatcher);
this.TestCasesCaption = "Test Cases (0)";
TestCases = new FilteredCollectionView<TestCaseViewModel, SearchQuery>(
this.FilteredTestCases = new FilteredCollectionView<TestCaseViewModel, SearchQuery>(
allTestCases, TestCaseMatches, searchQuery, TestComparer.Instance);
this.TestCases.CollectionChanged += TestCases_CollectionChanged;
this.FilteredTestCases.CollectionChanged += TestCases_CollectionChanged;
this.WindowLoadedCommand = new RelayCommand(OnExecuteWindowLoaded);
this.RunCommand = new RelayCommand(OnExecuteRun, CanExecuteRun);
this.CancelCommand = new RelayCommand(OnExecuteCancel, CanExecuteCancel);
@@ -101,8 +105,8 @@ namespace xunit.runner.wpf.ViewModel
private void TestCases_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
TestCasesCaption = $"Test Cases ({TestCases.Count:#,0})";
MaximumProgress = TestCases.Count;
TestCasesCaption = $"Test Cases ({FilteredTestCases.Count:#,0})";
MaximumProgress = FilteredTestCases.Count;
}
public ICommand ExitCommand { get; } = new RelayCommand(OnExecuteExit);
@@ -202,7 +206,7 @@ namespace xunit.runner.wpf.ViewModel
.ContinueWith(
x =>
{
TestCases.FilterArgument = searchQuery;
FilteredTestCases.FilterArgument = searchQuery;
},
token,
TaskContinuationOptions.None,
@@ -220,10 +224,6 @@ namespace xunit.runner.wpf.ViewModel
};
}
public ObservableCollection<TestAssemblyViewModel> Assemblies { get; } = new ObservableCollection<TestAssemblyViewModel>();
public FilteredCollectionView<TestCaseViewModel, SearchQuery> TestCases { get; }
public ObservableCollection<TraitViewModel> Traits => this.traitCollectionView.Collection;
private async void OnExecuteOpen(object sender, ExecutedRoutedEventArgs e)
{
var fileDialog = new OpenFileDialog
@@ -249,16 +249,23 @@ namespace xunit.runner.wpf.ViewModel
}
var loadingDialog = new LoadingDialog { Owner = MainWindow.Instance };
var newAssemblyViewModels = new List<TestAssemblyViewModel>();
try
{
await ExecuteTestSessionOperation(() =>
await this.ExecuteTestSessionOperation(() =>
{
var taskList = new List<Task>();
foreach (var assembly in assemblies)
{
var assemblyPath = assembly.AssemblyFileName;
taskList.Add(this.testUtil.Discover(assemblyPath, OnTestDiscovered, cancellationTokenSource.Token));
Assemblies.Add(new TestAssemblyViewModel(assembly));
taskList.Add(this.testUtil.Discover(assembly.AssemblyFileName, this.OnTestDiscovered, this.cancellationTokenSource.Token));
var assemblyViewModel = new TestAssemblyViewModel(assembly);
newAssemblyViewModels.Add(assemblyViewModel);
this.Assemblies.Add(assemblyViewModel);
assemblyViewModel.State = AssemblyState.Loading;
}
return taskList;
@@ -266,6 +273,11 @@ namespace xunit.runner.wpf.ViewModel
}
finally
{
foreach (var assemblyViewModel in newAssemblyViewModels)
{
assemblyViewModel.State = AssemblyState.Ready;
}
loadingDialog.Close();
}
}
@@ -278,9 +290,11 @@ namespace xunit.runner.wpf.ViewModel
await ExecuteTestSessionOperation(() =>
{
var taskList = new List<Task>();
foreach (var assembly in assemblies)
foreach (var assemblyViewModel in assemblies)
{
var assemblyPath = assembly.FileName;
assemblyViewModel.State = AssemblyState.Loading;
var assemblyPath = assemblyViewModel.FileName;
RemoveAssemblyTestCases(assemblyPath);
taskList.Add(this.testUtil.Discover(assemblyPath, OnTestDiscovered, cancellationTokenSource.Token));
@@ -293,6 +307,11 @@ namespace xunit.runner.wpf.ViewModel
}
finally
{
foreach (var assemblyViewModel in assemblies)
{
assemblyViewModel.State = AssemblyState.Ready;
}
loadingDialog.Close();
}
}
@@ -313,7 +332,7 @@ namespace xunit.runner.wpf.ViewModel
var i = 0;
while (i < this.allTestCases.Count)
{
if (this.allTestCases[i].AssemblyFileName == assemblyPath)
if (string.Compare(this.allTestCases[i].AssemblyFileName, assemblyPath, StringComparison.OrdinalIgnoreCase) == 0)
{
this.allTestCases.RemoveAt(i);
}
@@ -383,7 +402,7 @@ namespace xunit.runner.wpf.ViewModel
(fileName?.EndsWith(".json", StringComparison.OrdinalIgnoreCase) ?? false);
private bool CanExecuteRun()
=> !IsBusy && TestCases.Any();
=> !IsBusy && FilteredTestCases.Any();
private async void OnExecuteRun()
{
@@ -402,15 +421,15 @@ namespace xunit.runner.wpf.ViewModel
CurrentRunState = TestState.NotRun;
Output = string.Empty;
foreach (var tc in TestCases)
foreach (var tc in FilteredTestCases)
{
tc.State = TestState.NotRun;
}
var runAll = TestCases.Count == this.allTestCases.Count;
var runAll = FilteredTestCases.Count == this.allTestCases.Count;
var testSessionList = new List<Task>();
foreach (var assemblyPath in TestCases.Select(x => x.AssemblyFileName).Distinct())
foreach (var assemblyPath in FilteredTestCases.Select(x => x.AssemblyFileName).Distinct())
{
Task task;
if (runAll)
@@ -419,7 +438,7 @@ namespace xunit.runner.wpf.ViewModel
}
else
{
var testCaseDisplayNames = TestCases
var testCaseDisplayNames = FilteredTestCases
.Where(x => x.AssemblyFileName == assemblyPath)
.Select(x => x.DisplayName)
.ToImmutableArray();
@@ -468,7 +487,7 @@ namespace xunit.runner.wpf.ViewModel
private void OnTestFinished(TestResultData testResultData)
{
var testCase = TestCases.Single(x => x.DisplayName == testResultData.TestCaseDisplayName);
var testCase = FilteredTestCases.Single(x => x.DisplayName == testResultData.TestCaseDisplayName);
testCase.State = testResultData.TestState;
TestsCompleted++;
@@ -1,10 +1,5 @@
using GalaSoft.MvvmLight;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace xunit.runner.wpf.ViewModel
{
@@ -12,6 +7,7 @@ namespace xunit.runner.wpf.ViewModel
{
private readonly AssemblyAndConfigFile _assembly;
private bool _isSelected;
private AssemblyState _state;
public TestAssemblyViewModel(AssemblyAndConfigFile assembly)
{
@@ -27,5 +23,17 @@ namespace xunit.runner.wpf.ViewModel
get { return _isSelected; }
set { Set(ref _isSelected, value, nameof(IsSelected)); }
}
public AssemblyState State
{
get { return _state; }
set { Set(ref _state, value, nameof(State)); }
}
}
public enum AssemblyState
{
Ready,
Loading
}
}