Skip to content

Commit 227aae9

Browse files
committed
Elm test - expand CLI to offer listing tests
1 parent 82e2ad0 commit 227aae9

5 files changed

Lines changed: 453 additions & 13 deletions

File tree

implement/Pine.Core.Tests/Elm/ElmTest/ElmTestTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,34 @@ public void No_Elm_test_modules_is_a_test_run_result()
3636
}
3737

3838

39+
[Fact]
40+
public void Listed_test_and_listing_equality_is_structural()
41+
{
42+
var first =
43+
new ListedTest(
44+
"tests/Tests.elm",
45+
["Root", "Group"],
46+
"test name");
47+
48+
var second =
49+
new ListedTest(
50+
new string("tests/Tests.elm".ToCharArray()),
51+
[new string("Root".ToCharArray()), new string("Group".ToCharArray())],
52+
new string("test name".ToCharArray()));
53+
54+
first.Equals(second).Should().BeTrue();
55+
(first == second).Should().BeTrue();
56+
first.GetHashCode().Should().Be(second.GetHashCode());
57+
58+
var firstListing = new ElmTestRun.Listed([first]);
59+
var secondListing = new ElmTestRun.Listed([second]);
60+
61+
firstListing.Equals(secondListing).Should().BeTrue();
62+
(firstListing == secondListing).Should().BeTrue();
63+
firstListing.GetHashCode().Should().Be(secondListing.GetHashCode());
64+
}
65+
66+
3967
[Fact]
4068
public void Verify_elm_test_results_for_scenarios_from_files()
4169
{

implement/Pine.Core/Elm/Testing/ElmTestRunner.cs

Lines changed: 130 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ public static class ElmTestRunner
2828
public static ElmTestRun CompileAndRunTests(
2929
string appDirectory,
3030
IPineVM? pineVm = null,
31-
string? filter = null)
31+
string? filter = null,
32+
bool listTests = false)
3233
{
3334
appDirectory = Path.GetFullPath(appDirectory);
3435

@@ -76,6 +77,7 @@ file.path[0] is "tests" &&
7677

7778
return
7879
(file.path,
80+
filePathText: string.Join('/', file.path),
7981
moduleName: moduleHeader.ModuleName,
8082
moduleNameText: string.Join('.', moduleHeader.ModuleName));
8183
})
@@ -121,15 +123,37 @@ file.path[0] is "tests" &&
121123
"Did not find declaration '" + testModule.moduleNameText + ".suite'");
122124
}
123125

124-
DiscoverTests(suiteValue, path: [], discoveredTests);
126+
DiscoverTests(
127+
suiteValue,
128+
filePath: testModule.filePathText,
129+
descriptionPath: [],
130+
discoveredTests);
125131
}
126132

127133
if (filter is { } filterText)
128134
{
129135
discoveredTests.RemoveAll(
130136
test =>
137+
!test.FilePath.Contains(filterText, StringComparison.OrdinalIgnoreCase) &&
131138
!test.Path.Any(
132-
name => name.Contains(filterText, StringComparison.OrdinalIgnoreCase)));
139+
pathItem =>
140+
pathItem.Contains(filterText, StringComparison.OrdinalIgnoreCase)));
141+
}
142+
143+
if (listTests)
144+
{
145+
return
146+
new ElmTestRun.Listed(
147+
[
148+
.. discoveredTests
149+
.Where(test => test.Kind is not DiscoveredTestKind.EmptyGroup)
150+
.Select(
151+
test =>
152+
new ListedTest(
153+
test.FilePath,
154+
[.. test.Path.SkipLast(1)],
155+
test.Path[^1]))
156+
]);
133157
}
134158

135159
var parseCache = new PineVMParseCache();
@@ -425,7 +449,8 @@ private static IntermediatePineVM CreatePineVm() =>
425449

426450
private static void DiscoverTests(
427451
PineValue testValue,
428-
IReadOnlyList<string> path,
452+
string filePath,
453+
IReadOnlyList<string> descriptionPath,
429454
List<DiscoveredTest> discoveredTests)
430455
{
431456
var (tag, arguments) = ParseTaggedValue(testValue);
@@ -436,7 +461,7 @@ private static void DiscoverTests(
436461
throw new InvalidOperationException("Describe must contain two arguments");
437462

438463
var groupName = ParseElmString(arguments.Span[0]);
439-
var groupPath = path.Append(groupName).ToImmutableArray();
464+
var groupPath = descriptionPath.Append(groupName).ToImmutableArray();
440465

441466
if (arguments.Span[1] is not PineValue.ListValue children)
442467
throw new InvalidOperationException("Describe children must be a list");
@@ -445,6 +470,7 @@ private static void DiscoverTests(
445470
{
446471
discoveredTests.Add(
447472
new DiscoveredTest(
473+
filePath,
448474
groupPath,
449475
DiscoveredTestKind.EmptyGroup,
450476
Thunk: null));
@@ -453,7 +479,7 @@ private static void DiscoverTests(
453479
}
454480

455481
foreach (var child in children.Items.Span)
456-
DiscoverTests(child, groupPath, discoveredTests);
482+
DiscoverTests(child, filePath, groupPath, discoveredTests);
457483

458484
return;
459485
}
@@ -465,7 +491,8 @@ private static void DiscoverTests(
465491

466492
discoveredTests.Add(
467493
new DiscoveredTest(
468-
[.. path, ParseElmString(arguments.Span[0])],
494+
filePath,
495+
[.. descriptionPath, ParseElmString(arguments.Span[0])],
469496
DiscoveredTestKind.Runnable,
470497
arguments.Span[1]));
471498

@@ -479,7 +506,8 @@ private static void DiscoverTests(
479506

480507
discoveredTests.Add(
481508
new DiscoveredTest(
482-
[.. path, ParseElmString(arguments.Span[0])],
509+
filePath,
510+
[.. descriptionPath, ParseElmString(arguments.Span[0])],
483511
DiscoveredTestKind.Todo,
484512
Thunk: null));
485513

@@ -522,6 +550,7 @@ private enum DiscoveredTestKind
522550

523551

524552
private sealed record DiscoveredTest(
553+
string FilePath,
525554
IReadOnlyList<string> Path,
526555
DiscoveredTestKind Kind,
527556
PineValue? Thunk);
@@ -1020,6 +1049,64 @@ public void Deconstruct(
10201049
}
10211050

10221051

1052+
/// <summary>
1053+
/// Describes a discovered Elm test.
1054+
/// </summary>
1055+
public sealed record ListedTest
1056+
{
1057+
/// <summary>
1058+
/// Creates a description of a discovered Elm test.
1059+
/// </summary>
1060+
public ListedTest(
1061+
string filePath,
1062+
IReadOnlyList<string> descriptionPath,
1063+
string name)
1064+
{
1065+
FilePath = filePath;
1066+
DescriptionPath = descriptionPath;
1067+
Name = name;
1068+
}
1069+
1070+
/// <summary>
1071+
/// Gets the test module's path relative to the Elm project.
1072+
/// </summary>
1073+
public string FilePath { get; init; }
1074+
1075+
/// <summary>
1076+
/// Gets the path of nested descriptions containing the test.
1077+
/// </summary>
1078+
public IReadOnlyList<string> DescriptionPath { get; init; }
1079+
1080+
/// <summary>
1081+
/// Gets the test name.
1082+
/// </summary>
1083+
public string Name { get; init; }
1084+
1085+
/// <inheritdoc/>
1086+
public bool Equals(ListedTest? other) =>
1087+
ReferenceEquals(this, other) ||
1088+
(other is not null &&
1089+
FilePath == other.FilePath &&
1090+
DescriptionPath.SequenceEqual(other.DescriptionPath, StringComparer.Ordinal) &&
1091+
Name == other.Name);
1092+
1093+
/// <inheritdoc/>
1094+
public override int GetHashCode()
1095+
{
1096+
var hashCode = new HashCode();
1097+
1098+
hashCode.Add(FilePath, StringComparer.Ordinal);
1099+
1100+
foreach (var description in DescriptionPath)
1101+
hashCode.Add(description, StringComparer.Ordinal);
1102+
1103+
hashCode.Add(Name, StringComparer.Ordinal);
1104+
1105+
return hashCode.ToHashCode();
1106+
}
1107+
}
1108+
1109+
10231110
/// <summary>
10241111
/// Contains a styled fragment of rendered test output.
10251112
/// </summary>
@@ -1102,6 +1189,41 @@ public sealed record Completed(
11021189
TimeSpan Duration)
11031190
: ElmTestRun;
11041191

1192+
/// <summary>
1193+
/// Contains tests discovered without running them.
1194+
/// </summary>
1195+
public sealed record Listed : ElmTestRun
1196+
{
1197+
/// <summary>
1198+
/// Creates a result containing tests discovered without running them.
1199+
/// </summary>
1200+
public Listed(IReadOnlyList<ListedTest> tests)
1201+
{
1202+
Tests = tests;
1203+
}
1204+
1205+
/// <summary>
1206+
/// Gets the discovered tests.
1207+
/// </summary>
1208+
public IReadOnlyList<ListedTest> Tests { get; init; }
1209+
1210+
/// <inheritdoc/>
1211+
public bool Equals(Listed? other) =>
1212+
ReferenceEquals(this, other) ||
1213+
(other is not null && Tests.SequenceEqual(other.Tests));
1214+
1215+
/// <inheritdoc/>
1216+
public override int GetHashCode()
1217+
{
1218+
var hashCode = new HashCode();
1219+
1220+
foreach (var test in Tests)
1221+
hashCode.Add(test);
1222+
1223+
return hashCode.ToHashCode();
1224+
}
1225+
}
1226+
11051227
/// <summary>
11061228
/// Represents a test run for a project without Elm test modules.
11071229
/// </summary>

0 commit comments

Comments
 (0)