Skip to content

Commit 6c748e3

Browse files
committed
Showcase demo
1 parent b588c39 commit 6c748e3

23 files changed

+3071
-2
lines changed

SharpAssert.sln

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpAssert.PowerAssertTest
1212
EndProject
1313
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpAssert.IntegrationTests", "src\SharpAssert.IntegrationTests\SharpAssert.IntegrationTests.csproj", "{64391C1B-BDA7-4E82-9059-41AE07792FE4}"
1414
EndProject
15+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
16+
EndProject
17+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpAssert.Demo", "src\SharpAssert.Demo\SharpAssert.Demo.csproj", "{37E60194-2FE9-408E-B23E-CDB5199ABE36}"
18+
EndProject
1519
Global
1620
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1721
Debug|Any CPU = Debug|Any CPU
@@ -58,6 +62,7 @@ Global
5862
{C9949AD0-684A-415A-A4FB-626EF50E2242}.Release|x64.Build.0 = Release|Any CPU
5963
{C9949AD0-684A-415A-A4FB-626EF50E2242}.Release|x86.ActiveCfg = Release|Any CPU
6064
{C9949AD0-684A-415A-A4FB-626EF50E2242}.Release|x86.Build.0 = Release|Any CPU
65+
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
6166
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Debug|x64.ActiveCfg = Debug|Any CPU
6267
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Debug|x64.Build.0 = Debug|Any CPU
6368
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -67,7 +72,7 @@ Global
6772
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Release|x64.Build.0 = Release|Any CPU
6873
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Release|x86.ActiveCfg = Release|Any CPU
6974
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Release|x86.Build.0 = Release|Any CPU
70-
{B2178774-FB4B-4997-BEFC-A426FDC2BD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
75+
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7176
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Debug|x64.ActiveCfg = Debug|Any CPU
7277
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Debug|x64.Build.0 = Debug|Any CPU
7378
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -77,7 +82,6 @@ Global
7782
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Release|x64.Build.0 = Release|Any CPU
7883
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Release|x86.ActiveCfg = Release|Any CPU
7984
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Release|x86.Build.0 = Release|Any CPU
80-
{D6D87294-D61C-47CF-9FA6-8F1619140466}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
8185
{64391C1B-BDA7-4E82-9059-41AE07792FE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
8286
{64391C1B-BDA7-4E82-9059-41AE07792FE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
8387
{64391C1B-BDA7-4E82-9059-41AE07792FE4}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -90,8 +94,23 @@ Global
9094
{64391C1B-BDA7-4E82-9059-41AE07792FE4}.Release|x64.Build.0 = Release|Any CPU
9195
{64391C1B-BDA7-4E82-9059-41AE07792FE4}.Release|x86.ActiveCfg = Release|Any CPU
9296
{64391C1B-BDA7-4E82-9059-41AE07792FE4}.Release|x86.Build.0 = Release|Any CPU
97+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
98+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Debug|Any CPU.Build.0 = Debug|Any CPU
99+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Debug|x64.ActiveCfg = Debug|Any CPU
100+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Debug|x64.Build.0 = Debug|Any CPU
101+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Debug|x86.ActiveCfg = Debug|Any CPU
102+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Debug|x86.Build.0 = Debug|Any CPU
103+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Release|Any CPU.ActiveCfg = Release|Any CPU
104+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Release|Any CPU.Build.0 = Release|Any CPU
105+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Release|x64.ActiveCfg = Release|Any CPU
106+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Release|x64.Build.0 = Release|Any CPU
107+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Release|x86.ActiveCfg = Release|Any CPU
108+
{37E60194-2FE9-408E-B23E-CDB5199ABE36}.Release|x86.Build.0 = Release|Any CPU
93109
EndGlobalSection
94110
GlobalSection(SolutionProperties) = preSolution
95111
HideSolutionNode = FALSE
96112
EndGlobalSection
113+
GlobalSection(NestedProjects) = preSolution
114+
{37E60194-2FE9-408E-B23E-CDB5199ABE36} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
115+
EndGlobalSection
97116
EndGlobal
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace SharpAssert.Demo;
2+
3+
sealed class DemoCategory(
4+
string number,
5+
string name,
6+
string description,
7+
IEnumerable<DemoDefinition> demos)
8+
{
9+
public string Number { get; } = number;
10+
public string Name { get; } = name;
11+
public string Description { get; } = description;
12+
public IReadOnlyList<DemoDefinition> Demos { get; } = demos.ToList();
13+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
namespace SharpAssert.Demo;
2+
3+
sealed class DemoDefinition(
4+
string name,
5+
string description,
6+
string category,
7+
Delegate demoMethod)
8+
{
9+
public string Name { get; } = name;
10+
public string Description { get; } = description;
11+
public string Category { get; } = category;
12+
public Delegate DemoMethod { get; } = demoMethod;
13+
public bool IsAsync { get; } = demoMethod is Func<Task>;
14+
15+
public string ExtractCode()
16+
{
17+
return SourceCodeExtractor.ExtractMethodSource(DemoMethod);
18+
}
19+
20+
public async Task<DemoResult> ExecuteAsync()
21+
{
22+
try
23+
{
24+
if (DemoMethod is Action action)
25+
{
26+
action();
27+
}
28+
else if (DemoMethod is Func<Task> asyncAction)
29+
{
30+
await asyncAction();
31+
}
32+
else
33+
{
34+
return DemoResult.Error($"Unsupported delegate type: {DemoMethod.GetType()}");
35+
}
36+
37+
return DemoResult.Error("Demo should have thrown SharpAssertionException but didn't");
38+
}
39+
catch (SharpAssertionException ex)
40+
{
41+
return DemoResult.Success(ex.Message);
42+
}
43+
catch (Exception ex)
44+
{
45+
return DemoResult.Error($"Unexpected exception: {ex.GetType().Name}\n{ex.Message}");
46+
}
47+
}
48+
}
49+
50+
sealed class DemoResult
51+
{
52+
public bool IsSuccess { get; }
53+
public string Output { get; }
54+
55+
DemoResult(bool isSuccess, string output)
56+
{
57+
IsSuccess = isSuccess;
58+
Output = output;
59+
}
60+
61+
public static DemoResult Success(string output) => new(true, output);
62+
public static DemoResult Error(string message) => new(false, message);
63+
}

src/SharpAssert.Demo/DemoRunner.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using SharpAssert.Demo.Rendering;
2+
3+
namespace SharpAssert.Demo;
4+
5+
sealed class DemoRunner(IDemoRenderer renderer)
6+
{
7+
public async Task RunAllAsync(string title, IEnumerable<DemoCategory> categories)
8+
{
9+
renderer.RenderHeader(title);
10+
11+
var categoryList = categories.ToList();
12+
var totalDemos = 0;
13+
14+
foreach (var category in categoryList)
15+
{
16+
renderer.RenderCategory(category);
17+
18+
foreach (var demo in category.Demos)
19+
{
20+
var result = await demo.ExecuteAsync();
21+
renderer.RenderDemo(demo, result);
22+
23+
totalDemos++;
24+
}
25+
}
26+
27+
renderer.RenderFooter(categoryList.Count, totalDemos);
28+
renderer.Complete();
29+
SaveRendererIfPossible();
30+
}
31+
32+
void SaveRendererIfPossible()
33+
{
34+
if (renderer is ISaveableRenderer saveable)
35+
saveable.Save();
36+
}
37+
38+
public async Task RunCategoryAsync(string categoryName, IEnumerable<DemoCategory> categories)
39+
{
40+
var category = FindCategoryByName(categories, categoryName);
41+
if (category == null)
42+
{
43+
Console.WriteLine($"Category '{categoryName}' not found.");
44+
return;
45+
}
46+
47+
renderer.RenderHeader($"SharpAssert Demo - {category.Name}");
48+
renderer.RenderCategory(category);
49+
50+
foreach (var demo in category.Demos)
51+
{
52+
var result = await demo.ExecuteAsync();
53+
renderer.RenderDemo(demo, result);
54+
}
55+
56+
renderer.RenderFooter(1, category.Demos.Count);
57+
renderer.Complete();
58+
}
59+
60+
static DemoCategory? FindCategoryByName(IEnumerable<DemoCategory> categories, string name)
61+
{
62+
return categories.FirstOrDefault(c =>
63+
c.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
64+
}
65+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using static SharpAssert.Sharp;
2+
3+
namespace SharpAssert.Demo.Demos;
4+
5+
public static class BasicAssertionsDemos
6+
{
7+
/// <summary>
8+
/// Demonstrates a simple assertion failure showing the expression text.
9+
/// </summary>
10+
public static void SimpleFailure()
11+
{
12+
Assert(false);
13+
}
14+
15+
/// <summary>
16+
/// Demonstrates assertion failure with expression showing operands and result.
17+
/// </summary>
18+
public static void ExpressionText()
19+
{
20+
Assert(1 == 2);
21+
}
22+
23+
/// <summary>
24+
/// Demonstrates assertion failure with a custom message.
25+
/// </summary>
26+
public static void CustomMessage()
27+
{
28+
Assert(false, "This is a custom failure message");
29+
}
30+
31+
/// <summary>
32+
/// Demonstrates complex expression with multiple variables and operators.
33+
/// </summary>
34+
public static void ComplexExpression()
35+
{
36+
var x = 10;
37+
var y = 5;
38+
var z = 3;
39+
Assert(x + y * z > 100);
40+
}
41+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using static SharpAssert.Sharp;
2+
3+
namespace SharpAssert.Demo.Demos;
4+
5+
public static class BinaryComparisonDemos
6+
{
7+
/// <summary>
8+
/// Demonstrates equality and inequality operators with different types.
9+
/// </summary>
10+
public static void EqualityOperators()
11+
{
12+
var actual = 42;
13+
var expected = 100;
14+
Assert(actual == expected);
15+
}
16+
17+
/// <summary>
18+
/// Demonstrates relational operators (less than, greater than, etc.) with numbers.
19+
/// </summary>
20+
public static void RelationalOperators()
21+
{
22+
var value = 5;
23+
var threshold = 10;
24+
Assert(value > threshold);
25+
}
26+
27+
/// <summary>
28+
/// Demonstrates null comparisons showing left and right operand values.
29+
/// </summary>
30+
public static void NullComparisons()
31+
{
32+
string? nullValue = null;
33+
var nonNullValue = "text";
34+
Assert(nullValue == nonNullValue);
35+
}
36+
37+
static int callCount = 0;
38+
static int GetValue()
39+
{
40+
callCount++;
41+
return 42;
42+
}
43+
44+
/// <summary>
45+
/// Demonstrates that expressions are only evaluated once (single evaluation guarantee).
46+
/// </summary>
47+
public static void SingleEvaluationDemo()
48+
{
49+
callCount = 0;
50+
Assert(GetValue() == 100);
51+
}
52+
53+
/// <summary>
54+
/// Demonstrates comparing different types showing type information.
55+
/// </summary>
56+
public static void TypeMismatch()
57+
{
58+
object intValue = 42;
59+
object stringValue = "42";
60+
Assert(intValue.Equals(stringValue));
61+
}
62+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using static SharpAssert.Sharp;
2+
3+
namespace SharpAssert.Demo.Demos;
4+
5+
public static class LogicalOperatorDemos
6+
{
7+
/// <summary>
8+
/// Demonstrates AND operator failure showing which operand failed.
9+
/// </summary>
10+
public static void AndOperatorFailure()
11+
{
12+
var left = true;
13+
var right = false;
14+
Assert(left && right);
15+
}
16+
17+
/// <summary>
18+
/// Demonstrates short-circuit AND evaluation (right side not evaluated when left is false).
19+
/// </summary>
20+
public static void ShortCircuitAnd()
21+
{
22+
var condition = false;
23+
Assert(condition && ThrowsException());
24+
}
25+
26+
static bool ThrowsException()
27+
{
28+
throw new InvalidOperationException("This should not be called due to short-circuit");
29+
}
30+
31+
/// <summary>
32+
/// Demonstrates OR operator failure showing both operands were evaluated.
33+
/// </summary>
34+
public static void OrOperatorFailure()
35+
{
36+
var left = false;
37+
var right = false;
38+
Assert(left || right);
39+
}
40+
41+
/// <summary>
42+
/// Demonstrates NOT operator showing the actual value that was negated.
43+
/// </summary>
44+
public static void NotOperator()
45+
{
46+
var value = true;
47+
Assert(!value);
48+
}
49+
50+
/// <summary>
51+
/// Demonstrates complex nested logical expressions with multiple operators.
52+
/// </summary>
53+
public static void NestedLogical()
54+
{
55+
var a = true;
56+
var b = false;
57+
var c = true;
58+
var d = false;
59+
Assert((a && b) || (c && d));
60+
}
61+
}

0 commit comments

Comments
 (0)