Merge pull request #36 from Pilchie/assembly-reload
Fix assembly reloading
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user