Load assemblies from command line on startup

Also, display a dialog while loading

Fixes #10
This commit is contained in:
Kevin Pilch-Bisson
2015-08-15 20:27:04 -07:00
parent eeeb04c78e
commit 4e22e89d6e
6 changed files with 134 additions and 12 deletions
+30
View File
@@ -0,0 +1,30 @@
<Window x:Class="xunit.runner.wpf.LoadingDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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"
mc:Ignorable="d"
Title="Discovering Tests"
SizeToContent="WidthAndHeight"
ResizeMode="NoResize"
ShowInTaskbar="False"
MinHeight="100"
MinWidth="300"
WindowStartupLocation="CenterOwner">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="Discovering tests in:"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Row="0"/>
<TextBlock Text="{Binding Path=AssemblyFileName, RelativeSource={RelativeSource AncestorType=Window}}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Row="1"/>
</Grid>
</Window>
+36
View File
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace xunit.runner.wpf
{
/// <summary>
/// Interaction logic for LoadingDialog.xaml
/// </summary>
public partial class LoadingDialog : Window
{
public LoadingDialog()
{
InitializeComponent();
}
public string AssemblyFileName
{
get { return (string)GetValue(AssemblyFileNameProperty); }
set { SetValue(AssemblyFileNameProperty, value); }
}
public static readonly DependencyProperty AssemblyFileNameProperty =
DependencyProperty.Register(nameof(AssemblyFileName), typeof(string), typeof(LoadingDialog));
}
}
+8
View File
@@ -6,6 +6,8 @@
xmlns:local="clr-namespace:xunit.runner.wpf"
xmlns:converters="clr-namespace:xunit.runner.wpf.Converters"
xmlns:vm="clr-namespace:xunit.runner.wpf.ViewModel"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"
mc:Ignorable="d"
DataContext="{Binding Main, Source={StaticResource Locator}}"
Title="xUnit.net Test Runner"
@@ -14,6 +16,12 @@
Height="600"
Width="525">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<cmd:EventToCommand Command="{Binding WindowLoadedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Window.Resources>
<converters:TestStateConverter x:Key="TestStateConverter" />
</Window.Resources>
+4
View File
@@ -22,7 +22,11 @@ namespace xunit.runner.wpf
{
public MainWindow()
{
Instance = this;
InitializeComponent();
}
public static Window Instance { get; private set; }
}
}
+46 -12
View File
@@ -22,6 +22,7 @@ namespace xunit.runner.wpf.ViewModel
private bool isBusy;
private bool isCancelRequested;
public MainViewModel()
{
if (IsInDesignMode)
@@ -36,6 +37,7 @@ namespace xunit.runner.wpf.ViewModel
allTestCases, TestCaseMatches, Tuple.Create(string.Empty, TestState.All), TestComparer.Instance);
this.TestCases.CollectionChanged += TestCases_CollectionChanged;
this.WindowLoadedCommand = new RelayCommand(OnExecuteWindowLoaded);
this.RunCommand = new RelayCommand(OnExecuteRun, CanExecuteRun);
this.CancelCommand = new RelayCommand(OnExecuteCancel, CanExecuteCancel);
}
@@ -50,6 +52,7 @@ namespace xunit.runner.wpf.ViewModel
}
public ICommand ExitCommand { get; } = new RelayCommand(OnExecuteExit);
public ICommand WindowLoadedCommand { get; }
public RelayCommand RunCommand { get; }
public RelayCommand CancelCommand { get; }
@@ -162,7 +165,7 @@ namespace xunit.runner.wpf.ViewModel
public ObservableCollection<TestAssemblyViewModel> Assemblies { get; } = new ObservableCollection<TestAssemblyViewModel>();
public FilteredCollectionView<TestCaseViewModel, Tuple<string, TestState>> TestCases { get; }
private void OnExecuteOpen(object sender, ExecutedRoutedEventArgs e)
private async void OnExecuteOpen(object sender, ExecutedRoutedEventArgs e)
{
var fileDialog = new OpenFileDialog
{
@@ -175,30 +178,48 @@ namespace xunit.runner.wpf.ViewModel
}
var fileName = fileDialog.FileName;
await AddAssemblies(new[] { fileName });
}
private async Task AddAssemblies(IEnumerable<string> fileNames)
{
var loadingDialog = new LoadingDialog { Owner = MainWindow.Instance };
try
{
using (AssemblyHelper.SubscribeResolve())
{
using (var xunit = new XunitFrontController(
useAppDomain: true,
assemblyFileName: fileName,
diagnosticMessageSink: new DiagnosticMessageVisitor(),
shadowCopy: false))
using (var testDiscoveryVisitor = new TestDiscoveryVisitor(xunit))
loadingDialog.Show();
foreach (var fileName in fileNames)
{
xunit.Find(includeSourceInformation: false, messageSink: testDiscoveryVisitor, discoveryOptions: TestFrameworkOptions.ForDiscovery());
testDiscoveryVisitor.Finished.WaitOne();
allTestCases.AddRange(testDiscoveryVisitor.TestCases);
loadingDialog.AssemblyFileName = fileName;
using (var xunit = new XunitFrontController(
useAppDomain: true,
assemblyFileName: fileName,
diagnosticMessageSink: new DiagnosticMessageVisitor(),
shadowCopy: false))
using (var testDiscoveryVisitor = new TestDiscoveryVisitor(xunit))
{
await Task.Run(() =>
{
xunit.Find(includeSourceInformation: false, messageSink: testDiscoveryVisitor, discoveryOptions: TestFrameworkOptions.ForDiscovery());
testDiscoveryVisitor.Finished.WaitOne();
});
allTestCases.AddRange(testDiscoveryVisitor.TestCases);
Assemblies.Add(new TestAssemblyViewModel(fileName));
}
}
}
Assemblies.Add(new TestAssemblyViewModel(fileName));
}
catch (Exception ex)
{
MessageBox.Show(Application.Current.MainWindow, ex.ToString());
}
finally
{
loadingDialog.Close();
}
}
private class DiagnosticMessageVisitor : TestMessageVisitor
@@ -307,6 +328,19 @@ namespace xunit.runner.wpf.ViewModel
Application.Current.Shutdown();
}
private async void OnExecuteWindowLoaded()
{
try
{
IsBusy = true;
await AddAssemblies(Environment.GetCommandLineArgs().Skip(1));
}
finally
{
IsBusy = false;
}
}
private bool CanExecuteRun()
=> !IsBusy && TestCases.Any();
+10
View File
@@ -89,11 +89,18 @@
<Compile Include="Converters\TestStateConverter.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="FilteredCollectionView.cs" />
<Compile Include="LoadingDialog.xaml.cs">
<DependentUpon>LoadingDialog.xaml</DependentUpon>
</Compile>
<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="LoadingDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -148,6 +155,9 @@
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.