Skip to content

Commit 6e77f5a

Browse files
committed
implemented groupings in test explorer
1 parent 43ca37b commit 6e77f5a

File tree

9 files changed

+157
-71
lines changed

9 files changed

+157
-71
lines changed

RetailCoder.VBE/Rubberduck.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,8 +849,9 @@
849849
<Compile Include="UnitTesting\TestEngine.cs" />
850850
<Compile Include="UnitTesting\TestMethod.cs" />
851851
<Compile Include="UnitTesting\TestOutcome.cs" />
852-
<Compile Include="UnitTesting\TestOutcomeImageSourceConverter.cs" />
852+
<Compile Include="UI\UnitTesting\TestOutcomeImageSourceConverter.cs" />
853853
<Compile Include="UnitTesting\TestResult.cs" />
854+
<Compile Include="UI\UnitTesting\TestResultToOutcomeTextConverter.cs" />
854855
<Compile Include="UnitTesting\TestRunner.cs" />
855856
<Compile Include="UI\SourceControl\IUnSyncedCommitsView.cs" />
856857
<Compile Include="UI\SourceControl\UnSyncedCommitsControl.cs">

RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -347,20 +347,20 @@
347347
</MenuItem>
348348
</Menu>
349349

350-
<Menu>
351-
<MenuItem Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingGrid_GroupingStyle}">
352-
<MenuItem.Icon>
353-
<Image Height="16" Source="../../Resources/Microsoft/PNG/GroupBy_284_32.png" />
354-
</MenuItem.Icon>
350+
<Menu>
351+
<MenuItem Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingGrid_GroupingStyle}">
352+
<MenuItem.Icon>
353+
<Image Height="16" Source="../../Resources/Microsoft/PNG/GroupBy_284_32.png" />
354+
</MenuItem.Icon>
355355

356-
<MenuItem x:Name="GroupByInspectionType" Style="{DynamicResource MenuItemStyle}" VerticalAlignment="Center"
357-
Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingStyle_ByInspectionType}" IsChecked="True"
358-
IsCheckable="True" controls:MenuItemGroup.GroupName="GroupingStyle" />
359-
<MenuItem x:Name="GroupByModule" Style="{DynamicResource MenuItemStyle}" VerticalAlignment="Center"
360-
Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingStyle_ByLocation}"
361-
IsCheckable="True" controls:MenuItemGroup.GroupName="GroupingStyle" />
362-
</MenuItem>
363-
</Menu>
356+
<MenuItem x:Name="GroupByInspectionType" Style="{DynamicResource MenuItemStyle}" VerticalAlignment="Center"
357+
Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingStyle_ByInspectionType}" IsChecked="True"
358+
IsCheckable="True" controls:MenuItemGroup.GroupName="GroupingStyle" />
359+
<MenuItem x:Name="GroupByModule" Style="{DynamicResource MenuItemStyle}" VerticalAlignment="Center"
360+
Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingStyle_ByLocation}"
361+
IsCheckable="True" controls:MenuItemGroup.GroupName="GroupingStyle" />
362+
</MenuItem>
363+
</Menu>
364364

365365
<Separator />
366366

RetailCoder.VBE/UI/UnitTesting/TestExplorerControl.xaml

Lines changed: 76 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,35 @@
66
xmlns:local="clr-namespace:Rubberduck.UI.UnitTesting"
77
xmlns:unitTesting="clr-namespace:Rubberduck.UnitTesting"
88
xmlns:controls="clr-namespace:Rubberduck.UI.Controls"
9+
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
910
Language="{UICulture}"
1011
mc:Ignorable="d"
1112
d:DesignHeight="255" d:DesignWidth="455"
1213
d:DataContext="{d:DesignInstance local:TestExplorerViewModel}">
1314

1415
<UserControl.Resources>
15-
<unitTesting:TestOutcomeImageSourceConverter x:Key="OutcomeIconConverter" />
16+
<local:TestOutcomeImageSourceConverter x:Key="OutcomeIconConverter" />
17+
<local:TestResultToOutcomeTextConverter x:Key="OutcomeTextConverter" />
1618
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/>
19+
20+
<CollectionViewSource x:Key="ResultsByModule" Source="{Binding Model.Tests}">
21+
<CollectionViewSource.SortDescriptions>
22+
<componentModel:SortDescription PropertyName="QualifiedMemberName.QualifiedModuleName.Name" />
23+
</CollectionViewSource.SortDescriptions>
24+
<CollectionViewSource.GroupDescriptions>
25+
<PropertyGroupDescription PropertyName="QualifiedMemberName.QualifiedModuleName.Name" />
26+
</CollectionViewSource.GroupDescriptions>
27+
</CollectionViewSource>
28+
29+
<CollectionViewSource x:Key="ResultsByOutcome" Source="{Binding Model.Tests}">
30+
<CollectionViewSource.SortDescriptions>
31+
<componentModel:SortDescription PropertyName="Result.Outcome" />
32+
</CollectionViewSource.SortDescriptions>
33+
<CollectionViewSource.GroupDescriptions>
34+
<PropertyGroupDescription PropertyName="Result" Converter="{StaticResource OutcomeTextConverter}" />
35+
</CollectionViewSource.GroupDescriptions>
36+
</CollectionViewSource>
37+
1738
</UserControl.Resources>
1839

1940
<Grid>
@@ -87,6 +108,21 @@
87108
</Menu>
88109
<Separator />
89110

111+
<Menu>
112+
<MenuItem Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingGrid_GroupingStyle}">
113+
<MenuItem.Icon>
114+
<Image Height="16" Source="../../Resources/Microsoft/PNG/GroupBy_284_32.png" />
115+
</MenuItem.Icon>
116+
117+
<MenuItem x:Name="GroupByOutcome" Style="{DynamicResource MenuItemStyle}" VerticalAlignment="Center"
118+
Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingStyle_ByOutcome}" IsChecked="True"
119+
IsCheckable="True" controls:MenuItemGroup.GroupName="GroupingStyle" />
120+
<MenuItem x:Name="GroupByModule" Style="{DynamicResource MenuItemStyle}" VerticalAlignment="Center"
121+
Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=GroupingStyle_ByLocation}"
122+
IsCheckable="True" controls:MenuItemGroup.GroupName="GroupingStyle" />
123+
</MenuItem>
124+
</Menu>
125+
90126
<Button Command="{Binding CopyResultsCommand}">
91127
<Image Height="16" Source="../../Resources/document-copy.png" />
92128
</Button>
@@ -112,23 +148,45 @@
112148

113149
<Border Grid.Row="2" Padding="2">
114150
<ScrollViewer VerticalScrollBarVisibility="Visible">
115-
<controls:GroupingGrid ItemsSource="{Binding Model.TestMethods}"
116-
SelectedItem="{Binding SelectedTest}"
117-
ShowGroupingItemCount="True">
118-
<DataGrid.Columns>
119-
<DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=Outcome}">
120-
<DataGridTemplateColumn.CellTemplate>
121-
<DataTemplate DataType="unitTesting:TestMethod">
122-
<Image Source="{Binding Result.Outcome, Converter={StaticResource OutcomeIconConverter}}" Height="16" />
123-
</DataTemplate>
124-
</DataGridTemplateColumn.CellTemplate>
125-
</DataGridTemplateColumn>
126-
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding QualifiedMemberName.QualifiedModuleName}" />
127-
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_MethodName}" Binding="{Binding QualifiedMemberName.MemberName}" />
128-
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
129-
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
130-
</DataGrid.Columns>
131-
</controls:GroupingGrid>
151+
<Grid>
152+
<controls:GroupingGrid ItemsSource="{Binding Source={StaticResource ResultsByOutcome}}"
153+
SelectedItem="{Binding SelectedTest}"
154+
ShowGroupingItemCount="True"
155+
Visibility="{Binding IsChecked, ElementName=GroupByOutcome, Converter={StaticResource BoolToVisibility}}">
156+
<DataGrid.Columns>
157+
<DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=Outcome}">
158+
<DataGridTemplateColumn.CellTemplate>
159+
<DataTemplate DataType="unitTesting:TestMethod">
160+
<Image Source="{Binding Result.Outcome, Converter={StaticResource OutcomeIconConverter}}" Height="16" />
161+
</DataTemplate>
162+
</DataGridTemplateColumn.CellTemplate>
163+
</DataGridTemplateColumn>
164+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding QualifiedMemberName.QualifiedModuleName}" />
165+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_MethodName}" Binding="{Binding QualifiedMemberName.MemberName}" />
166+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
167+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
168+
</DataGrid.Columns>
169+
</controls:GroupingGrid>
170+
171+
<controls:GroupingGrid ItemsSource="{Binding Source={StaticResource ResultsByModule}}"
172+
SelectedItem="{Binding SelectedTest}"
173+
ShowGroupingItemCount="True"
174+
Visibility="{Binding IsChecked, ElementName=GroupByModule, Converter={StaticResource BoolToVisibility}}">
175+
<DataGrid.Columns>
176+
<DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=Outcome}">
177+
<DataGridTemplateColumn.CellTemplate>
178+
<DataTemplate DataType="unitTesting:TestMethod">
179+
<Image Source="{Binding Result.Outcome, Converter={StaticResource OutcomeIconConverter}}" Height="16" />
180+
</DataTemplate>
181+
</DataGridTemplateColumn.CellTemplate>
182+
</DataGridTemplateColumn>
183+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding QualifiedMemberName.QualifiedModuleName}" />
184+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_MethodName}" Binding="{Binding QualifiedMemberName.MemberName}" />
185+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
186+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
187+
</DataGrid.Columns>
188+
</controls:GroupingGrid>
189+
</Grid>
132190
</ScrollViewer>
133191
</Border>
134192
<controls:BusyIndicator Grid.Row="2" Width="36" Height="36" Visibility="{Binding Model.IsBusy, Converter={StaticResource BoolToVisibility}}" />

RetailCoder.VBE/UI/UnitTesting/TestExplorerControl.xaml.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Windows.Controls;
1+
using System;
2+
using System.Windows.Controls;
3+
using System.Windows.Data;
24

35
namespace Rubberduck.UI.UnitTesting
46
{
@@ -10,6 +12,37 @@ public partial class TestExplorerControl : UserControl
1012
public TestExplorerControl()
1113
{
1214
InitializeComponent();
15+
DataContextChanged += TestExplorerControl_DataContextChanged;
16+
}
17+
18+
void TestExplorerControl_DataContextChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
19+
{
20+
var oldContext = e.OldValue as TestExplorerViewModel;
21+
if (oldContext != null)
22+
{
23+
oldContext.TestCompleted -= OnTestCompleted;
24+
}
25+
26+
var context = e.NewValue as TestExplorerViewModel;
27+
if (context != null)
28+
{
29+
context.TestCompleted += OnTestCompleted;
30+
}
31+
}
32+
33+
private void OnTestCompleted(object sender, EventArgs eventArgs)
34+
{
35+
try
36+
{
37+
var resource = FindResource("ResultsByOutcome") as CollectionViewSource;
38+
if (resource != null)
39+
{
40+
resource.View.Refresh();
41+
}
42+
}
43+
catch (Exception)
44+
{
45+
}
1346
}
1447
}
1548
}

RetailCoder.VBE/UI/UnitTesting/TestExplorerModelBase.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System.Collections.Generic;
22
using System.Collections.ObjectModel;
33
using System.Linq;
4-
using System.Windows.Data;
54
using System.Windows.Media;
65
using Rubberduck.Parsing.Reflection;
76
using Rubberduck.UnitTesting;
@@ -10,23 +9,11 @@ namespace Rubberduck.UI.UnitTesting
109
{
1110
public abstract class TestExplorerModelBase : ViewModelBase
1211
{
13-
protected TestExplorerModelBase()
14-
{
15-
_testMethods = new ListCollectionView(_tests);
16-
if (_testMethods.GroupDescriptions != null)
17-
{
18-
_testMethods.GroupDescriptions.Add(new PropertyGroupDescription("Result", new TestResultToOutcomeTextConverter()));
19-
}
20-
}
21-
2212
public abstract void Refresh();
2313

2414
private readonly ObservableCollection<TestMethod> _tests = new ObservableCollection<TestMethod>();
2515
public ObservableCollection<TestMethod> Tests { get { return _tests; } }
2616

27-
private readonly ListCollectionView _testMethods;
28-
public ListCollectionView TestMethods { get { return _testMethods;} }
29-
3017
private static readonly string[] ReservedTestAttributeNames =
3118
{
3219
"ModuleInitialize",
@@ -41,21 +28,19 @@ protected TestExplorerModelBase()
4128
public void ClearLastRun()
4229
{
4330
_lastRun.Clear();
44-
_testMethods.Refresh();
4531
}
4632

4733
public void AddExecutedTest(TestMethod test)
4834
{
4935
_lastRun.Add(test);
50-
_testMethods.Refresh();
51-
5236
ExecutedCount = _tests.Count(t => t.Result.Outcome != TestOutcome.Unknown);
5337

5438
ProgressBarColor = _tests.Any(t => t.Result.Outcome == TestOutcome.Failed)
5539
? Colors.Red
5640
: _tests.Any(t => t.Result.Outcome == TestOutcome.Inconclusive)
5741
? Colors.Gold
5842
: Colors.LimeGreen;
43+
5944
}
6045

6146
private int _executedCount;

RetailCoder.VBE/UnitTesting/TestOutcomeImageSourceConverter.cs renamed to RetailCoder.VBE/UI/UnitTesting/TestOutcomeImageSourceConverter.cs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,10 @@
66
using System.Windows.Data;
77
using System.Windows.Media;
88
using System.Windows.Media.Imaging;
9-
using Rubberduck.UI;
9+
using Rubberduck.UnitTesting;
1010

11-
namespace Rubberduck.UnitTesting
11+
namespace Rubberduck.UI.UnitTesting
1212
{
13-
public class TestResultToOutcomeTextConverter : IValueConverter
14-
{
15-
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
16-
{
17-
var result = value as TestResult;
18-
if (result != null)
19-
{
20-
return RubberduckUI.ResourceManager.GetString("TestOutcome_" + result.Outcome);
21-
}
22-
23-
throw new ArgumentException("value is not a TestResult object.", "value");
24-
}
25-
26-
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
27-
{
28-
throw new NotImplementedException();
29-
}
30-
}
31-
3213
public class TestOutcomeImageSourceConverter : IValueConverter
3314
{
3415
private static readonly IDictionary<TestOutcome,ImageSource> Icons =
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows.Data;
4+
using Rubberduck.UnitTesting;
5+
6+
namespace Rubberduck.UI.UnitTesting
7+
{
8+
public class TestResultToOutcomeTextConverter : IValueConverter
9+
{
10+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11+
{
12+
var result = value as TestResult;
13+
if (result != null)
14+
{
15+
return RubberduckUI.ResourceManager.GetString("TestOutcome_" + result.Outcome);
16+
}
17+
18+
throw new ArgumentException("value is not a TestResult object.", "value");
19+
}
20+
21+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
22+
{
23+
throw new NotImplementedException();
24+
}
25+
}
26+
}

RetailCoder.VBE/UnitTesting/TestMethod.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public void Run()
5454
public TestResult Result
5555
{
5656
get { return _result; }
57-
set { _result = value; OnPropertyChanged();}
57+
set { _result = value; OnPropertyChanged(); }
5858
}
5959

6060
void HandleAssertCompleted(object sender, AssertCompletedEventArgs e)

Rubberduck.VBEEditor/QualifiedModuleName.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ public QualifiedMemberName QualifyMemberName(string member)
7777
private readonly string _componentName;
7878
public string ComponentName { get { return _componentName; } }
7979

80+
public string Name { get { return ToString(); } }
81+
8082
public override string ToString()
8183
{
8284
return _component == null && string.IsNullOrEmpty(_projectName) ? string.Empty : _projectName + "." + _componentName;

0 commit comments

Comments
 (0)