Skip to content

Commit 922937d

Browse files
committed
Add project brief
1 parent 1337df2 commit 922937d

1 file changed

Lines changed: 110 additions & 0 deletions

File tree

BRIEF.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# SharpAssert: Write Assertions, Not Riddles
2+
3+
Tired of deciphering NUnit's `Is.EqualTo(x)` or chaining FluentAssertions like `Should().BeEquivalentTo()`? SharpAssert
4+
transforms your tests by letting you use plain, intuitive C# for your assertions. It eliminates domain-specific languages (DSLs)
5+
for testing and gives you incredibly detailed error messages when things go wrong.
6+
7+
## The SharpAssert Philosophy: Just Write C#
8+
9+
The core idea is simple: **an assertion is just a boolean expression**. If it's `true`, the test passes. If it's `false`, it fails.
10+
SharpAssert hooks into the build process to automatically rewrite your simple boolean checks into rich, diagnostic assertions.
11+
12+
**The Old Way:**
13+
```csharp
14+
// NUnit
15+
Assert.That(result, Is.EqualTo(expected));
16+
17+
// FluentAssertions
18+
result.Should().Be(expected);
19+
```
20+
21+
**The Clean Way:**
22+
```csharp
23+
Assert(result == expected);
24+
```
25+
26+
When this fails, SharpAssert provides a rich diagnostic message, showing the value of each part of the expression:
27+
```
28+
Assertion failed: result == expected at MyTest.cs:15
29+
Left: 4
30+
Right: 5
31+
Result: false
32+
```
33+
34+
Or consider this simple test:
35+
```csharp
36+
var items = new[] { 1, 2, 3 };
37+
var target = 4;
38+
39+
Assert(items.Contains(target));
40+
```
41+
42+
When this fails you'll get the rich diagnostics:
43+
```
44+
Assertion failed: items.Contains(target) at ItemTests.cs:211
45+
items: [1, 2, 3]
46+
target: 4
47+
Result: false
48+
```
49+
50+
This level of detail makes debugging failed tests trivial.
51+
The result is cleaner, more readable test code that leverages the C# syntax you already know and love,
52+
removing the need to learn and apply, and decipher a separate assertion DSL.
53+
54+
## Side-by-Side: Common Assertion Idioms
55+
56+
Let's see how common NUnit and FluentAssertions patterns are simplified with SharpAssert, using real examples from the migration.
57+
58+
### 1. Equality and Binary Comparisons
59+
60+
No more `Is.EqualTo` or `Should().Be()`. Just use standard C# operators.
61+
62+
| Scenario | NUnit / FluentAssertions | SharpAssert |
63+
| :--- | :--- | :--- |
64+
| **Simple Equality** | `Assert.That(count, Is.EqualTo(3));`<br>`count.Should().Be(3);` | `Assert(count == 3);` |
65+
| **Property Check** | `Assert.That(item.Data, Is.EqualTo("foo"));`<br>`item.Data.Should().Be("foo");` | `Assert(item.Data == "foo");` |
66+
| **Inequality** | `Assert.That(a, Is.Not.EqualTo(b));`<br>`a.Should().NotBe(b);` | `Assert(a != b);` |
67+
68+
### 2. Boolean Checks
69+
70+
Forget `Is.True` and `Should().BeTrue()`. Your assertions are already boolean!
71+
72+
| Scenario | NUnit / FluentAssertions | SharpAssert |
73+
| :--- | :--- | :--- |
74+
| **Assert True** | `Assert.True(executed);`<br>`executed.Should().BeTrue();` | `Assert(executed);` |
75+
| **Assert False** | `Assert.False(nextPipeExecuted);`<br>`nextPipeExecuted.Should().BeFalse();` | `Assert(!nextPipeExecuted);` |
76+
77+
### 3. Collection and Sequence Comparisons
78+
79+
This is where SharpAssert truly shines by simplifying verbose collection assertions and using familiar LINQ-style methods.
80+
81+
| Scenario | NUnit / FluentAssertions | SharpAssert |
82+
| :--- | :--- | :--- |
83+
| **Sequence Equality** | `Assert.That(batch, Is.EqualTo(new[] {"i1", "i2"}));`<br>`batch.Should().Equal(new[] {"i1", "i2"});` | `Assert(batch.SequenceEqual(new[] {"i1", "i2"}));` |
84+
| **Collection Contains** | `Assert.That(nextReceived, Does.Contain(42));`<br>`nextReceived.Should().Contain(42);` | `Assert(nextReceived.Contains(42));` |
85+
| **Collection Empty** | `Assert.That(mainProcessed, Is.Empty);`<br>`mainProcessed.Should().BeEmpty();` | `Assert(!mainProcessed.Any());` |
86+
| **Collection Count** | `Assert.That(items, Has.Count.EqualTo(2));`<br>`items.Should().HaveCount(2);` | `Assert(items.Count == 2);` |
87+
88+
### 4. Object Identity (Reference Equality)
89+
90+
Checking if two variables point to the same object becomes more explicit and clear using the standard `ReferenceEquals` method.
91+
92+
| Scenario | NUnit / FluentAssertions | SharpAssert |
93+
| :--- | :--- | :--- |
94+
| **Reference Equality** | `Assert.That(doneItems[0], Is.SameAs(item));`<br>`doneItems[0].Should().BeSameAs(item);` | `Assert(ReferenceEquals(doneItems[0], item));` |
95+
96+
### 5. Exception Assertions
97+
98+
SharpAssert provides a powerful and composable way to test for exceptions that feels more integrated with the C# language.
99+
100+
| Scenario | NUnit / FluentAssertions | SharpAssert |
101+
| :--- |:-----------------------------------------------------------------------------------------------------------------------------------------------------| :--- |
102+
| **Simple Throw** | `await Assert.Throws<InvalidCastException>(() => ...);`<br>`Action act = () => ...; act.Should().Throw<InvalidCastException>();` | `Assert(Throws<InvalidCastException>(() => ...));` |
103+
| **Async Throw** | `await Assert.ThrowsAsync<ArgumentException>(() => ...);`<br>`Func<Task> act = async () => ...; await act.Should().ThrowAsync<ArgumentException>();` | `Assert(await ThrowsAsync<ArgumentException>(() => ...));` |
104+
| **Check Exception Message** | `var ex = Assert.Throws<Exception>(...); Assert.That(ex.Message, ...);`<br>`act.Should().Throw<Exception>().WithMessage("...");` | `Assert(Throws<Exception>(...).Message == "...");` |
105+
106+
## Summary
107+
108+
By embracing standard C# syntax, SharpAssert offers a more direct, readable, and ultimately more maintainable way
109+
to write tests. Instead of framework-specific jargon the language-native expressions could be used.
110+
The result is code that is easier to write, easier to read, and comes with powerful diagnostics out-of-the-box.

0 commit comments

Comments
 (0)