vabka
@vabka
Токсичный шарпист

Как при помощи nuke описать фоновую задачу?

Использую Nuke
В проекте есть e2e тесты, которые должны выполняться, когда запущена апишка.
Сейчас я делаю так:
Target на сборку проектов

Target на запуск, который зависит от сборки и триггерит остановку. Тут я делаю Process.Start, перенаправляю stdout и прочее. Запущенные процессы складываю в List

Target на тесты, который зависит от запуска и выполняется строго до остановки

Target на остановку. Тут я прохожусь по всем процессам, останавливаю их, и делаю Dispose всех открытых файлов и StreamWriter-ов

Мне кажется, что получилось немного запутанно, но ничего лучше не придумал.

Вопрос: можно ли это всё сделать красивее? Как подобное делаете вы?
class Build {
    Target FunctionalTests => _ => _
        .After(IntegrationTests)
        .DependsOn(StartForFTests)
        .DependsOn(Compile)
        .Executes(() =>
        {
            foreach (var project in Solution.AllProjects.Where(x => x.Name.EndsWith("Tests.Functional")))
            {
                Logger.Info("Starting {0}", project.Name);
                DotNetTest(c => c
                    .SetProjectFile(project.Path)
                    .EnableNoBuild());
            }
        });

    #region FTests flow

    readonly List<Process> Processes = new();
    readonly List<IDisposable> Resources = new();
    readonly List<Task> Tasks = new();

    Target StartForFTests => _ => _
        .Unlisted()
        .DependsOn(Publish)
        .Executes(async () =>
        {
            foreach (var exec in Out.GlobFiles("*/*.exe"))
            {
                var processStartInfo = new ProcessStartInfo
                {
                    FileName = exec,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true
                };
                Logger.Info("Starting {0}", processStartInfo.FileName);
                var process = Process.Start(processStartInfo);
                if (process != null)
                {
                    Logger.Success("Process {0} started", process.ProcessName);
                    Processes.Add(process);
                }
                else
                {
                    Logger.Error("Can't start {0}", processStartInfo.FileName);
                }
            }

            if (!Directory.Exists(Logs))
                Directory.CreateDirectory(Logs);
            foreach (var proc in Processes)
            {
                var file = File.Open(Logs / proc.ProcessName + ".log", FileMode.OpenOrCreate);
                var errFile = File.Open(Logs / proc.ProcessName + ".error.log", FileMode.OpenOrCreate);
                Resources.Add(file);
                Resources.Add(errFile);
                Tasks.Add(proc.StandardOutput.BaseStream.CopyToAsync(file));
                Tasks.Add(proc.StandardError.BaseStream.CopyToAsync(errFile));
            }

            Logger.Info("Warmup");
            await Task.Delay(TimeSpan.FromSeconds(15));
            var succ = true;
            foreach (var proc in Processes.Where(proc => proc.HasExited))
            {
                Logger.Error("{0} has exited", proc.ProcessName);
                succ = false;
            }

            if (succ)
                Logger.Success("All processes started");
            ControlFlow.Fail("Some processes exited");
        });

    Target StopAfterFTests => _ => _
        .Unlisted()
        .TriggeredBy(StartForFTests)
        .After(FunctionalTests)
        .AssuredAfterFailure()
        .Executes(async () =>
        {
            foreach (var process in Processes) process.Kill();
            foreach (var process in Processes) process.WaitForExit();
            await Task.WhenAll(Tasks);
            Tasks.Clear();
            Processes.Clear();
            foreach (var resource in Resources) resource.Dispose();
            Resources.Clear();
        });

    #endregion
}
  • Вопрос задан
  • 242 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы