Skip to content

Commit 7b83970

Browse files
committed
refactor: improve DependencyGraphGenerator and test cases for better readability and structure
1 parent bc6818f commit 7b83970

3 files changed

Lines changed: 81 additions & 104 deletions

File tree

CodeLineCounter.Tests/DependencyGraphGeneratorTests.cs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using CodeLineCounter.Services;
33
using DotNetGraph.Core;
44
using DotNetGraph.Extensions;
5+
using Microsoft.CodeAnalysis.CSharp.Syntax;
56

67
namespace CodeLineCounter.Tests
78
{
@@ -13,41 +14,44 @@ public class DependencyGraphGeneratorTests : IDisposable
1314

1415
public DependencyGraphGeneratorTests()
1516
{
16-
_testDirectory = Path.Combine(Path.GetTempPath(), "DependencyGraphGeneratorTests");
17+
_testDirectory = Path.Combine(Path.GetTempPath(), "dependencygraphgeneratortests");
1718
Directory.CreateDirectory(_testDirectory);
1819
}
1920
[Fact]
2021
public async Task generate_graph_with_valid_dependencies_creates_dot_file()
2122
{
2223
using (var sw = new StringWriter())
2324
{
24-
Console.SetOut(sw);
25-
25+
var testDirectory = _testDirectory;
26+
string fileName = "testgraph.dot";
2627
// Arrange
2728
var dependencies = new List<DependencyRelation>
2829
{
2930
new DependencyRelation { SourceClass = "ClassA", SourceNamespace = "NamespaceA", SourceAssembly = "AssemblyA", TargetClass = "ClassB" , TargetNamespace = "NamespaceB", TargetAssembly = "AssemblyB", FilePath = "path/to/file", StartLine = 1},
3031
new DependencyRelation { SourceClass = "ClassB", SourceNamespace = "NamespaceB", SourceAssembly = "AssemblyB", TargetClass = "ClassC", TargetNamespace = "NamespaceB", TargetAssembly = "AssemblyB", FilePath = "path/to/file", StartLine = 1}
3132
};
3233

33-
string fileName = "testGraph.dot";
34-
35-
string outputPath = Path.Combine(_testDirectory, fileName);
36-
37-
// Act
38-
39-
DotGraph graph = DependencyGraphGenerator.GenerateGraphOnly(dependencies);
40-
Directory.CreateDirectory(_testDirectory);
41-
await DependencyGraphGenerator.CompileGraphAndWriteToFile(fileName, _testDirectory, graph);
42-
43-
// Assert
44-
Assert.True(File.Exists(outputPath));
45-
string content = await File.ReadAllTextAsync(outputPath);
46-
Assert.Contains("ClassA", content);
47-
Assert.Contains("ClassB", content);
48-
Assert.Contains("ClassC", content);
49-
50-
File.Delete(outputPath);
34+
string outputPath = Path.Combine(testDirectory, fileName);
35+
try
36+
{
37+
Console.SetOut(sw);
38+
39+
// Act
40+
DotGraph graph = DependencyGraphGenerator.GenerateGraphOnly(dependencies);
41+
Directory.CreateDirectory(testDirectory);
42+
await DependencyGraphGenerator.CompileGraphAndWriteToFile(fileName, testDirectory, graph);
43+
44+
// Assert
45+
Assert.True(File.Exists(outputPath));
46+
string content = await File.ReadAllTextAsync(outputPath);
47+
Assert.Contains("ClassA", content);
48+
Assert.Contains("ClassB", content);
49+
Assert.Contains("ClassC", content);
50+
}
51+
finally
52+
{
53+
File.Delete(outputPath);
54+
}
5155
}
5256

5357
}

CodeLineCounter.Tests/SolutionAnalyzerTests.cs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ public void analyze_and_export_solution_succeeds_with_valid_inputs()
4040
var format = CoreUtils.ExportFormat.CSV;
4141
var outputPath = _outputPath;
4242

43-
try
43+
44+
// Redirect console output
45+
using (StringWriter stringWriter = new StringWriter())
4446
{
45-
// Redirect console output
46-
using (StringWriter stringWriter = new StringWriter())
47-
{
4847

49-
Console.SetOut(stringWriter);
48+
Console.SetOut(stringWriter);
49+
50+
try
51+
{
5052

5153
// Act
5254
var exception = Record.Exception(() =>
@@ -57,18 +59,20 @@ public void analyze_and_export_solution_succeeds_with_valid_inputs()
5759
// Assert
5860
Assert.Null(exception);
5961
Assert.True(File.Exists(Path.Combine(outputPath, "TestSolution.CodeMetrics.csv")));
60-
}
61-
62-
}
63-
finally
64-
{
65-
// Cleanup
6662

67-
if (File.Exists(solutionPath))
63+
}
64+
finally
6865
{
69-
File.Delete(solutionPath);
66+
// Cleanup
67+
68+
if (File.Exists(solutionPath))
69+
{
70+
File.Delete(solutionPath);
71+
}
7072
}
7173
}
74+
75+
7276
}
7377

7478
[Fact]

CodeLineCounter/Services/DependencyGraphGenerator.cs

Lines changed: 39 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ public static class DependencyGraphGenerator
1212
{
1313
public static DotGraph GenerateGraphOnly(List<DependencyRelation> dependencies, string? filterNamespace = null, string? filterAssembly = null)
1414
{
15-
var filteredDependencies = dependencies;
16-
filteredDependencies = FilterNamespaceFromDependencies(dependencies, filterNamespace, filteredDependencies);
17-
filteredDependencies = FilterAssemblyFromDependencies(filterAssembly, filteredDependencies);
15+
var filteredDependencies = dependencies
16+
.Where(d => (string.IsNullOrEmpty(filterNamespace) || d.SourceNamespace.Contains(filterNamespace) || d.TargetNamespace.Contains(filterNamespace)) &&
17+
(string.IsNullOrEmpty(filterAssembly) || d.SourceAssembly.Equals(filterAssembly) || d.TargetAssembly.Equals(filterAssembly)))
18+
.ToList();
1819

1920
var vertexInfo = new Dictionary<string, (int incoming, int outgoing)>();
2021
var namespaceGroups = new Dictionary<string, List<string>>();
@@ -50,7 +51,6 @@ public static void CreateClustersAndNodes(Dictionary<string, (int incoming, int
5051
foreach (var vertex in nsGroup.Value)
5152
{
5253
DotNode node = CreateNode(vertexInfo, EncloseNotEmptyOrNullStringInQuotes(vertex));
53-
5454
cluster.Elements.Add(node);
5555
}
5656

@@ -62,7 +62,39 @@ public static void CollectDegreeInformationAndGroupByNamespace(List<DependencyRe
6262
{
6363
foreach (var dep in filteredDependencies)
6464
{
65-
GroupByNamespace(vertexInfo, namespaceGroups, dep);
65+
var sourceLabel = dep.SourceClass;
66+
var targetLabel = dep.TargetClass;
67+
68+
if (!vertexInfo.ContainsKey(sourceLabel))
69+
{
70+
vertexInfo[sourceLabel] = (dep.IncomingDegree, dep.OutgoingDegree);
71+
}
72+
if (!vertexInfo.ContainsKey(targetLabel))
73+
{
74+
vertexInfo[targetLabel] = (dep.IncomingDegree, dep.OutgoingDegree);
75+
}
76+
77+
// Group by namespace
78+
if (!namespaceGroups.TryGetValue(dep.SourceNamespace, out var sourceNamespaceList))
79+
{
80+
sourceNamespaceList = new List<string>();
81+
namespaceGroups[dep.SourceNamespace] = sourceNamespaceList;
82+
}
83+
if (!sourceNamespaceList.Contains(dep.SourceClass))
84+
{
85+
sourceNamespaceList.Add(dep.SourceClass);
86+
}
87+
88+
if (!namespaceGroups.TryGetValue(dep.TargetNamespace, out var targetNamespaceList))
89+
{
90+
targetNamespaceList = new List<string>();
91+
namespaceGroups[dep.TargetNamespace] = targetNamespaceList;
92+
}
93+
94+
if (!targetNamespaceList.Contains(dep.TargetClass))
95+
{
96+
targetNamespaceList.Add(dep.TargetClass);
97+
}
6698
}
6799
}
68100

@@ -125,45 +157,7 @@ public static DotNode CreateNode(Dictionary<string, (int incoming, int outgoing)
125157
return node;
126158
}
127159

128-
private static void GroupByNamespace(Dictionary<string, (int incoming, int outgoing)> vertexInfo, Dictionary<string, List<string>> namespaceGroups, DependencyRelation dep)
129-
{
130-
var sourceLabel = dep.SourceClass;
131-
var targetLabel = dep.TargetClass;
132-
133-
if (!vertexInfo.ContainsKey(sourceLabel))
134-
{
135-
vertexInfo[sourceLabel] = (dep.IncomingDegree, dep.OutgoingDegree);
136-
}
137-
if (!vertexInfo.ContainsKey(targetLabel))
138-
{
139-
vertexInfo[targetLabel] = (dep.IncomingDegree, dep.OutgoingDegree);
140-
}
141-
142-
// Group by namespace
143-
if (!namespaceGroups.TryGetValue(dep.SourceNamespace, out var sourceNamespaceList))
144-
{
145-
sourceNamespaceList = [];
146-
namespaceGroups[dep.SourceNamespace] = sourceNamespaceList;
147-
148-
}
149-
if (!sourceNamespaceList.Contains(dep.SourceClass))
150-
{
151-
sourceNamespaceList.Add(dep.SourceClass);
152-
}
153-
154-
if (!namespaceGroups.TryGetValue(dep.TargetNamespace, out var targetNamespaceList))
155-
{
156-
targetNamespaceList = [];
157-
namespaceGroups[dep.TargetNamespace] = targetNamespaceList;
158-
}
159-
160-
if (!targetNamespaceList.Contains(dep.TargetClass))
161-
{
162-
targetNamespaceList.Add(dep.TargetClass);
163-
}
164-
}
165-
166-
public static async Task CompileGraphAndWriteToFile(string fileName,string outputPath, DotGraph graph)
160+
public static async Task CompileGraphAndWriteToFile(string fileName, string outputPath, DotGraph graph)
167161
{
168162
// Use memory buffer
169163
using var memoryStream = new MemoryStream();
@@ -182,30 +176,6 @@ public static async Task CompileGraphAndWriteToFile(string fileName,string outpu
182176
await memoryStream.CopyToAsync(fileStream); // Write complete buffer to file
183177
}
184178

185-
private static List<DependencyRelation> FilterAssemblyFromDependencies(string? filterAssembly, List<DependencyRelation> filteredDependencies)
186-
{
187-
if (!string.IsNullOrEmpty(filterAssembly))
188-
{
189-
filteredDependencies = filteredDependencies.Where(d =>
190-
d.SourceAssembly.Equals(filterAssembly) ||
191-
d.TargetAssembly.Equals(filterAssembly)).ToList();
192-
}
193-
194-
return filteredDependencies;
195-
}
196-
197-
private static List<DependencyRelation> FilterNamespaceFromDependencies(List<DependencyRelation> dependencies, string? filterNamespace, List<DependencyRelation> filteredDependencies)
198-
{
199-
if (!string.IsNullOrEmpty(filterNamespace))
200-
{
201-
filteredDependencies = dependencies.Where(d =>
202-
d.SourceNamespace.Contains(filterNamespace) ||
203-
d.TargetNamespace.Contains(filterNamespace)).ToList();
204-
}
205-
206-
return filteredDependencies;
207-
}
208-
209179
public static string EncloseNotEmptyOrNullStringInQuotes(string? str)
210180
{
211181
if (!string.IsNullOrEmpty(str))
@@ -216,12 +186,11 @@ public static string EncloseNotEmptyOrNullStringInQuotes(string? str)
216186
{
217187
return string.Empty;
218188
}
219-
220189
}
221190

222191
public static string RemoveQuotes(string str)
223192
{
224193
return str.Replace("\"", "");
225194
}
226195
}
227-
}
196+
}

0 commit comments

Comments
 (0)