Skip to content

Commit 938fef8

Browse files
authored
Merge pull request #4219 from rkapka/rkapka-master
Introducing Test Category
2 parents 60a13a9 + 376379b commit 938fef8

File tree

13 files changed

+322
-7
lines changed

13 files changed

+322
-7
lines changed

Rubberduck.Core/Rubberduck.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@
536536
<Compile Include="UnitTesting\IFakes.cs" />
537537
<Compile Include="UnitTesting\ReturnTypeConverter.cs" />
538538
<Compile Include="UnitTesting\PermissiveObjectComparer.cs" />
539+
<Compile Include="UnitTesting\TestCategory.cs" />
539540
<Compile Include="VersionCheck\IVersionCheck.cs" />
540541
<Compile Include="UI\Command\MenuItems\CommandBars\AppCommandBarBase.cs" />
541542
<Compile Include="UI\Command\MenuItems\CommandBars\ContextSelectionLabelMenuItem.cs" />

Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@
269269

270270
<CollectionViewSource x:Key="ResultsByOutcome" Source="{Binding Model.Tests}">
271271
<CollectionViewSource.SortDescriptions>
272-
<componentModel:SortDescription PropertyName="Result.Outcome" />
272+
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.QualifiedModuleName.Name" />
273273
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.MemberName" />
274274
</CollectionViewSource.SortDescriptions>
275275
<CollectionViewSource.GroupDescriptions>
@@ -278,6 +278,19 @@
278278

279279
</CollectionViewSource.GroupDescriptions>
280280
</CollectionViewSource>
281+
282+
<CollectionViewSource x:Key="ResultsByCategory" Source="{Binding Model.Tests}">
283+
<CollectionViewSource.SortDescriptions>
284+
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.QualifiedModuleName.Name" />
285+
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.MemberName" />
286+
</CollectionViewSource.SortDescriptions>
287+
<CollectionViewSource.GroupDescriptions>
288+
289+
<PropertyGroupDescription PropertyName="Category.Name" />
290+
291+
</CollectionViewSource.GroupDescriptions>
292+
</CollectionViewSource>
293+
281294
<SolidColorBrush x:Key="ToolBarToggleButtonVerticalBackground" Color="#FFEEF5FD"/>
282295
<SolidColorBrush x:Key="ToolBarButtonHover" Color="#210080FF"/>
283296
<SolidColorBrush x:Key="ToolBarGripper" Color="#FF6D6D6D"/>
@@ -504,6 +517,11 @@
504517
<Image Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/flask--arrow.png" />
505518
</MenuItem.Icon>
506519
</MenuItem>
520+
<MenuItem Command="{Binding RunSelectedCategoryTestsCommand}" Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer ,Key=TestExplorer_RunSelectedCategoryTests}" >
521+
<MenuItem.Icon>
522+
<Image Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/flask--arrow.png" />
523+
</MenuItem.Icon>
524+
</MenuItem>
507525
<MenuItem Command="{Binding RunInconclusiveTestsCommand}" Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_RunInconclusiveTests}" >
508526
<MenuItem.Icon>
509527
<Image Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/flask--exclamation.png" />
@@ -572,6 +590,15 @@
572590
Command="{Binding SetLocationGroupingCommand}"
573591
CommandParameter="{Binding ElementName=GroupByLocation, Path=IsChecked}"
574592
controls:MenuItemGroup.GroupName="TestExplorer_GroupingStyle" />
593+
<MenuItem x:Name="GroupByCategory"
594+
Style="{DynamicResource MenuItemStyle}"
595+
VerticalAlignment="Center"
596+
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingStyle_ByCategory}"
597+
IsChecked="{Binding GroupByCategory, UpdateSourceTrigger=PropertyChanged}"
598+
IsCheckable="True"
599+
Command="{Binding SetCategoryGroupingCommand}"
600+
CommandParameter="{Binding ElementName=GroupByCategory, Path=IsChecked}"
601+
controls:MenuItemGroup.GroupName="TestExplorer_GroupingStyle" />
575602
</MenuItem>
576603
</Menu>
577604

@@ -615,6 +642,7 @@
615642
</DataGridTemplateColumn>
616643
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}" />
617644
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.IdentifierName}" />
645+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_CategoryName}" Binding="{Binding Category.Name}" />
618646
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
619647
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
620648
</DataGrid.Columns>
@@ -633,6 +661,26 @@
633661
</DataGridTemplateColumn>
634662
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}" />
635663
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.QualifiedName.MemberName}" />
664+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_CategoryName}" Binding="{Binding Category.Name}" />
665+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
666+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
667+
</DataGrid.Columns>
668+
</controls:GroupingGrid>
669+
<controls:GroupingGrid ItemsSource="{Binding Source={StaticResource ResultsByCategory}}"
670+
SelectedItem="{Binding SelectedTest}"
671+
ShowGroupingItemCount="True"
672+
Visibility="{Binding IsChecked, ElementName=GroupByCategory, Converter={StaticResource BoolToVisibility}}">
673+
<DataGrid.Columns>
674+
<DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Outcome}">
675+
<DataGridTemplateColumn.CellTemplate>
676+
<DataTemplate DataType="unitTesting:TestMethod">
677+
<Image Source="{Binding Result.Outcome, Converter={StaticResource OutcomeIconConverter}}" Height="16" />
678+
</DataTemplate>
679+
</DataGridTemplateColumn.CellTemplate>
680+
</DataGridTemplateColumn>
681+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}" />
682+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.QualifiedName.MemberName}" />
683+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_CategoryName}" Binding="{Binding Category.Name}" />
636684
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
637685
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
638686
</DataGrid.Columns>

Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,43 @@ public TestExplorerViewModel(IVBE vbe,
6060
RunFailedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunFailedTestsCommand, CanExecuteRunFailedTestsCommand);
6161
RunPassedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunPassedTestsCommand, CanExecuteRunPassedTestsCommand);
6262
RunSelectedTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSelectedTestCommand, CanExecuteSelectedTestCommand);
63+
RunSelectedCategoryTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunSelectedCategoryTestsCommand, CanExecuteRunSelectedCategoryTestsCommand);
6364

6465
CopyResultsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteCopyResultsCommand);
6566

6667
OpenTestSettingsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), OpenSettings);
6768

6869
SetOutcomeGroupingCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), param =>
6970
{
70-
GroupByOutcome = (bool)param;
71-
GroupByLocation = !(bool)param;
71+
GroupByOutcome = true;
72+
73+
if ((bool)param)
74+
{
75+
GroupByLocation = false;
76+
GroupByCategory = false;
77+
}
7278
});
7379

7480
SetLocationGroupingCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), param =>
7581
{
76-
GroupByLocation = (bool)param;
77-
GroupByOutcome = !(bool)param;
82+
GroupByLocation = true;
83+
84+
if ((bool) param)
85+
{
86+
GroupByOutcome = false;
87+
GroupByCategory = false;
88+
}
89+
});
90+
91+
SetCategoryGroupingCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), param =>
92+
{
93+
GroupByCategory = true;
94+
95+
if ((bool)param)
96+
{
97+
GroupByOutcome = false;
98+
GroupByLocation = false;
99+
}
78100
});
79101
}
80102

@@ -162,10 +184,28 @@ public bool GroupByLocation
162184
}
163185
}
164186

187+
private bool _groupByCategory;
188+
public bool GroupByCategory
189+
{
190+
get => _groupByCategory;
191+
set
192+
{
193+
if (_groupByCategory == value)
194+
{
195+
return;
196+
}
197+
198+
_groupByCategory = value;
199+
OnPropertyChanged();
200+
}
201+
}
202+
165203
public CommandBase SetOutcomeGroupingCommand { get; }
166204

167205
public CommandBase SetLocationGroupingCommand { get; }
168206

207+
public CommandBase SetCategoryGroupingCommand { get; }
208+
169209
public long TotalDuration { get; private set; }
170210

171211
public RunAllTestsCommand RunAllTestsCommand { get; }
@@ -195,6 +235,8 @@ public bool GroupByLocation
195235

196236
public CommandBase RunSelectedTestCommand { get; }
197237

238+
public CommandBase RunSelectedCategoryTestsCommand { get; }
239+
198240
public CommandBase OpenTestSettingsCommand { get; }
199241

200242
private void OpenSettings(object param)
@@ -382,6 +424,33 @@ private void ExecuteCopyResultsCommand(object parameter)
382424
_clipboard.Flush();
383425
}
384426

427+
private void ExecuteRunSelectedCategoryTestsCommand(object obj)
428+
{
429+
EnsureRubberduckIsReferencedForEarlyBoundTests();
430+
431+
Model.ClearLastRun();
432+
433+
var stopwatch = new Stopwatch();
434+
Model.IsBusy = true;
435+
436+
stopwatch.Start();
437+
_testEngine.Run(Model.Tests.Where(test => test.Category.Equals(SelectedTest.Category)));
438+
stopwatch.Stop();
439+
440+
Model.IsBusy = false;
441+
TotalDuration = stopwatch.ElapsedMilliseconds;
442+
}
443+
444+
private bool CanExecuteRunSelectedCategoryTestsCommand(object obj)
445+
{
446+
if (Model.IsBusy || SelectedItem == null)
447+
{
448+
return false;
449+
}
450+
451+
return ((TestMethod) SelectedItem).Category.Name != string.Empty;
452+
}
453+
385454
//KEEP THIS, AS IT MAKES FOR THE BASIS OF A USEFUL *SUMMARY* REPORT
386455
//private void ExecuteCopyResultsCommand(object parameter)
387456
//{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
3+
namespace Rubberduck.UnitTesting
4+
{
5+
public class TestCategory
6+
{
7+
public string Name { get; }
8+
9+
public TestCategory(string name)
10+
{
11+
Name = name ?? throw new ArgumentNullException(nameof(name));
12+
}
13+
14+
public override bool Equals(object obj)
15+
{
16+
if (!(obj is TestCategory category))
17+
{
18+
return false;
19+
}
20+
21+
return Name == category.Name;
22+
}
23+
24+
public override int GetHashCode()
25+
{
26+
return Name.GetHashCode();
27+
}
28+
}
29+
}

Rubberduck.Core/UnitTesting/TestMethod.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Globalization;
55
using System.Linq;
66
using Rubberduck.Parsing;
7+
using Rubberduck.Parsing.Annotations;
78
using Rubberduck.Parsing.Symbols;
89
using Rubberduck.Parsing.VBA;
910
using Rubberduck.UI;
@@ -77,6 +78,17 @@ public TestResult Result
7778
set { _result = value; OnPropertyChanged(); }
7879
}
7980

81+
public TestCategory Category
82+
{
83+
get
84+
{
85+
var testMethodAnnotation = (TestMethodAnnotation) Declaration.Annotations
86+
.First(annotation => annotation.AnnotationType == AnnotationType.TestMethod);
87+
88+
return new TestCategory(testMethodAnnotation.Category);
89+
}
90+
}
91+
8092
private void HandleAssertCompleted(object sender, AssertCompletedEventArgs e)
8193
{
8294
_assertResults.Add(e);

Rubberduck.Parsing/Annotations/TestMethodAnnotation.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using Rubberduck.VBEditor;
1+
using System;
2+
using Rubberduck.VBEditor;
23
using System.Collections.Generic;
4+
using System.Linq;
35

46
namespace Rubberduck.Parsing.Annotations
57
{
@@ -13,6 +15,16 @@ public TestMethodAnnotation(
1315
IEnumerable<string> parameters)
1416
: base(AnnotationType.TestMethod, qualifiedSelection)
1517
{
18+
var firstParameter = parameters.FirstOrDefault();
19+
if ((firstParameter?.StartsWith("\"") ?? false) && firstParameter.EndsWith("\""))
20+
{
21+
// Strip surrounding double quotes
22+
firstParameter = firstParameter.Substring(1, firstParameter.Length - 2);
23+
}
24+
25+
Category = string.IsNullOrWhiteSpace(firstParameter) ? string.Empty : firstParameter;
1626
}
27+
28+
public string Category { get; }
1729
}
1830
}

Rubberduck.Resources/RubberduckUI.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/RubberduckUI.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,4 +1291,7 @@ NOTE: Restart is required for the setting to take effect.</value>
12911291
<data name="Settings" xml:space="preserve">
12921292
<value>Settings</value>
12931293
</data>
1294+
<data name="GroupingStyle_ByCategory" xml:space="preserve">
1295+
<value>By category</value>
1296+
</data>
12941297
</root>

Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/UnitTesting/TestExplorer.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,10 @@
228228
<data name="Command_AddTestModule_Error" xml:space="preserve">
229229
<value>Unable to create test module. The host application may not allow for creation of new modules or the project may be locked. For details, check the log.</value>
230230
</data>
231+
<data name="TestExplorer_RunSelectedCategoryTests" xml:space="preserve">
232+
<value>Selected Category</value>
233+
</data>
234+
<data name="TestExplorer_CategoryName" xml:space="preserve">
235+
<value>Category Name</value>
236+
</data>
231237
</root>

0 commit comments

Comments
 (0)