Skip to content

Commit 7d43260

Browse files
authored
improve test baseline (#3)
1 parent 64fc568 commit 7d43260

File tree

13 files changed

+568
-1
lines changed

13 files changed

+568
-1
lines changed

doc/Testing_Strategy.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,33 @@ Examples:
369369

370370
---
371371

372+
## Assertion Best Practices
373+
374+
**MSTest Guidelines** (no third-party libraries):
375+
376+
1. **Object comparison**: `Assert.AreEqual(expected, actual, message)`
377+
2. **JSON comparison**: Parse with `JsonDocument` for structure validation
378+
3. **Collection comparison**: `CollectionAssert.AreEqual(expected, actual)`
379+
4. **String checks** (MSTEST0037):
380+
- ✅ Use `Assert.Contains(substring, actualString)`
381+
- ✅ Use `Assert.DoesNotContain(substring, actualString)`
382+
- ❌ Avoid `Assert.IsTrue(str.Contains(...))` or `Assert.IsFalse(str.Contains(...))`
383+
5. **Null checks**: `Assert.IsNull()` / `Assert.IsNotNull()`
384+
6. **Boolean checks**: `Assert.IsTrue()` / `Assert.IsFalse()` (but prefer specific assertions when available)
385+
386+
**Example**:
387+
```csharp
388+
// Good
389+
Assert.Contains("\"type\":\"line\"", json);
390+
Assert.DoesNotContain("\"series\"", json);
391+
392+
// Avoid (triggers MSTEST0037 warning)
393+
Assert.IsTrue(json.Contains("\"type\":\"line\""));
394+
Assert.IsFalse(json.Contains("\"series\""));
395+
```
396+
397+
---
398+
372399
## Test Data Isolation & Reusability
373400

374401
### Principles
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[*.cs]
2+
3+
# MSTest analyzer rules
4+
dotnet_diagnostic.MSTEST0037.severity = warning
5+
6+
# Use Assert.Contains/DoesNotContain for string checks
7+
# instead of Assert.IsTrue/IsFalse with .Contains()

src/Vizor.ECharts.Tests/TestFixtures/ChartOptionsBuilder.cs

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,134 @@ public static ChartOptions BarChartMultipleSeries()
4545
}
4646
};
4747
}
48+
49+
public static ChartOptions ScatterChartWithVisualMap()
50+
{
51+
return new ChartOptions
52+
{
53+
Title = new() { Text = "Scatter with Visual Map" },
54+
XAxis = new() { Type = AxisType.Value },
55+
YAxis = new() { Type = AxisType.Value },
56+
VisualMap = new ContinuousVisualMap
57+
{
58+
Min = 0,
59+
Max = 100,
60+
Dimension = 2,
61+
InRange = new()
62+
{
63+
Color = new Color[] { "#50a3ba", "#eac736", "#d94e5d" }
64+
}
65+
},
66+
Series = new List<ISeries>
67+
{
68+
new ScatterSeries
69+
{
70+
Data = new List<SeriesData<double, double, double>>
71+
{
72+
new(10.0, 20.0, 30.0),
73+
new(15.0, 25.0, 50.0),
74+
new(20.0, 30.0, 80.0)
75+
},
76+
SymbolSize = 20
77+
}
78+
}
79+
};
80+
}
81+
82+
public static ChartOptions PieChartWithLabel()
83+
{
84+
return new ChartOptions
85+
{
86+
Title = new() { Text = "Pie Chart", Left = "center" },
87+
Tooltip = new() { Trigger = TooltipTrigger.Item },
88+
Legend = new() { Orient = Orient.Vertical, Left = "left" },
89+
Series = new List<ISeries>
90+
{
91+
new PieSeries
92+
{
93+
Radius = new CircleRadius("50%"),
94+
Data = new List<object>
95+
{
96+
new { value = 335, name = "Direct" },
97+
new { value = 234, name = "Email" },
98+
new { value = 1548, name = "Search" }
99+
},
100+
Emphasis = new()
101+
{
102+
ItemStyle = new()
103+
{
104+
ShadowBlur = 10,
105+
ShadowOffsetX = 0,
106+
ShadowColor = "rgba(0, 0, 0, 0.5)"
107+
}
108+
}
109+
}
110+
}
111+
};
112+
}
113+
114+
public static ChartOptions GaugeChart()
115+
{
116+
return new ChartOptions
117+
{
118+
Series = new List<ISeries>
119+
{
120+
new GaugeSeries
121+
{
122+
Min = 0,
123+
Max = 100,
124+
Data = new List<object> { new { value = 75, name = "Score" } }
125+
}
126+
}
127+
};
128+
}
129+
130+
public static ChartOptions RadarChart()
131+
{
132+
return new ChartOptions
133+
{
134+
Radar = new()
135+
{
136+
Indicator = new List<RadarIndicator>
137+
{
138+
new() { Name = "Sales", Max = 100 },
139+
new() { Name = "Quality", Max = 100 },
140+
new() { Name = "Support", Max = 100 }
141+
}
142+
},
143+
Series = new List<ISeries>
144+
{
145+
new RadarSeries
146+
{
147+
Data = new List<object>
148+
{
149+
new { value = new[] { 90, 80, 85 }, name = "Q1" }
150+
}
151+
}
152+
}
153+
};
154+
}
155+
156+
public static ChartOptions CandlestickChart()
157+
{
158+
return new ChartOptions
159+
{
160+
Title = new() { Text = "Candlestick Chart" },
161+
XAxis = new() { Type = AxisType.Category, Data = new List<string> { "2024-01-01", "2024-01-02", "2024-01-03" } },
162+
YAxis = new() { Type = AxisType.Value },
163+
Series = new List<ISeries>
164+
{
165+
new CandlestickSeries
166+
{
167+
Name = "Stock",
168+
Data = new List<object>
169+
{
170+
new[] { 20, 34, 10, 38 }, // [open, close, lowest, highest]
171+
new[] { 40, 35, 30, 50 },
172+
new[] { 31, 38, 33, 44 }
173+
}
174+
}
175+
}
176+
};
177+
}
48178
}

src/Vizor.ECharts.Tests/TestFixtures/SnapshotHelper.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ public static void AssertJsonSnapshot(
1616
string testClassName,
1717
string testMethodName,
1818
JsonSerializerOptions serializerOptions,
19+
bool skipNormalization = false,
1920
[CallerFilePath] string filePath = "")
2021
{
2122
string actualJson = JsonSerializer.Serialize(actual, serializerOptions);
22-
string normalizedActual = NormalizeJson(actualJson);
23+
string normalizedActual = skipNormalization ? actualJson : NormalizeJson(actualJson);
2324

2425
string snapshotDir = Path.Combine(
2526
Path.GetDirectoryName(filePath)!,
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using Vizor.ECharts.Tests.TestFixtures;
2+
3+
namespace Vizor.ECharts.Tests.Unit.Serialization;
4+
5+
[TestClass]
6+
public class ChartTypesSnapshotTests
7+
{
8+
private static JsonSerializerOptions CreateOptions() => new TestChart().GetSerializerOptions();
9+
10+
[TestMethod]
11+
public void SerializesScatterChartWithVisualMap()
12+
{
13+
var options = ChartOptionsBuilder.ScatterChartWithVisualMap();
14+
SnapshotHelper.AssertJsonSnapshot(
15+
options,
16+
nameof(ChartTypesSnapshotTests),
17+
nameof(SerializesScatterChartWithVisualMap),
18+
CreateOptions());
19+
}
20+
21+
[TestMethod]
22+
public void SerializesPieChartWithLabel()
23+
{
24+
var options = ChartOptionsBuilder.PieChartWithLabel();
25+
SnapshotHelper.AssertJsonSnapshot(
26+
options,
27+
nameof(ChartTypesSnapshotTests),
28+
nameof(SerializesPieChartWithLabel),
29+
CreateOptions());
30+
}
31+
32+
[TestMethod]
33+
public void SerializesGaugeChart()
34+
{
35+
var options = ChartOptionsBuilder.GaugeChart();
36+
SnapshotHelper.AssertJsonSnapshot(
37+
options,
38+
nameof(ChartTypesSnapshotTests),
39+
nameof(SerializesGaugeChart),
40+
CreateOptions());
41+
}
42+
43+
[TestMethod]
44+
public void SerializesRadarChart()
45+
{
46+
var options = ChartOptionsBuilder.RadarChart();
47+
SnapshotHelper.AssertJsonSnapshot(
48+
options,
49+
nameof(ChartTypesSnapshotTests),
50+
nameof(SerializesRadarChart),
51+
CreateOptions());
52+
}
53+
54+
[TestMethod]
55+
public void SerializesCandlestickChart()
56+
{
57+
var options = ChartOptionsBuilder.CandlestickChart();
58+
SnapshotHelper.AssertJsonSnapshot(
59+
options,
60+
nameof(ChartTypesSnapshotTests),
61+
nameof(SerializesCandlestickChart),
62+
CreateOptions());
63+
}
64+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using Vizor.ECharts.Tests.TestFixtures;
2+
3+
namespace Vizor.ECharts.Tests.Unit.Serialization;
4+
5+
[TestClass]
6+
public class ComplexFeaturesTests
7+
{
8+
private static JsonSerializerOptions CreateOptions() => new TestChart().GetSerializerOptions();
9+
10+
[TestMethod]
11+
public void SerializesChartWithDataZoomAndFormatter()
12+
{
13+
var options = new ChartOptions
14+
{
15+
Title = new() { Text = "DataZoom Example" },
16+
XAxis = new() { Type = AxisType.Category, Data = new List<string> { "A", "B", "C" } },
17+
YAxis = new() { Type = AxisType.Value },
18+
DataZoom = new List<IDataZoom>
19+
{
20+
new InsideDataZoom { XAxisIndex = new NumberOrNumberArray(0) },
21+
new SliderDataZoom { XAxisIndex = new NumberOrNumberArray(0), Start = 10, End = 90 }
22+
},
23+
Tooltip = new()
24+
{
25+
Trigger = TooltipTrigger.Axis,
26+
Formatter = new JavascriptFunction("function(params) { return params[0].name + ': ' + params[0].value; }")
27+
},
28+
Series = new List<ISeries>
29+
{
30+
new LineSeries
31+
{
32+
Data = new List<int> { 10, 20, 30 }
33+
}
34+
}
35+
};
36+
37+
SnapshotHelper.AssertJsonSnapshot(
38+
options,
39+
nameof(ComplexFeaturesTests),
40+
nameof(SerializesChartWithDataZoomAndFormatter),
41+
CreateOptions(),
42+
skipNormalization: true);
43+
}
44+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using Vizor.ECharts.Tests.TestFixtures;
2+
3+
namespace Vizor.ECharts.Tests.Unit.Serialization;
4+
5+
[TestClass]
6+
public class EdgeCasesTests
7+
{
8+
private static JsonSerializerOptions CreateOptions() => new TestChart().GetSerializerOptions();
9+
10+
[TestMethod]
11+
public void SerializesEmptyChartOptions()
12+
{
13+
var options = new ChartOptions();
14+
string json = JsonSerializer.Serialize(options, CreateOptions());
15+
16+
using var doc = JsonDocument.Parse(json);
17+
Assert.AreEqual(JsonValueKind.Object, doc.RootElement.ValueKind);
18+
}
19+
20+
[TestMethod]
21+
public void SerializesChartWithNullSeries()
22+
{
23+
var options = new ChartOptions
24+
{
25+
Title = new() { Text = "Null Series" },
26+
Series = null
27+
};
28+
29+
string json = JsonSerializer.Serialize(options, CreateOptions());
30+
Assert.DoesNotContain("\"series\"", json, "Null series should not appear in JSON");
31+
}
32+
33+
[TestMethod]
34+
public void SerializesMultipleAxesAndGrids()
35+
{
36+
var options = new ChartOptions
37+
{
38+
Grid = new Grid { Top = "10%", Bottom = "50%" },
39+
XAxis = new() { Type = AxisType.Category, GridIndex = 0 },
40+
YAxis = new() { Type = AxisType.Value, GridIndex = 0 }
41+
};
42+
43+
string json = JsonSerializer.Serialize(options, CreateOptions());
44+
45+
using var doc = JsonDocument.Parse(json);
46+
Assert.IsTrue(doc.RootElement.TryGetProperty("grid", out _));
47+
Assert.IsTrue(doc.RootElement.TryGetProperty("xAxis", out _));
48+
Assert.IsTrue(doc.RootElement.TryGetProperty("yAxis", out _));
49+
}
50+
51+
[TestMethod]
52+
public void SerializesSeriesWithNullData()
53+
{
54+
var options = new ChartOptions
55+
{
56+
XAxis = new() { Type = AxisType.Category },
57+
YAxis = new() { Type = AxisType.Value },
58+
Series = new List<ISeries>
59+
{
60+
new LineSeries
61+
{
62+
Name = "Test",
63+
Data = null
64+
}
65+
}
66+
};
67+
68+
string json = JsonSerializer.Serialize(options, CreateOptions());
69+
70+
using var doc = JsonDocument.Parse(json);
71+
Assert.IsTrue(doc.RootElement.TryGetProperty("series", out var series));
72+
Assert.AreEqual(1, series.GetArrayLength());
73+
Assert.AreEqual("line", series[0].GetProperty("type").GetString());
74+
}
75+
}

0 commit comments

Comments
 (0)