26.06.08
This commit is contained in:
@@ -3,7 +3,6 @@ using Microsoft.CodeAnalysis.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Text;
|
||||
|
||||
namespace G;
|
||||
@@ -20,12 +19,9 @@ public class TestsGenerator : IIncrementalGenerator
|
||||
|
||||
context.RegisterSourceOutput(compilationProvider, (spc, compilation) =>
|
||||
{
|
||||
// Генерируем тесты только если это тестовый проект
|
||||
var assemblyName = compilation.AssemblyName;
|
||||
if (assemblyName == null || !assemblyName.EndsWith(".Tests"))
|
||||
if (compilation.AssemblyName == null || !compilation.AssemblyName.EndsWith(".Tests"))
|
||||
return;
|
||||
|
||||
// Находим основную сборку
|
||||
var mensuraAssembly = compilation.References
|
||||
.Select(r => compilation.GetAssemblyOrModuleSymbol(r) as IAssemblySymbol)
|
||||
.FirstOrDefault(a => a?.Name == "QWERTYkez.Mensura" || a?.Name?.EndsWith(".Mensura") == true);
|
||||
@@ -33,7 +29,6 @@ public class TestsGenerator : IIncrementalGenerator
|
||||
if (mensuraAssembly == null)
|
||||
return;
|
||||
|
||||
// Собираем типы с атрибутами
|
||||
var targetTypes = new List<INamedTypeSymbol>();
|
||||
CollectTypesWithAttribute(mensuraAssembly.GlobalNamespace, targetTypes, UnitAttributeFullName);
|
||||
CollectTypesWithAttribute(mensuraAssembly.GlobalNamespace, targetTypes, ComplexAttributeFullName);
|
||||
@@ -43,81 +38,59 @@ public class TestsGenerator : IIncrementalGenerator
|
||||
|
||||
foreach (var type in targetTypes)
|
||||
{
|
||||
var typeName = type.Name;
|
||||
var unitProperties = GetStaticProperties(type);
|
||||
var firstNonBaseProp = unitProperties.FirstOrDefault(p => !p.Name.StartsWith("_"));
|
||||
if (unitProperties.Length == 0) continue;
|
||||
var firstNonBase = unitProperties.FirstOrDefault(p => !p.Name.StartsWith("_"));
|
||||
if (firstNonBase.Name == null) continue;
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("// <auto-generated/>");
|
||||
sb.AppendLine("#pragma warning disable");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("using Xunit;");
|
||||
sb.AppendLine("using QWERTYkez.Mensura.Units;");
|
||||
sb.AppendLine("using QWERTYkez.Mensura.Extensions;");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"namespace QWERTYkez.Mensura.Tests");
|
||||
sb.AppendLine("{");
|
||||
sb.AppendLine($" public class {typeName}Tests");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine($" private const double Tolerance = 1e-12;");
|
||||
sb.AppendLine();
|
||||
|
||||
// Тест значения по умолчанию
|
||||
sb.AppendLine($" [Fact]");
|
||||
sb.AppendLine($" public void Default_ValueIsZero()");
|
||||
sb.AppendLine($" {{");
|
||||
sb.AppendLine($" var unit = new {typeName}();");
|
||||
sb.AppendLine($" Assert.Equal(0, (double)unit, Tolerance);");
|
||||
sb.AppendLine($" }}");
|
||||
sb.AppendLine();
|
||||
|
||||
// Тесты статических свойств (единиц)
|
||||
foreach (var prop in unitProperties)
|
||||
{
|
||||
bool isBase = prop.Name.StartsWith("_");
|
||||
sb.AppendLine($" [Fact]");
|
||||
sb.AppendLine($" public void {prop.Name}_IsCorrect()");
|
||||
sb.AppendLine($" {{");
|
||||
sb.AppendLine($" var unit = {typeName}.{prop.Name};");
|
||||
if (isBase)
|
||||
{
|
||||
sb.AppendLine($" Assert.Equal(1, (double)unit, Tolerance);");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine($" Assert.True((double)unit > 0);");
|
||||
}
|
||||
sb.AppendLine($" }}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
// Тесты коллекционных методов
|
||||
if (unitProperties.Length > 0 && firstNonBaseProp.Name != null)
|
||||
{
|
||||
sb.AppendLine($" [Fact]");
|
||||
sb.AppendLine($" public void CollectionOperations_Work()");
|
||||
sb.AppendLine($" {{");
|
||||
sb.AppendLine($" var first = {typeName}.{firstNonBaseProp.Name};");
|
||||
sb.AppendLine($" var items = new[] {{ first, first }};");
|
||||
sb.AppendLine($" var sum = items.Sum();");
|
||||
sb.AppendLine($" Assert.True((double)sum > 0);");
|
||||
sb.AppendLine($" var avg = items.Average();");
|
||||
sb.AppendLine($" Assert.True((double)avg > 0);");
|
||||
sb.AppendLine($" var max = items.Max();");
|
||||
sb.AppendLine($" Assert.True((double)max > 0);");
|
||||
sb.AppendLine($" var min = items.Min();");
|
||||
sb.AppendLine($" Assert.True((double)min > 0);");
|
||||
sb.AppendLine($" }}");
|
||||
sb.AppendLine();
|
||||
}
|
||||
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine("}");
|
||||
spc.AddSource($"{typeName}Tests.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
||||
// Генерируем два файла
|
||||
GenerateSerializationTest(spc, type.Name, firstNonBase.Name, "SystemText", "System.Text.Json");
|
||||
GenerateSerializationTest(spc, type.Name, firstNonBase.Name, "Newtonsoft", "Newtonsoft.Json");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void GenerateSerializationTest(SourceProductionContext spc, string typeName, string unitName, string framework, string namespaceName)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("// <auto-generated/>");
|
||||
sb.AppendLine("#pragma warning disable");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("using Xunit;");
|
||||
sb.AppendLine($"using {namespaceName};");
|
||||
sb.AppendLine("using QWERTYkez.Mensura.Units;");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"namespace QWERTYkez.Mensura.Tests");
|
||||
sb.AppendLine("{");
|
||||
sb.AppendLine($" public class {typeName}Serialization_{framework}Tests");
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine($" private const double Tolerance = 1e-12;");
|
||||
sb.AppendLine($" private readonly {typeName} _testValue = {typeName}.{unitName};");
|
||||
sb.AppendLine();
|
||||
|
||||
// Тест
|
||||
sb.AppendLine(" [Fact]");
|
||||
sb.AppendLine($" public void {framework}_SerializeDeserialize_ReturnsEqualValue()");
|
||||
sb.AppendLine(" {");
|
||||
if (framework == "SystemText")
|
||||
{
|
||||
sb.AppendLine(" var json = System.Text.Json.JsonSerializer.Serialize(_testValue);");
|
||||
sb.AppendLine($" var deserialized = System.Text.Json.JsonSerializer.Deserialize<{typeName}>(json);");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine(" var json = Newtonsoft.Json.JsonConvert.SerializeObject(_testValue);");
|
||||
sb.AppendLine($" var deserialized = Newtonsoft.Json.JsonConvert.DeserializeObject<{typeName}>(json);");
|
||||
}
|
||||
sb.AppendLine(" Assert.Equal((double)_testValue, (double)deserialized, Tolerance);");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine("}");
|
||||
|
||||
spc.AddSource($"Serialize.{framework}.{typeName}.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
|
||||
}
|
||||
|
||||
private static void CollectTypesWithAttribute(INamespaceSymbol ns, List<INamedTypeSymbol> results, string attributeFullName)
|
||||
{
|
||||
foreach (var type in ns.GetTypeMembers())
|
||||
@@ -154,7 +127,7 @@ public class TestsGenerator : IIncrementalGenerator
|
||||
props.Add(new UnitProperty(propName, prop.Type.ToString()));
|
||||
}
|
||||
}
|
||||
return [.. props];
|
||||
return props.ToImmutableArray();
|
||||
}
|
||||
|
||||
private readonly struct UnitProperty
|
||||
|
||||
Reference in New Issue
Block a user