Skip to content

Commit 5b2df7b

Browse files
authored
Merge pull request #14 from magic5644/feature-add-json-export
feat: add JSON export format support and implement JSON serialization/deserialization utilities
2 parents 56ea56d + 2644aaf commit 5b2df7b

9 files changed

+361
-249
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
/publish
1313
/*.zip
1414
/*.csv
15+
/*.json
1516
/*.xlsx
1617
/output.txt
1718
/test.cmd

CodeLineCounter.Tests/CoreUtilsTests.cs

+23-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public void ParseArguments_Should_Return_Correct_Values()
1111
string[] args = ["-verbose", "-d", "testDirectory"];
1212

1313
// Act
14-
var (Verbose, DirectoryPath, _) = CoreUtils.ParseArguments(args);
14+
var (Verbose, DirectoryPath, _, _) = CoreUtils.ParseArguments(args);
1515

1616
// Assert
1717
Assert.True(Verbose);
@@ -25,7 +25,7 @@ public void ParseArguments_help_Should_Return_Correct_Values()
2525
string[] args = ["-help"];
2626

2727
// Act
28-
var (_, _, Help) = CoreUtils.ParseArguments(args);
28+
var (_, _, Help, _) = CoreUtils.ParseArguments(args);
2929

3030
// Assert
3131
Assert.True(Help);
@@ -38,7 +38,7 @@ public void ParseArguments_Should_Return_Default_Values_When_No_Arguments_Passed
3838
string[] args = [];
3939

4040
// Act
41-
var (Verbose, DirectoryPath, _) = CoreUtils.ParseArguments(args);
41+
var (Verbose, DirectoryPath, _, _) = CoreUtils.ParseArguments(args);
4242

4343
// Assert
4444
Assert.False(Verbose);
@@ -49,10 +49,10 @@ public void ParseArguments_Should_Return_Default_Values_When_No_Arguments_Passed
4949
public void ParseArguments_Should_Ignore_Invalid_Arguments()
5050
{
5151
// Arrange
52-
string[] args = ["-invalid", "-d", "testDirectory"];
52+
string[] args = ["-invalid", "-d", "testDirectory", "-f", "json"];
5353

5454
// Act
55-
var (Verbose, DirectoryPath, _) = CoreUtils.ParseArguments(args);
55+
var (Verbose, DirectoryPath, _, _) = CoreUtils.ParseArguments(args);
5656

5757
// Assert
5858
Assert.False(Verbose);
@@ -149,7 +149,7 @@ public void GetFilenamesList_Should_Return_List_Of_Filenames()
149149
public void CheckSettings_WhenHelpIsTrue_ReturnsFalse()
150150
{
151151
// Arrange
152-
(bool Verbose, string? DirectoryPath, bool Help) settings = (true, null, true);
152+
(bool Verbose, string? DirectoryPath, bool Help, CoreUtils.ExportFormat format) settings = (true, null, true, CoreUtils.ExportFormat.JSON);
153153
using var sw = new StringWriter();
154154
Console.SetOut(sw);
155155

@@ -165,7 +165,7 @@ public void CheckSettings_WhenHelpIsTrue_ReturnsFalse()
165165
public void CheckSettings_WhenDirectoryPathIsNull_ReturnsFalse()
166166
{
167167
// Arrange
168-
(bool Verbose, string? DirectoryPath, bool Help) settings = (Verbose: false, DirectoryPath: null, Help: false);
168+
(bool Verbose, string? DirectoryPath, bool Help, CoreUtils.ExportFormat format) settings = (Verbose: false, DirectoryPath: null, Help: false, format: CoreUtils.ExportFormat.CSV);
169169
using var sw = new StringWriter();
170170
Console.SetOut(sw);
171171

@@ -181,13 +181,28 @@ public void CheckSettings_WhenDirectoryPathIsNull_ReturnsFalse()
181181
public void CheckSettings_WhenSettingsAreValid_ReturnsTrue()
182182
{
183183
// Arrange
184-
(bool Verbose, string DirectoryPath, bool Help) settings = (false, "some_directory", false);
184+
(bool Verbose, string DirectoryPath, bool Help, CoreUtils.ExportFormat format) settings = (false, "some_directory", false, CoreUtils.ExportFormat.CSV);
185185

186186
// Act
187187
var result = CoreUtils.CheckSettings(settings);
188188

189189
// Assert
190190
Assert.True(result);
191191
}
192+
193+
[Fact]
194+
public void CheckSettings_WhenSettingsAreInvalid_ReturnsFalse()
195+
{
196+
// Arrange
197+
(bool Verbose, string? DirectoryPath, bool Help, CoreUtils.ExportFormat format) settings = (false, null, false, CoreUtils.ExportFormat.CSV);
198+
using var sw = new StringWriter();
199+
Console.SetOut(sw);
200+
201+
// Act
202+
var result = CoreUtils.CheckSettings(settings);
203+
204+
// Assert
205+
Assert.False(result);
206+
}
192207
}
193208
}

CodeLineCounter.Tests/CsvExporterTests.cs

-121
This file was deleted.
+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
using Xunit;
2+
using System;
3+
using System.IO;
4+
using System.Collections.Generic;
5+
using CodeLineCounter.Models;
6+
using CodeLineCounter.Utils;
7+
using System.Linq;
8+
9+
namespace CodeLineCounter.Tests
10+
{
11+
public class DataExporterTests : IDisposable
12+
{
13+
private readonly string _testDirectory;
14+
private bool _disposed;
15+
16+
public DataExporterTests()
17+
{
18+
_testDirectory = Path.Combine(Path.GetTempPath(), "DataExporterTests");
19+
Directory.CreateDirectory(_testDirectory);
20+
}
21+
22+
[Theory]
23+
[InlineData(CoreUtils.ExportFormat.CSV, ".csv")]
24+
[InlineData(CoreUtils.ExportFormat.JSON, ".json")]
25+
public void Export_SingleItem_CreatesFileWithCorrectExtension(CoreUtils.ExportFormat format, string expectedExtension)
26+
{
27+
// Arrange
28+
var testItem = new TestClass { Id = 1, Name = "Test" };
29+
var filePath = Path.Combine(_testDirectory, "test");
30+
31+
// Act
32+
DataExporter.Export(filePath, testItem, format);
33+
34+
// Assert
35+
Assert.True(File.Exists(filePath + expectedExtension));
36+
}
37+
38+
[Theory]
39+
[InlineData(CoreUtils.ExportFormat.CSV, ".csv")]
40+
[InlineData(CoreUtils.ExportFormat.JSON, ".json")]
41+
public void ExportCollection_WithMultipleItems_CreatesFile(CoreUtils.ExportFormat format, string expectedExtension)
42+
{
43+
// Arrange
44+
var items = new List<TestClass>
45+
{
46+
new() { Id = 1, Name = "Test1" },
47+
new() { Id = 2, Name = "Test2" }
48+
};
49+
var filePath = Path.Combine(_testDirectory, "collection");
50+
51+
// Act
52+
DataExporter.ExportCollection(filePath, items, format);
53+
54+
// Assert
55+
Assert.True(File.Exists(filePath + expectedExtension));
56+
}
57+
58+
[Fact]
59+
public void ExportMetrics_CreatesFileWithCorrectData()
60+
{
61+
// Arrange
62+
var metrics = new List<NamespaceMetrics>
63+
{
64+
new() { ProjectName = "Project1", LineCount = 100 },
65+
new() { ProjectName = "Project2", LineCount = 200 }
66+
};
67+
var projectTotals = new Dictionary<string, int>
68+
{
69+
{ "Project1", 100 },
70+
{ "Project2", 200 }
71+
};
72+
var duplications = new List<DuplicationCode>();
73+
var filePath = Path.Combine(_testDirectory, "metrics");
74+
75+
// Act
76+
DataExporter.ExportMetrics(filePath, metrics, projectTotals, 300, duplications, null, CoreUtils.ExportFormat.CSV);
77+
78+
// Assert
79+
Assert.True(File.Exists(filePath + ".csv"));
80+
}
81+
82+
[Fact]
83+
public void ExportDuplications_CreatesFileWithCorrectData()
84+
{
85+
// Arrange
86+
var duplications = new List<DuplicationCode>
87+
{
88+
new() { CodeHash = "hash1", FilePath = "file1.cs", MethodName = "method1", StartLine = 10, NbLines = 20 },
89+
new() { CodeHash = "hash2", FilePath = "file2.cs", MethodName = "method2", StartLine = 8, NbLines = 10 }
90+
};
91+
var filePath = Path.Combine(_testDirectory, "duplications");
92+
93+
// Act
94+
DataExporter.ExportDuplications(filePath, duplications, CoreUtils.ExportFormat.CSV);
95+
96+
// Assert
97+
Assert.True(File.Exists(filePath + ".csv"));
98+
}
99+
100+
protected virtual void Dispose(bool disposing)
101+
{
102+
if (!_disposed)
103+
{
104+
if (disposing && Directory.Exists(_testDirectory))
105+
{
106+
// Dispose managed resources
107+
Directory.Delete(_testDirectory, true);
108+
}
109+
110+
// Dispose unmanaged resources (if any)
111+
112+
_disposed = true;
113+
}
114+
}
115+
116+
private class TestClass
117+
{
118+
public int Id { get; set; }
119+
public string Name { get; set; } = string.Empty;
120+
}
121+
122+
public void Dispose()
123+
{
124+
Dispose(true);
125+
GC.SuppressFinalize(this);
126+
}
127+
128+
~DataExporterTests()
129+
{
130+
Dispose(false);
131+
}
132+
133+
134+
}
135+
}

CodeLineCounter/Program.cs

+9-4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Linq;
88
using System.Collections.Generic;
9+
using System.Collections.Specialized;
910

1011
namespace CodeLineCounter
1112
{
@@ -30,17 +31,19 @@ static void Main(string[] args)
3031
if (choice == -1) return;
3132

3233
var solutionPath = Path.GetFullPath(solutionFiles[choice - 1]);
33-
AnalyzeAndExportSolution(solutionPath, settings.Verbose);
34+
AnalyzeAndExportSolution(solutionPath, settings.Verbose, settings.format);
3435
}
3536
}
3637

37-
private static void AnalyzeAndExportSolution(string solutionPath, bool verbose)
38+
private static void AnalyzeAndExportSolution(string solutionPath, bool verbose, CoreUtils.ExportFormat format )
3839
{
3940
var timer = new Stopwatch();
4041
timer.Start();
4142
string solutionFilename = Path.GetFileName(solutionPath);
4243
string csvFilePath = $"{solutionFilename}-CodeMetrics.csv";
44+
csvFilePath = CoreUtils.GetExportFileNameWithExtension(csvFilePath, format);
4345
string duplicationCsvFilePath = $"{solutionFilename}-CodeDuplications.csv";
46+
duplicationCsvFilePath = CoreUtils.GetExportFileNameWithExtension(duplicationCsvFilePath, format);
4447

4548
var (metrics, projectTotals, totalLines, totalFiles, duplicationMap) = CodeAnalyzer.AnalyzeSolution(solutionPath);
4649
timer.Stop();
@@ -67,8 +70,10 @@ private static void AnalyzeAndExportSolution(string solutionPath, bool verbose)
6770
Console.WriteLine($"Percentage of duplicated code: {percentageDuplication:F2} %");
6871

6972
Parallel.Invoke(
70-
() => CsvExporter.ExportToCsv(csvFilePath, metrics, projectTotals, totalLines, duplicationMap, solutionPath),
71-
() => CsvExporter.ExportCodeDuplicationsToCsv(duplicationCsvFilePath, duplicationMap)
73+
//() => CsvExporter.ExportToCsv(csvFilePath, metrics, projectTotals, totalLines, duplicationMap, solutionPath),
74+
//() => CsvExporter.ExportCodeDuplicationsToCsv(duplicationCsvFilePath, duplicationMap),
75+
() => DataExporter.ExportMetrics(csvFilePath, metrics, projectTotals, totalLines, duplicationMap, solutionPath, format),
76+
() => DataExporter.ExportDuplications(duplicationCsvFilePath, duplicationMap, format)
7277
);
7378

7479
Console.WriteLine($"The data has been exported to {csvFilePath}");

0 commit comments

Comments
 (0)