Skip to content

Commit 1932687

Browse files
Test refactorings for improved code coverage (#976)
* Test refactorings for improved code coverage Added .runsettings file for configuring code coverage, separated OpenXmlImporter and OpenXmlExporter tests, added new tests for retrieving sheet informations, sheet dimensions and column names, added new queryrange tests, added new addpicture test, removed obsolete FileHelper test utility class * Expanded tests to run on NET8 and NET9 and removed superfluous excel test files * Minor corrections
1 parent 3359104 commit 1932687

36 files changed

Lines changed: 2068 additions & 1218 deletions

.github/workflows/dotnet.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
with:
1818
dotnet-version: |
1919
8.0.x
20+
9.0.x
2021
10.0.x
2122
- name: Restore dependencies
2223
run: dotnet restore

.runsettings

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RunSettings>
3+
<DataCollectionRunSettings>
4+
<DataCollectors>
5+
<DataCollector friendlyName="Code Coverage">
6+
<Configuration>
7+
<CodeCoverage>
8+
<ModulePaths>
9+
<Exclude>
10+
<ModulePath>.*MiniExcel.Tests.Common.dll</ModulePath>
11+
<ModulePath>.*MiniExcel.Csv.Tests.dll</ModulePath>
12+
<ModulePath>.*MiniExcel.OpenXml.Tests.dll</ModulePath>
13+
<ModulePath>.*Dapper.dll</ModulePath>
14+
</Exclude>
15+
</ModulePaths>
16+
17+
<Functions>
18+
<Exclude>
19+
<Function>System.Text.RegularExpressions.Generated</Function>
20+
</Exclude>
21+
</Functions>
22+
</CodeCoverage>
23+
</Configuration>
24+
</DataCollector>
25+
</DataCollectors>
26+
</DataCollectionRunSettings>
27+
</RunSettings>

MiniExcel.slnx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<File Path=".gitattributes" />
88
<File Path=".gitignore" />
99
<File Path=".github\workflows\dotnet.yml" />
10+
<File Path=".runsettings" />
1011
<File Path="LICENSE" />
1112
<File Path="README.md" />
1213
<File Path="README.zh-CN.md" />
@@ -26,9 +27,9 @@
2627
<File Path="src/.editorconfig" />
2728
<File Path="src\Directory.Build.props" />
2829
<File Path="src\Directory.Packages.props" />
29-
<Project Path="src\MiniExcel.OpenXml/MiniExcel.OpenXml.csproj" />
3030
<Project Path="src\MiniExcel.Core\MiniExcel.Core.csproj" />
3131
<Project Path="src\MiniExcel.Csv\MiniExcel.Csv.csproj" />
32+
<Project Path="src\MiniExcel.OpenXml/MiniExcel.OpenXml.csproj" />
3233
<Project Path="src\MiniExcel\MiniExcel.csproj" />
3334
</Folder>
3435
<Folder Name="/tests/">

src/MiniExcel.Core/MiniExcelDataReaderBase.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,10 @@ public DataTable GetSchemaTable()
248248

249249
return Schema;
250250
}
251-
252-
public virtual bool NextResult()
253-
=> throw new NotImplementedException();
254251

255-
public virtual Task<bool> NextResultAsync(CancellationToken cancellationToken = default)
256-
=> throw new NotImplementedException();
252+
public abstract bool NextResult();
253+
254+
public abstract Task<bool> NextResultAsync(CancellationToken cancellationToken = default);
257255

258256

259257
public void Close()

src/MiniExcel.OpenXml/Api/OpenXmlExporter.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ public async Task<int> CopyAndAddSheetAsync(string inputFile, string outputFile,
127127
if (inputFile.Equals(outputFile, StringComparison.InvariantCultureIgnoreCase))
128128
throw new ArgumentException("The generated file must not have the same path as the original file.");
129129

130+
if (Path.GetExtension(outputFile).Equals(".xlsm", StringComparison.InvariantCultureIgnoreCase))
131+
throw new NotSupportedException("MiniExcel's CopyAndAddSheet does not support the .xlsm format");
132+
130133
var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.RandomAccess);
131134
await using var disposableInputStream = inputStream.ConfigureAwait(false);
132135

src/MiniExcel.OpenXml/Api/OpenXmlImporter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public async IAsyncEnumerable<dynamic> QueryAsync(Stream stream, bool hasHeaderR
109109
#region Query Range
110110

111111
/// <summary>
112-
/// Queries a specific rectangular region within an worksheet using index-based coordinates.
112+
/// Queries a specific rectangular region within an worksheet using cell-based coordinates.
113113
/// </summary>
114114
/// <param name="path">The path to the Excel document.</param>
115115
/// <param name="hasHeaderRow">If true, the first row within the range is used as column headers for dynamic object properties. Default is false.</param>
@@ -131,7 +131,7 @@ public async IAsyncEnumerable<dynamic> QueryRangeAsync(string path, bool hasHead
131131
}
132132

133133
/// <summary>
134-
/// Queries a specific rectangular region within an worksheet using index-based coordinates.
134+
/// Queries a specific rectangular region within an worksheet using cell-based coordinates.
135135
/// </summary>
136136
/// <param name="stream">The stream containing the Excel file data. The stream position is not reset after reading.</param>
137137
/// <param name="hasHeaderRow">If true, the first row within the range is used as column headers for dynamic object properties. Default is false.</param>
@@ -375,7 +375,7 @@ public async Task<List<SheetInfo>> GetSheetInformationsAsync(string path, Cancel
375375
[CreateSyncVersion]
376376
public async Task<List<SheetInfo>> GetSheetInformationsAsync(Stream stream, bool leaveOpen = false, CancellationToken cancellationToken = default)
377377
{
378-
var archive = await OpenXmlZip.CreateAsync(stream, cancellationToken: cancellationToken).ConfigureAwait(false);
378+
var archive = await OpenXmlZip.CreateAsync(stream, leaveOpen: leaveOpen, cancellationToken: cancellationToken).ConfigureAwait(false);
379379
await using var disposableArchve = archive.ConfigureAwait(false);
380380

381381
var rels = await OpenXmlReader.GetWorkbookRelsAsync(archive.EntryCollection, cancellationToken).ConfigureAwait(false);

src/MiniExcel.OpenXml/Api/OpenXmlTemplater.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public async Task AddPictureAsync(string path, CancellationToken cancellationTok
2222
var stream = File.Open(path, FileMode.OpenOrCreate);
2323
await using var disposableStream = stream.ConfigureAwait(false);
2424

25-
await MiniExcelPictureImplement.AddPictureAsync(stream, cancellationToken, images).ConfigureAwait(false);
25+
await AddPictureAsync(stream, cancellationToken, images).ConfigureAwait(false);
2626
}
2727

2828
/// <summary>

tests/MiniExcel.Csv.Tests/DataReader/CsvDataReaderAsyncTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ public async Task GetDataReader_GetOrdinal_ReturnsColumnIndex()
115115
public async Task GetDataReader_NextResult_ThrowsNotSupportedException()
116116
{
117117
var path = PathHelper.GetFile("csv/TestDataReaderHeader.csv");
118-
await using var stream = File.OpenRead(path);
119-
await using var reader = await _csvImporter.GetAsyncDataReader(stream, hasHeaderRow: true);
118+
await using var reader = await _csvImporter.GetAsyncDataReader(path, hasHeaderRow: true);
120119

121120
await Assert.ThrowsAsync<NotSupportedException>(async () => await reader.NextResultAsync());
122121
}

tests/MiniExcel.Csv.Tests/DataReader/CsvDataReaderTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,10 @@ public void GetDataReader_GetOrdinal_ReturnsColumnIndex()
112112
}
113113

114114
[Fact]
115-
public async Task GetDataReader_NextResult_ThrowsNotSupportedException()
115+
public void GetDataReader_NextResult_ThrowsNotSupportedException()
116116
{
117117
var path = PathHelper.GetFile("csv/TestDataReaderHeader.csv");
118-
await using var stream = File.OpenRead(path);
119-
await using var reader = await _csvImporter.GetAsyncDataReader(stream, hasHeaderRow: true);
118+
using var reader = _csvImporter.GetDataReader(path, hasHeaderRow: true);
120119

121120
Assert.Throws<NotSupportedException>(() => reader.NextResult());
122121
}

tests/MiniExcel.Csv.Tests/Main/MiniExcelCsvAsyncTests.cs

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ public class MiniExcelCsvAsyncTests
66
private readonly CsvImporter _csvImporter = MiniExcel.Importers.GetCsvImporter();
77

88
[Fact]
9-
public void Gb2312_Encoding_Read_Test()
9+
public async Task Gb2312_Encoding_Read_Test()
1010
{
1111
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
1212
var path = PathHelper.GetFile("csv/gb2312_Encoding_Read_Test.csv");
1313
var config = new CsvConfiguration
1414
{
1515
StreamReaderFunc = stream => new StreamReader(stream, encoding: Encoding.GetEncoding("gb2312"))
1616
};
17-
var rows = _csvImporter.QueryAsync(path, true, configuration: config).ToBlockingEnumerable().ToList();
17+
var rows = await _csvImporter.QueryAsync(path, true, configuration: config).ToListAsync();
1818
Assert.Equal("世界你好", rows[0].栏位1);
1919
}
2020

@@ -57,6 +57,14 @@ public async Task SeperatorTest()
5757
Assert.Equal(expected, await File.ReadAllTextAsync(path));
5858
}
5959

60+
[Fact]
61+
public async Task WriteNullValueTest()
62+
{
63+
using var path = AutoDeletingPath.Create(ExcelType.Csv);
64+
await _csvExporter.ExportAsync(path.FilePath, null!);
65+
Assert.Equal("", File.ReadAllText(path.FilePath));
66+
}
67+
6068
[Fact]
6169
public async Task SaveAsByDictionary()
6270
{
@@ -361,8 +369,67 @@ static async IAsyncEnumerable<TestDto> GetValues()
361369
Assert.Equal("A2", results[1].C1);
362370
Assert.Equal("B2", results[1].C2);
363371
}
364-
365-
[Fact]
372+
373+
[Fact]
374+
public async Task AppendToCsvTest()
375+
{
376+
using var file = AutoDeletingPath.Create(ExcelType.Csv);
377+
var path = file.ToString();
378+
379+
{
380+
var value = new[]
381+
{
382+
new { ID = 1, Name = "Jack", InDate = new DateTime(2021,01,03) },
383+
new { ID = 2, Name = "Henry", InDate = new DateTime(2020,05,03) },
384+
};
385+
await _csvExporter.AppendAsync(path, value);
386+
387+
var content = await File.ReadAllTextAsync(path);
388+
Assert.Equal(
389+
"""
390+
ID,Name,InDate
391+
1,Jack,"2021-01-03 00:00:00"
392+
2,Henry,"2020-05-03 00:00:00"
393+
394+
""", content);
395+
}
396+
{
397+
var value = new { ID = 3, Name = "Mike", InDate = new DateTime(2021, 04, 23) };
398+
await _csvExporter.AppendAsync(path, value);
399+
400+
var content = await File.ReadAllTextAsync(path);
401+
Assert.Equal(
402+
"""
403+
ID,Name,InDate
404+
1,Jack,"2021-01-03 00:00:00"
405+
2,Henry,"2020-05-03 00:00:00"
406+
3,Mike,"2021-04-23 00:00:00"
407+
408+
""", content);
409+
}
410+
{
411+
var value = new[]
412+
{
413+
new { ID = 4, Name = "Frank", InDate = new DateTime(2021,06,07) },
414+
new { ID = 5, Name = "Gloria", InDate = new DateTime(2022,05,03) }
415+
};
416+
await _csvExporter.AppendAsync(path, value);
417+
418+
var content = await File.ReadAllTextAsync(path);
419+
Assert.Equal(
420+
"""
421+
ID,Name,InDate
422+
1,Jack,"2021-01-03 00:00:00"
423+
2,Henry,"2020-05-03 00:00:00"
424+
3,Mike,"2021-04-23 00:00:00"
425+
4,Frank,"2021-06-07 00:00:00"
426+
5,Gloria,"2022-05-03 00:00:00"
427+
428+
""", content);
429+
}
430+
}
431+
432+
[Fact]
366433
public async Task ExportDataTableWithProgressTest()
367434
{
368435
var dataTable = new DataTable();
@@ -409,4 +476,21 @@ public async Task ExportDataTableWithProgressTest()
409476
}
410477
}
411478
}
479+
480+
[Fact]
481+
public async Task GetColumnNamesTest()
482+
{
483+
var path = PathHelper.GetFile(@"csv/TestHeader.csv");
484+
var cols = (await _csvImporter.GetColumnNamesAsync(path, true)).ToArray();
485+
Assert.Equal("Column1", cols[0]);
486+
Assert.Equal("Column2", cols[1]);
487+
}
488+
489+
[Fact]
490+
public async Task GetColumnNamesEmptyTest()
491+
{
492+
await using var ms = new MemoryStream();
493+
var cols = await _csvImporter.GetColumnNamesAsync(ms);
494+
Assert.Empty(cols);
495+
}
412496
}

0 commit comments

Comments
 (0)