Skip to main content
added 7 characters in body
Source Link
t3chb0t
  • 44.3k
  • 9
  • 84
  • 190
[SettingName("TehApp")]
internal class TehApplicashun
{
    public static readonly string Name = Assembly.GetAssembly(typeof(Program)).GetName().Name;
    public static readonly string Version = "2.0.0";
    private static readonly string GlobalFileName = "_Global.json";

    private readonly ILogger _logger;
    private readonly IPathResolver _pathResolver;
    private readonly IFileSystem _fileSystem;
    private readonly IVariableBuilder _variableBuilder;
    private readonly AutofacContractResolver _autofacContractResolver;
    private readonly TestRunner _testRunner;

    public TehApplicashun(
        ILogger logger,
        IPathResolver pathResolver,
        IFileSystem fileSystem,
        IVariableBuilder variableBuilder,
        AutofacContractResolver autofacContractResolver,
        TestRunner testRunner)
    {
        _logger = logger;
        _pathResolver = pathResolver;
        _fileSystem = fileSystem;
        _variableBuilder = variableBuilder;
        _autofacContractResolver = autofacContractResolver;
        _testRunner = testRunner;
    }

    public Workspace Workspace { get; set; }

    public void Start(string[] args)
    {
        var globalFile = LoadGlobalFile();

        var globals = VariableResolver.Empty
            .MergeWith(globalFile.Globals)
            .MergeWith(_variableBuilder.BuildVariables(Workspace));

        var testFiles = LoadTestFiles().ToList();

        LogEntry.New().Debug().Message($"Test files ({testFiles.Count}) loaded.").Log(_logger);
        LogEntry.New().Info().Message($"*** {Name} v{Version} started. ***").Log(_logger);

        _testRunner.RunTestFiles(testFiles, args, globals);
    }

    private GlobalFile LoadGlobalFile()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);
        var fileName = Path.Combine(targetsDirectoryName, GlobalFileName);

        if (!File.Exists(fileName)) { return new GlobalFile(); }

        try
        {
            var globalFileJson = File_fileSystem.ReadAllText(fileName);
            var globalFile = JsonConvert.DeserializeObject<GlobalFile>(globalFileJson);

            VariableValidator.ValidateNamesNotReserved(globalFile.Globals, _variableBuilder.Names);

            LogEntry.New().Debug().Message($"{Path.GetFileName(fileName)} loaded.").Log(_logger);

            return globalFile;
        }
        catch (Exception ex)
        {
            throw new InitializationException($"Could not load {Path.GetFileName(fileName)}.", ex);
        }
    }

    [NotNull, ItemNotNull]
    private IEnumerable<TestFile> LoadTestFiles()
    {
        LogEntry.New().Debug().Message("Initializing tests...").Log(_logger);

        return 
            GetTestFileNames()
                .Select(LoadTest)
                .Where(Conditional.IsNotNull);
    }

    [NotNull, ItemNotNull]
    private IEnumerable<string> GetTestFileNames()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);

        return
            from fullName in _fileSystem.GetFiles(targetsDirectoryName, "*.json")
            where !Path.GetFileName(fullName).StartsWith("_", StringComparison.OrdinalIgnoreCase)
            select fullName;
    }

    [CanBeNull]
    private TestFile LoadTest(string fileName)
    {
        var logEntry = LogEntry.New().Info();
        try
        {
            var json = _fileSystem.ReadAllText(fileName);
            var testFile = JsonConvert.DeserializeObject<TestFile>(json, new JsonSerializerSettings
            {
                ContractResolver = _autofacContractResolver,
                DefaultValueHandling = DefaultValueHandling.Populate,
                TypeNameHandling = TypeNameHandling.Auto,
            });
            testFile.FullName = fileName;

            VariableValidator.ValidateNamesNotReserved(testFile.Locals, _variableBuilder.Names);

            logEntry.Message($"Test initialized: {fileName}");
            return testFile;
        }
        catch (Exception ex)
        {
            logEntry.Error().Message($"Could not initialize test: {fileName}").Exception(ex);
            return null;
        }
        finally
        {
            logEntry.Log(_logger);
        }
    }
}
[SettingName("TehApp")]
internal class TehApplicashun
{
    public static readonly string Name = Assembly.GetAssembly(typeof(Program)).GetName().Name;
    public static readonly string Version = "2.0.0";
    private static readonly string GlobalFileName = "_Global.json";

    private readonly ILogger _logger;
    private readonly IPathResolver _pathResolver;
    private readonly IFileSystem _fileSystem;
    private readonly IVariableBuilder _variableBuilder;
    private readonly AutofacContractResolver _autofacContractResolver;
    private readonly TestRunner _testRunner;

    public TehApplicashun(
        ILogger logger,
        IPathResolver pathResolver,
        IFileSystem fileSystem,
        IVariableBuilder variableBuilder,
        AutofacContractResolver autofacContractResolver,
        TestRunner testRunner)
    {
        _logger = logger;
        _pathResolver = pathResolver;
        _fileSystem = fileSystem;
        _variableBuilder = variableBuilder;
        _autofacContractResolver = autofacContractResolver;
        _testRunner = testRunner;
    }

    public Workspace Workspace { get; set; }

    public void Start(string[] args)
    {
        var globalFile = LoadGlobalFile();

        var globals = VariableResolver.Empty
            .MergeWith(globalFile.Globals)
            .MergeWith(_variableBuilder.BuildVariables(Workspace));

        var testFiles = LoadTestFiles().ToList();

        LogEntry.New().Debug().Message($"Test files ({testFiles.Count}) loaded.").Log(_logger);
        LogEntry.New().Info().Message($"*** {Name} v{Version} started. ***").Log(_logger);

        _testRunner.RunTestFiles(testFiles, args, globals);
    }

    private GlobalFile LoadGlobalFile()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);
        var fileName = Path.Combine(targetsDirectoryName, GlobalFileName);

        if (!File.Exists(fileName)) { return new GlobalFile(); }

        try
        {
            var globalFileJson = File.ReadAllText(fileName);
            var globalFile = JsonConvert.DeserializeObject<GlobalFile>(globalFileJson);

            VariableValidator.ValidateNamesNotReserved(globalFile.Globals, _variableBuilder.Names);

            LogEntry.New().Debug().Message($"{Path.GetFileName(fileName)} loaded.").Log(_logger);

            return globalFile;
        }
        catch (Exception ex)
        {
            throw new InitializationException($"Could not load {Path.GetFileName(fileName)}.", ex);
        }
    }

    [NotNull, ItemNotNull]
    private IEnumerable<TestFile> LoadTestFiles()
    {
        LogEntry.New().Debug().Message("Initializing tests...").Log(_logger);

        return 
            GetTestFileNames()
                .Select(LoadTest)
                .Where(Conditional.IsNotNull);
    }

    [NotNull, ItemNotNull]
    private IEnumerable<string> GetTestFileNames()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);

        return
            from fullName in _fileSystem.GetFiles(targetsDirectoryName, "*.json")
            where !Path.GetFileName(fullName).StartsWith("_", StringComparison.OrdinalIgnoreCase)
            select fullName;
    }

    [CanBeNull]
    private TestFile LoadTest(string fileName)
    {
        var logEntry = LogEntry.New().Info();
        try
        {
            var json = _fileSystem.ReadAllText(fileName);
            var testFile = JsonConvert.DeserializeObject<TestFile>(json, new JsonSerializerSettings
            {
                ContractResolver = _autofacContractResolver,
                DefaultValueHandling = DefaultValueHandling.Populate,
                TypeNameHandling = TypeNameHandling.Auto,
            });
            testFile.FullName = fileName;

            VariableValidator.ValidateNamesNotReserved(testFile.Locals, _variableBuilder.Names);

            logEntry.Message($"Test initialized: {fileName}");
            return testFile;
        }
        catch (Exception ex)
        {
            logEntry.Error().Message($"Could not initialize test: {fileName}").Exception(ex);
            return null;
        }
        finally
        {
            logEntry.Log(_logger);
        }
    }
}
[SettingName("TehApp")]
internal class TehApplicashun
{
    public static readonly string Name = Assembly.GetAssembly(typeof(Program)).GetName().Name;
    public static readonly string Version = "2.0.0";
    private static readonly string GlobalFileName = "_Global.json";

    private readonly ILogger _logger;
    private readonly IPathResolver _pathResolver;
    private readonly IFileSystem _fileSystem;
    private readonly IVariableBuilder _variableBuilder;
    private readonly AutofacContractResolver _autofacContractResolver;
    private readonly TestRunner _testRunner;

    public TehApplicashun(
        ILogger logger,
        IPathResolver pathResolver,
        IFileSystem fileSystem,
        IVariableBuilder variableBuilder,
        AutofacContractResolver autofacContractResolver,
        TestRunner testRunner)
    {
        _logger = logger;
        _pathResolver = pathResolver;
        _fileSystem = fileSystem;
        _variableBuilder = variableBuilder;
        _autofacContractResolver = autofacContractResolver;
        _testRunner = testRunner;
    }

    public Workspace Workspace { get; set; }

    public void Start(string[] args)
    {
        var globalFile = LoadGlobalFile();

        var globals = VariableResolver.Empty
            .MergeWith(globalFile.Globals)
            .MergeWith(_variableBuilder.BuildVariables(Workspace));

        var testFiles = LoadTestFiles().ToList();

        LogEntry.New().Debug().Message($"Test files ({testFiles.Count}) loaded.").Log(_logger);
        LogEntry.New().Info().Message($"*** {Name} v{Version} started. ***").Log(_logger);

        _testRunner.RunTestFiles(testFiles, args, globals);
    }

    private GlobalFile LoadGlobalFile()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);
        var fileName = Path.Combine(targetsDirectoryName, GlobalFileName);

        if (!File.Exists(fileName)) { return new GlobalFile(); }

        try
        {
            var globalFileJson = _fileSystem.ReadAllText(fileName);
            var globalFile = JsonConvert.DeserializeObject<GlobalFile>(globalFileJson);

            VariableValidator.ValidateNamesNotReserved(globalFile.Globals, _variableBuilder.Names);

            LogEntry.New().Debug().Message($"{Path.GetFileName(fileName)} loaded.").Log(_logger);

            return globalFile;
        }
        catch (Exception ex)
        {
            throw new InitializationException($"Could not load {Path.GetFileName(fileName)}.", ex);
        }
    }

    [NotNull, ItemNotNull]
    private IEnumerable<TestFile> LoadTestFiles()
    {
        LogEntry.New().Debug().Message("Initializing tests...").Log(_logger);

        return 
            GetTestFileNames()
                .Select(LoadTest)
                .Where(Conditional.IsNotNull);
    }

    [NotNull, ItemNotNull]
    private IEnumerable<string> GetTestFileNames()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);

        return
            from fullName in _fileSystem.GetFiles(targetsDirectoryName, "*.json")
            where !Path.GetFileName(fullName).StartsWith("_", StringComparison.OrdinalIgnoreCase)
            select fullName;
    }

    [CanBeNull]
    private TestFile LoadTest(string fileName)
    {
        var logEntry = LogEntry.New().Info();
        try
        {
            var json = _fileSystem.ReadAllText(fileName);
            var testFile = JsonConvert.DeserializeObject<TestFile>(json, new JsonSerializerSettings
            {
                ContractResolver = _autofacContractResolver,
                DefaultValueHandling = DefaultValueHandling.Populate,
                TypeNameHandling = TypeNameHandling.Auto,
            });
            testFile.FullName = fileName;

            VariableValidator.ValidateNamesNotReserved(testFile.Locals, _variableBuilder.Names);

            logEntry.Message($"Test initialized: {fileName}");
            return testFile;
        }
        catch (Exception ex)
        {
            logEntry.Error().Message($"Could not initialize test: {fileName}").Exception(ex);
            return null;
        }
        finally
        {
            logEntry.Log(_logger);
        }
    }
}
Source Link
t3chb0t
  • 44.3k
  • 9
  • 84
  • 190

It wasn't easy but I managed to move all code that needs to be tested into a new TehApplicashun class - I know, lolcat speak :-) that now receives a bunch of serivces and is created by Autofac too. Everything is abstracted and everything can be replaced for testing. Now I can test the application's behavior for example to verfiy it exits if one of the requried files is missing or doesn't crash if an optional one is invalid.

[SettingName("TehApp")]
internal class TehApplicashun
{
    public static readonly string Name = Assembly.GetAssembly(typeof(Program)).GetName().Name;
    public static readonly string Version = "2.0.0";
    private static readonly string GlobalFileName = "_Global.json";

    private readonly ILogger _logger;
    private readonly IPathResolver _pathResolver;
    private readonly IFileSystem _fileSystem;
    private readonly IVariableBuilder _variableBuilder;
    private readonly AutofacContractResolver _autofacContractResolver;
    private readonly TestRunner _testRunner;

    public TehApplicashun(
        ILogger logger,
        IPathResolver pathResolver,
        IFileSystem fileSystem,
        IVariableBuilder variableBuilder,
        AutofacContractResolver autofacContractResolver,
        TestRunner testRunner)
    {
        _logger = logger;
        _pathResolver = pathResolver;
        _fileSystem = fileSystem;
        _variableBuilder = variableBuilder;
        _autofacContractResolver = autofacContractResolver;
        _testRunner = testRunner;
    }

    public Workspace Workspace { get; set; }

    public void Start(string[] args)
    {
        var globalFile = LoadGlobalFile();

        var globals = VariableResolver.Empty
            .MergeWith(globalFile.Globals)
            .MergeWith(_variableBuilder.BuildVariables(Workspace));

        var testFiles = LoadTestFiles().ToList();

        LogEntry.New().Debug().Message($"Test files ({testFiles.Count}) loaded.").Log(_logger);
        LogEntry.New().Info().Message($"*** {Name} v{Version} started. ***").Log(_logger);

        _testRunner.RunTestFiles(testFiles, args, globals);
    }

    private GlobalFile LoadGlobalFile()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);
        var fileName = Path.Combine(targetsDirectoryName, GlobalFileName);

        if (!File.Exists(fileName)) { return new GlobalFile(); }

        try
        {
            var globalFileJson = File.ReadAllText(fileName);
            var globalFile = JsonConvert.DeserializeObject<GlobalFile>(globalFileJson);

            VariableValidator.ValidateNamesNotReserved(globalFile.Globals, _variableBuilder.Names);

            LogEntry.New().Debug().Message($"{Path.GetFileName(fileName)} loaded.").Log(_logger);

            return globalFile;
        }
        catch (Exception ex)
        {
            throw new InitializationException($"Could not load {Path.GetFileName(fileName)}.", ex);
        }
    }

    [NotNull, ItemNotNull]
    private IEnumerable<TestFile> LoadTestFiles()
    {
        LogEntry.New().Debug().Message("Initializing tests...").Log(_logger);

        return 
            GetTestFileNames()
                .Select(LoadTest)
                .Where(Conditional.IsNotNull);
    }

    [NotNull, ItemNotNull]
    private IEnumerable<string> GetTestFileNames()
    {
        var targetsDirectoryName = _pathResolver.ResolveDirectoryPath(Workspace.Targets);

        return
            from fullName in _fileSystem.GetFiles(targetsDirectoryName, "*.json")
            where !Path.GetFileName(fullName).StartsWith("_", StringComparison.OrdinalIgnoreCase)
            select fullName;
    }

    [CanBeNull]
    private TestFile LoadTest(string fileName)
    {
        var logEntry = LogEntry.New().Info();
        try
        {
            var json = _fileSystem.ReadAllText(fileName);
            var testFile = JsonConvert.DeserializeObject<TestFile>(json, new JsonSerializerSettings
            {
                ContractResolver = _autofacContractResolver,
                DefaultValueHandling = DefaultValueHandling.Populate,
                TypeNameHandling = TypeNameHandling.Auto,
            });
            testFile.FullName = fileName;

            VariableValidator.ValidateNamesNotReserved(testFile.Locals, _variableBuilder.Names);

            logEntry.Message($"Test initialized: {fileName}");
            return testFile;
        }
        catch (Exception ex)
        {
            logEntry.Error().Message($"Could not initialize test: {fileName}").Exception(ex);
            return null;
        }
        finally
        {
            logEntry.Log(_logger);
        }
    }
}

Additionaly I had to create a new small service to be able to fake the file-system and simulate missing or invalid file.

[PublicAPI]
internal interface IFileSystem
{
    string ReadAllText(string fileName);
    string[] GetFiles(string path, string searchPattern);
}

internal class FileSystem : IFileSystem
{
    public string ReadAllText(string fileName)
    {
        return File.ReadAllText(fileName);
    }

    public string[] GetFiles(string path, string searchPattern)
    {
        return Directory.GetFiles(path, searchPattern);
    }
}

The new Main is now nice and small. Jut resolve TehApplicashun and Start.

private static int Main(string[] args)
{
    var mainLogEntry = 
        LogEntry
            .New()
            .MessageBuilder(sb => sb.Append($"*** {TehApplicashun.Name} v{TehApplicashun.Version}"))
            .Stopwatch(sw => sw.Start());

    try
    {
        var container = InitializeContainer().GetAwaiter().GetResult();
        using (var scope = container.BeginLifetimeScope())
        {
            var tehApp = scope.Resolve<TehApplicashun>();
            tehApp.Start(args);                    
        }

        mainLogEntry.Info().MessageBuilder(sb => sb.Append("completed."));
        return 0;
    }
    catch (Exception ex)
    {
        mainLogEntry.Fatal().MessageBuilder(sb => sb.Append("crashed.")).Exception(ex);
        return 1;
    }
    finally
    {
        mainLogEntry.MessageBuilder(sb => sb.Append(" ***")).Log(Logger);
    }
}

I still need to clean-up the container configuration but this shouldn't be easy done with autofac-modules also exchangable for testing.