Skip to content

Commit aff84ad

Browse files
committed
Add migration document
1 parent e8ca123 commit aff84ad

1 file changed

Lines changed: 197 additions & 0 deletions

File tree

‎MIGRATION.md‎

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# SharpAssert Migration Guide
2+
3+
Pytest-style assertions using native C# syntax. MSBuild compile-time rewriting provides rich diagnostics without special syntax.
4+
5+
## Core Concept
6+
7+
```csharp
8+
// Other frameworks
9+
actual.Should().Be(expected);
10+
Assert.AreEqual(expected, actual);
11+
12+
// SharpAssert - native C# expressions
13+
Assert(actual == expected);
14+
```
15+
16+
Basic setup:
17+
```csharp
18+
using static SharpAssert.Sharp;
19+
```
20+
21+
## API
22+
23+
```csharp
24+
Assert(bool condition [, string message])
25+
TException Throws<TException>(Action action [, string message])
26+
Task<TException> ThrowsAsync<TException>(Func<Task> action [, string message])
27+
28+
// Custom Expectations
29+
collection.IsInAscendingOrder([IComparer<T>])
30+
collection.IsInDescendingOrder([IComparer<T>])
31+
collection.AllUnique([Func<T, object> keySelector | IEqualityComparer<object>])
32+
string.Matches(pattern)
33+
string.MatchesIgnoringCase(pattern)
34+
string.Contains(substring, Occur.Exactly|AtLeast|AtMost(count))
35+
string.MatchesRegex(pattern, Occur.Exactly|AtLeast|AtMost(count))
36+
T.IsEquivalentTo(expected [, config => config.Excluding|Including|WithoutStrictOrdering()])
37+
```
38+
39+
## Native C# Support
40+
41+
SharpAssert works with standard C# - no special syntax required:
42+
43+
```csharp
44+
// Comparisons
45+
Assert(actual == expected); // ==, !=, <, >, <=, >=
46+
47+
// Logical
48+
Assert(x > 0 && y < 100); // &&, ||, !
49+
50+
// LINQ
51+
Assert(items.Contains(value));
52+
Assert(items.Any(x => x.Valid));
53+
Assert(items.All(x => x.Valid));
54+
Assert(actual.SequenceEqual(expected));
55+
56+
// Strings (auto-diff on ==)
57+
Assert(str == expected);
58+
Assert(str.StartsWith(prefix));
59+
Assert(str.EndsWith(suffix));
60+
Assert(str.Contains(substring));
61+
62+
// Async
63+
Assert(await GetAsync() == expected);
64+
65+
// Exceptions
66+
Assert(Throws<ArgumentException>(() => code));
67+
Assert(await ThrowsAsync<InvalidOperationException>(() => asyncCode));
68+
```
69+
70+
## Custom Expectations
71+
72+
For reusable patterns not covered above:
73+
74+
```csharp
75+
sealed class IsEvenExpectation(int value) : Expectation
76+
{
77+
public override EvaluationResult Evaluate(ExpectationContext context) =>
78+
value % 2 == 0
79+
? ExpectationResults.Pass(context.Expression)
80+
: ExpectationResults.Fail(context.Expression, $"Expected even, got {value}");
81+
}
82+
83+
// Usage
84+
Assert(IsEven(4));
85+
```
86+
87+
## Anti-Patterns
88+
89+
```csharp
90+
Assert(condition == true); // Bad → Assert(condition)
91+
Assert(value == false); // Bad → Assert(!value)
92+
Assert(x.Equals(y)); // Bad → Assert(x == y)
93+
try { code; Assert(false); } // Bad → Assert(Throws<T>(() => code))
94+
```
95+
96+
---
97+
98+
# Framework Migration
99+
100+
## NUnit / xUnit / MSTest
101+
102+
```csharp
103+
// Basic
104+
Assert.True(condition) → Assert(condition)
105+
Assert.False(condition) → Assert(!condition)
106+
Assert.AreEqual(expected, actual) → Assert(actual == expected)
107+
Assert.AreNotEqual(expected, actual) → Assert(actual != expected)
108+
Assert.IsNull(actual) → Assert(actual == null)
109+
Assert.IsNotNull(actual) → Assert(actual != null)
110+
Assert.Greater(actual, expected) → Assert(actual > expected)
111+
Assert.Less(actual, expected) → Assert(actual < expected)
112+
Assert.That(actual, Is.EqualTo(expected)) → Assert(actual == expected)
113+
114+
// Strings
115+
Assert.That(str, Does.StartWith(prefix)) → Assert(str.StartsWith(prefix))
116+
Assert.That(str, Does.EndWith(suffix)) → Assert(str.EndsWith(suffix))
117+
Assert.That(str, Does.Contain(substring)) → Assert(str.Contains(substring))
118+
StringAssert.Contains(substring, str) → Assert(str.Contains(substring))
119+
120+
// Collections
121+
CollectionAssert.Contains(coll, item) → Assert(coll.Contains(item))
122+
CollectionAssert.AreEqual(exp, actual) → Assert(actual.SequenceEqual(exp))
123+
CollectionAssert.IsEmpty(coll) → Assert(!coll.Any())
124+
CollectionAssert.IsNotEmpty(coll) → Assert(coll.Any())
125+
Assert.That(coll, Has.Count.EqualTo(n)) → Assert(coll.Count() == n)
126+
127+
// Exceptions
128+
Assert.Throws<T>(() => code) → Assert(Throws<T>(() => code))
129+
Assert.ThrowsAsync<T>(() => asyncCode) → Assert(await ThrowsAsync<T>(() => asyncCode))
130+
```
131+
132+
## FluentAssertions
133+
134+
Additional imports:
135+
```csharp
136+
using SharpAssert.Features.Collections; // For IsInAscendingOrder(), AllUnique()
137+
using SharpAssert.Features.Strings; // For Matches(), occurrence counting
138+
```
139+
140+
Migration:
141+
```csharp
142+
// Basic
143+
actual.Should().Be(expected) → Assert(actual == expected)
144+
actual.Should().NotBe(expected) → Assert(actual != expected)
145+
actual.Should().BeTrue() → Assert(actual)
146+
actual.Should().BeFalse() → Assert(!actual)
147+
actual.Should().BeNull() → Assert(actual == null)
148+
actual.Should().NotBeNull() → Assert(actual != null)
149+
actual.Should().BeGreaterThan(x) → Assert(actual > x)
150+
actual.Should().BeLessThan(x) → Assert(actual < x)
151+
152+
// Strings
153+
str.Should().StartWith(prefix) → Assert(str.StartsWith(prefix))
154+
str.Should().EndWith(suffix) → Assert(str.EndsWith(suffix))
155+
str.Should().Contain(substring) → Assert(str.Contains(substring))
156+
str.Should().Match(pattern) → Assert(str.Matches(pattern))
157+
str.Should().MatchEquivalentOf(pattern) → Assert(str.MatchesIgnoringCase(pattern))
158+
str.Should().Contain(sub, Exactly.Once()) → Assert(str.Contains(sub, Occur.Exactly(1)))
159+
str.Should().Contain(sub, AtLeast.Twice())→ Assert(str.Contains(sub, Occur.AtLeast(2)))
160+
str.Should().MatchRegex(pattern) → Assert(str.MatchesRegex(pattern, Occur.AtLeast(1)))
161+
162+
// Collections
163+
coll.Should().Contain(item) → Assert(coll.Contains(item))
164+
coll.Should().NotContain(item) → Assert(!coll.Contains(item))
165+
coll.Should().BeEmpty() → Assert(!coll.Any())
166+
coll.Should().NotBeEmpty() → Assert(coll.Any())
167+
coll.Should().HaveCount(n) → Assert(coll.Count() == n)
168+
coll.Should().Equal(expected) → Assert(coll.SequenceEqual(expected))
169+
coll.Should().BeInAscendingOrder() → Assert(coll.IsInAscendingOrder())
170+
coll.Should().BeInDescendingOrder() → Assert(coll.IsInDescendingOrder())
171+
coll.Should().OnlyHaveUniqueItems() → Assert(coll.AllUnique())
172+
coll.Should().OnlyHaveUniqueItems(x=>x.K) → Assert(coll.AllUnique(x => x.K))
173+
coll.Should().ContainSingle() → Assert(coll.Count() == 1)
174+
coll.Should().AllSatisfy(pred) → Assert(coll.All(pred))
175+
176+
// Objects
177+
obj.Should().BeEquivalentTo(exp) → Assert(obj.IsEquivalentTo(exp))
178+
obj.Should().BeEquivalentTo(exp, o=>o.Excluding(x=>x.Id))
179+
→ Assert(obj.IsEquivalentTo(exp, c=>c.Excluding(x=>x.Id)))
180+
obj.Should().BeEquivalentTo(exp, o=>o.Including(x=>x.Name))
181+
→ Assert(obj.IsEquivalentTo(exp, c=>c.Including(x=>x.Name)))
182+
obj.Should().BeEquivalentTo(exp, o=>o.WithoutStrictOrdering())
183+
→ Assert(obj.IsEquivalentTo(exp, c=>c.WithoutStrictOrdering()))
184+
185+
// Exceptions
186+
act.Should().Throw<T>() → Assert(Throws<T>(act))
187+
act.Should().NotThrow() → Assert(!Throws<Exception>(act))
188+
act.Should().ThrowAsync<T>() → Assert(await ThrowsAsync<T>(act))
189+
act.Should().Throw<T>().WithMessage(msg) → var ex = Throws<T>(act);
190+
Assert(ex.Message.Contains(msg))
191+
192+
// Numerics
193+
val.Should().BePositive() → Assert(val > 0)
194+
val.Should().BeNegative() → Assert(val < 0)
195+
val.Should().BeInRange(min, max) → Assert(val >= min && val <= max)
196+
val.Should().BeCloseTo(target, precision) → Assert(Math.Abs(val - target) <= precision)
197+
```

0 commit comments

Comments
 (0)