Better logging alignment for continous tests

This commit is contained in:
benbierens 2023-06-21 10:06:54 +02:00
parent 978d2d3a84
commit c5c54f5963
No known key found for this signature in database
GPG Key ID: FE44815D96D0A1AA
6 changed files with 102 additions and 55 deletions

View File

@ -1,64 +1,86 @@
using DistTestCore;
using DistTestCore.Codex;
using Logging;
using Utils;
namespace ContinuousTests
{
public class TestRun
public class AllTestsRun
{
private readonly Random random = new Random();
private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory();
private readonly Configuration config;
private readonly BaseLog log;
private readonly FixtureLog log;
private readonly TestFactory testFinder;
private readonly FileManager fileManager;
private ITimeSet timeSet;
public TestRun(Configuration config, BaseLog log, TestFactory testFinder)
public AllTestsRun(Configuration config, FixtureLog log, TestFactory testFinder)
{
this.config = config;
this.log = log;
this.testFinder = testFinder;
fileManager = new FileManager(log, new DistTestCore.Configuration());
timeSet = new DefaultTimeSet();
}
public void Run()
public ContinuousTestResult RunAll()
{
var remainingTests = testFinder.CreateTests().ToList();
var result = ContinuousTestResult.Passed;
while (remainingTests.Any())
{
var test = PickOneRandom(remainingTests);
var nodes = CreateRandomNodes(test.RequiredNumberOfNodes);
AssignEssentials(test, nodes);
fileManager.PushFileSet();
var test = remainingTests.PickOneRandom();
var testLog = log.CreateTestLog(test.Name);
var singleTestRun = new SingleTestRun(config, test, testLog);
log.Log($"Start '{test.Name}'");
try
{
test.Run();
singleTestRun.Run();
log.Log($"'{test.Name}' = Passed");
}
catch
{
log.Log($"'{test.Name}' = Failed");
testLog.MarkAsFailed();
result = ContinuousTestResult.Failed;
}
fileManager.PopFileSet();
ClearEssentials(test);
Thread.Sleep(config.SleepSecondsPerTest * 1000);
}
return result;
}
}
public class SingleTestRun
{
private readonly CodexNodeFactory codexNodeFactory = new CodexNodeFactory();
private readonly Configuration config;
private readonly ContinuousTest test;
private readonly CodexNode[] nodes;
private readonly FileManager fileManager;
public SingleTestRun(Configuration config, ContinuousTest test, BaseLog testLog)
{
this.config = config;
this.test = test;
nodes = CreateRandomNodes(test.RequiredNumberOfNodes, testLog);
fileManager = new FileManager(testLog, new DistTestCore.Configuration());
test.Initialize(nodes, testLog, fileManager);
}
private void AssignEssentials(ContinuousTest test, CodexNode[] nodes)
public void Run()
{
test.Initialize(nodes, log, fileManager);
test.Run();
}
private void ClearEssentials(ContinuousTest test)
public void TearDown()
{
// Looks a little strange, but prevents finished test from interacting further.
test.Initialize(null!, null!, null!);
fileManager.DeleteAllTestFiles();
}
private CodexNode[] CreateRandomNodes(int number, BaseLog testLog)
{
var urls = SelectRandomUrls(number);
return codexNodeFactory.Create(urls, testLog, test.TimeSet);
}
private string[] SelectRandomUrls(int number)
@ -67,23 +89,9 @@ namespace ContinuousTests
var result = new string[number];
for (var i = 0; i < number; i++)
{
result[i] = PickOneRandom(urls);
result[i] = urls.PickOneRandom();
}
return result;
}
private CodexNode[] CreateRandomNodes(int number)
{
var urls = SelectRandomUrls(number);
return codexNodeFactory.Create(urls, log, timeSet);
}
private T PickOneRandom<T>(List<T> remainingItems)
{
var i = random.Next(0, remainingItems.Count);
var result = remainingItems[i];
remainingItems.RemoveAt(i);
return result;
}
}
}

View File

@ -16,6 +16,10 @@ namespace ContinuousTests
public Configuration Load()
{
var config = Read();
//config.LogPath = "logs";
//config.SleepSecondsPerTest = 10;
//config.CodexUrls = new string[] { "http://localhost:8080", "http://localhost:8081" };
Validate(config);
return config;
}

View File

@ -13,33 +13,43 @@ namespace ContinuousTests
public void Run()
{
var config = configLoader.Load();
var log = new TestLog(config.LogPath, true);
log.Log("Starting continuous test run...");
log.Log("Checking configuration...");
PreflightCheck(config);
log.Log("Contacting Codex nodes...");
CheckCodexNodes(log, config);
log.Log("All OK.");
log.Log("");
StartupChecks(config);
while (true)
{
var run = new TestRun(config, log, testFactory);
var log = new FixtureLog(new LogConfig(config.LogPath, false), "StartupChecks");
var allTestsRun = new AllTestsRun(config, log, testFactory);
var result = ContinuousTestResult.Passed;
try
{
run.Run();
result = allTestsRun.RunAll();
}
catch (Exception ex)
{
log.Error($"Exception during test run: " + ex);
}
if (result == ContinuousTestResult.Failed)
{
log.MarkAsFailed();
}
Thread.Sleep(config.SleepSecondsPerTest * 1000);
}
}
private void StartupChecks(Configuration config)
{
var log = new FixtureLog(new LogConfig(config.LogPath, false), "ContinuousTestsRun");
log.Log("Starting continuous test run...");
log.Log("Checking configuration...");
PreflightCheck(config);
log.Log("Contacting Codex nodes...");
CheckCodexNodes(log, config);
log.Log("All OK.");
}
private void PreflightCheck(Configuration config)
{
var tests = testFactory.CreateTests();
@ -106,4 +116,10 @@ namespace ContinuousTests
return true;
}
}
public enum ContinuousTestResult
{
Passed,
Failed
}
}

View File

@ -8,19 +8,19 @@ namespace Logging
private readonly string fullName;
private readonly LogConfig config;
public FixtureLog(LogConfig config)
public FixtureLog(LogConfig config, string name = "")
: base(config.DebugEnabled)
{
start = DateTime.UtcNow;
var folder = DetermineFolder(config);
var fixtureName = GetFixtureName();
var fixtureName = GetFixtureName(name);
fullName = Path.Combine(folder, fixtureName);
this.config = config;
}
public TestLog CreateTestLog()
public TestLog CreateTestLog(string name = "")
{
return new TestLog(fullName, config.DebugEnabled);
return new TestLog(fullName, config.DebugEnabled, name);
}
protected override LogFile CreateLogFile()
@ -36,10 +36,12 @@ namespace Logging
Pad(start.Day));
}
private string GetFixtureName()
private string GetFixtureName(string name)
{
var test = TestContext.CurrentContext.Test;
var className = test.ClassName!.Substring(test.ClassName.LastIndexOf('.') + 1);
if (!string.IsNullOrEmpty(name)) className = name;
return $"{Pad(start.Hour)}-{Pad(start.Minute)}-{Pad(start.Second)}Z_{className.Replace('.', '-')}";
}

View File

@ -9,10 +9,10 @@ namespace Logging
private readonly string methodName;
private readonly string fullName;
public TestLog(string folder, bool debug)
public TestLog(string folder, bool debug, string name = "")
: base(debug)
{
methodName = GetMethodName();
methodName = GetMethodName(name);
fullName = Path.Combine(folder, methodName);
Log($"*** Begin: {methodName}");
@ -39,13 +39,15 @@ namespace Logging
MarkAsFailed();
}
}
protected override LogFile CreateLogFile()
{
return new LogFile(fullName, "log");
}
private string GetMethodName()
private string GetMethodName(string name)
{
if (!string.IsNullOrEmpty(name)) return name;
var test = TestContext.CurrentContext.Test;
var args = FormatArguments(test);
return $"{test.MethodName}{args}";

15
Utils/RandomUtils.cs Normal file
View File

@ -0,0 +1,15 @@
namespace Utils
{
public static class RandomUtils
{
private static readonly Random random = new Random();
public static T PickOneRandom<T>(this List<T> remainingItems)
{
var i = random.Next(0, remainingItems.Count);
var result = remainingItems[i];
remainingItems.RemoveAt(i);
return result;
}
}
}