From eb3188c9ecc24eba4af45efabdfdb57de474f685 Mon Sep 17 00:00:00 2001 From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com> Date: Fri, 8 Nov 2024 21:09:22 +0100 Subject: [PATCH] test: Run test projects parallel --- .cake-scripts/parameters.cake | 2 + .cake-scripts/paths.cake | 2 +- .cake-scripts/version.cake | 2 +- .config/dotnet-tools.json | 2 +- .github/workflows/cicd.yml | 102 +++++++++++------- .github/workflows/test-report.yml | 13 +-- build.cake | 31 +++++- .../TarOutputMemoryStreamTest.cs | 2 +- .../WaitUntilHttpRequestIsSucceededTest.cs | 2 +- 9 files changed, 101 insertions(+), 57 deletions(-) diff --git a/.cake-scripts/parameters.cake b/.cake-scripts/parameters.cake index 320489de1..00c78b211 100644 --- a/.cake-scripts/parameters.cake +++ b/.cake-scripts/parameters.cake @@ -19,6 +19,7 @@ internal sealed class BuildParameters public string PullRequestId { get; private set; } public string Version { get; private set; } public string TestFilter { get; private set; } + public string TestProject { get; private set; } public bool IsLocalBuild { get; private set; } public bool IsReleaseBuild { get; private set; } public bool IsPullRequest { get; private set; } @@ -49,6 +50,7 @@ internal sealed class BuildParameters PullRequestId = buildInformation.PullRequestId, Version = buildInformation.Version, TestFilter = context.Argument("test-filter", null), + TestProject = context.Argument("test-project", null), IsLocalBuild = buildInformation.IsLocalBuild, IsReleaseBuild = !buildInformation.IsLocalBuild && buildInformation.IsReleaseBuild, IsPullRequest = buildInformation.IsPullRequest, diff --git a/.cake-scripts/paths.cake b/.cake-scripts/paths.cake index 720bddacd..4209e74c4 100644 --- a/.cake-scripts/paths.cake +++ b/.cake-scripts/paths.cake @@ -9,7 +9,7 @@ internal sealed class BuildPaths public static BuildPaths Instance(ICakeContext context, string version) { - var baseDir = (DirectoryPath) context.Directory("."); + var baseDir = (DirectoryPath)context.Directory("."); var testResultsDir = baseDir.Combine("test-results"); var testCoverageDir = baseDir.Combine("test-coverage"); diff --git a/.cake-scripts/version.cake b/.cake-scripts/version.cake index a8ab7b043..818abd6db 100644 --- a/.cake-scripts/version.cake +++ b/.cake-scripts/version.cake @@ -1,4 +1,4 @@ -#addin nuget:?package=Cake.Git&version=3.0.0 +#addin nuget:?package=Cake.Git&version=4.0.0 internal sealed class BuildInformation { diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 678c0adde..6c3c9381b 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "cake.tool": { - "version": "3.2.0", + "version": "4.2.0", "commands": [ "dotnet-cake" ] diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml index 9f221c5aa..08b77d44e 100644 --- a/.github/workflows/cicd.yml +++ b/.github/workflows/cicd.yml @@ -25,13 +25,61 @@ env: TZ: CET # https://stackoverflow.com/q/53510011 jobs: - build: + ci: strategy: - fail-fast: false + max-parallel: 6 matrix: - os: [ ubuntu-22.04, windows-2022 ] - - runs-on: ${{ matrix.os }} + test-projects: [ + { name: "Testcontainers", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Platform.Linux", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Platform.Windows", runs-on: "windows-2022" }, + { name: "Testcontainers.Databases", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.ResourceReaper", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.ActiveMq", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.ArangoDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Azurite", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.BigQuery", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Bigtable", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.ClickHouse", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.CockroachDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Consul", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.CosmosDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Couchbase", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.CouchDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.DynamoDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Elasticsearch", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.EventStoreDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.FakeGcsServer", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.FirebirdSql", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Firestore", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.InfluxDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.JanusGraph", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.K3s", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Kafka", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Keycloak", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Kusto", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.LocalStack", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.MariaDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Milvus", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Minio", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.MongoDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.MsSql", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.MySql", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Nats", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Neo4j", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Oracle", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Papercut", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.PostgreSql", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.PubSub", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Pulsar", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.RabbitMq", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.RavenDb", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Redis", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.Redpanda", runs-on: "ubuntu-22.04" }, + { name: "Testcontainers.WebDriver", runs-on: "ubuntu-22.04" } + ] + + runs-on: ${{ matrix.test-projects.runs-on }} steps: - name: Checkout Repository @@ -42,27 +90,9 @@ jobs: - name: Cache NuGet Packages uses: actions/cache@v4 with: - key: ${{ matrix.os }}-nuget-${{ hashFiles('Directory.Packages.props') }} + key: ${{ matrix.test-projects.runs-on }}-nuget-${{ hashFiles('Directory.Packages.props') }} path: ~/.nuget/packages - # Our modules occupy too much disk space. The GitHub-hosted runners ran into the - # error: "no space left on device." The pulled images are not cleaned up between - # the test runs. One obvious approach is splitting the tests and running them on - # multiple runners. However, we need to keep in mind that running too many - # simultaneous builds has an impact on others as well. We observed that scheduled - # Dependabot builds blocked others in the Testcontainers organization. - - name: Free Disk Space - uses: jlumbroso/free-disk-space@v1.3.1 - if: runner.os == 'Linux' - with: - tool-cache: true - android: true - dotnet: true - haskell: true - large-packages: true - docker-images: true - swap-storage: false - - name: Setup .NET uses: actions/setup-dotnet@v4 @@ -76,28 +106,28 @@ jobs: run: dotnet cake --target=Build - name: Run Tests - run: dotnet cake --target=Tests --test-filter=${{ startsWith(matrix.os, 'ubuntu') && 'FullyQualifiedName~Testcontainers' || 'DockerPlatform=Windows' }} + run: dotnet cake --target=Test --test-project=${{ matrix.test-projects.name }} - name: Upload Test And Coverage Results uses: actions/upload-artifact@v4 if: always() with: - name: ${{ matrix.os }} + name: ${{ matrix.test-projects.name }} path: test-results - publish: + cd: if: ${{ contains(fromJson('["develop", "main"]'), github.ref_name) }} - needs: build + needs: ci environment: production - runs-on: ubuntu-22.04 - permissions: contents: write pull-requests: read + runs-on: ubuntu-22.04 + env: CODE_SIGNING_CERTIFICATE_BASE64: ${{ secrets.CODE_SIGNING_CERTIFICATE_BASE64 }} CODE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.CODE_SIGNING_CERTIFICATE_PASSWORD }} @@ -116,16 +146,10 @@ jobs: lfs: true fetch-depth: 0 - - name: Download Test And Coverage Results (ubuntu-22.04) - uses: actions/download-artifact@v4 - with: - name: ubuntu-22.04 - path: test-results - - - name: Download Test And Coverage Results (windows-2022) + - name: Download Test And Coverage Results uses: actions/download-artifact@v4 with: - name: windows-2022 + pattern: Testcontainers* path: test-results - name: Fix Absolute Code Coverage Paths @@ -142,7 +166,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: temurin - java-version: 17 + java-version: 21 - name: Setup .NET uses: actions/setup-dotnet@v4 diff --git a/.github/workflows/test-report.yml b/.github/workflows/test-report.yml index 3b246fb7d..0d8a9836c 100644 --- a/.github/workflows/test-report.yml +++ b/.github/workflows/test-report.yml @@ -8,24 +8,19 @@ on: jobs: report: - strategy: - fail-fast: false - matrix: - os: [ ubuntu-22.04, windows-2022 ] - - runs-on: ${{ matrix.os }} - permissions: actions: read checks: write contents: read + runs-on: ubuntu-22.04 + steps: # https://github.com/dorny/test-reporter/issues/363#issuecomment-2381625959. - name: Publish Test Report uses: dorny/test-reporter@v1.9.1 with: - artifact: ${{ matrix.os }} - name: report (${{ matrix.os }}) + artifact: Testcontainers* + name: Test Report path: '*.trx' reporter: dotnet-trx diff --git a/build.cake b/build.cake index 7b6fb4884..22abda8f7 100644 --- a/build.cake +++ b/build.cake @@ -1,8 +1,8 @@ -#tool nuget:?package=dotnet-sonarscanner&version=9.0.0 +#tool nuget:?package=dotnet-sonarscanner&version=9.0.1 -#addin nuget:?package=Cake.Sonar&version=1.1.32 +#addin nuget:?package=Cake.Sonar&version=1.1.33 -#addin nuget:?package=Cake.Git&version=3.0.0 +#addin nuget:?package=Cake.Git&version=4.0.0 #load ".cake-scripts/parameters.cake" @@ -71,6 +71,26 @@ Task("Build") }); }); +Task("Test") + .Does(() => +{ + var testProject = param.Projects.OnlyTests + .Select(testProject => testProject.Path.FullPath) + .Single(testProject => testProject.EndsWith(param.TestProject + ".Tests.csproj")); + + DotNetTest(testProject, new DotNetTestSettings + { + Configuration = param.Configuration, + Verbosity = param.Verbosity, + NoRestore = true, + NoBuild = true, + Collectors = new[] { "XPlat Code Coverage;Format=opencover" }, + ResultsDirectory = param.Paths.Directories.TestResultsDirectoryPath, + ArgumentCustomization = args => args + .AppendSwitchQuoted("--blame-hang-timeout", "5m") + }); +}); + Task("Tests") .Does(() => { @@ -111,7 +131,10 @@ Task("Sonar-Begin") PullRequestBranch = param.SourceBranch, PullRequestBase = param.TargetBranch, OpenCoverReportsPath = $"{MakeAbsolute(param.Paths.Directories.TestResultsDirectoryPath)}/**/*.opencover.xml", - VsTestReportsPath = $"{MakeAbsolute(param.Paths.Directories.TestResultsDirectoryPath)}/**/*.trx" + VsTestReportsPath = $"{MakeAbsolute(param.Paths.Directories.TestResultsDirectoryPath)}/**/*.trx", + ArgumentCustomization = args => args + .Append("/d:sonar.scanner.scanAll=\"false\"") + .Append("/d:sonar.scanner.skipJreProvisioning=\"true\"") }); }); diff --git a/tests/Testcontainers.Platform.Linux.Tests/TarOutputMemoryStreamTest.cs b/tests/Testcontainers.Platform.Linux.Tests/TarOutputMemoryStreamTest.cs index 8c2bf7cb0..46b810995 100644 --- a/tests/Testcontainers.Platform.Linux.Tests/TarOutputMemoryStreamTest.cs +++ b/tests/Testcontainers.Platform.Linux.Tests/TarOutputMemoryStreamTest.cs @@ -174,7 +174,7 @@ public sealed class HttpFixture : IAsyncLifetime private readonly IContainer _container = new ContainerBuilder() .WithImage(CommonImages.Alpine) .WithEntrypoint("/bin/sh", "-c") - .WithCommand($"while true; do echo \"HTTP/1.1 200 OK\r\n\" | nc -l -p {HttpPort}; done") + .WithCommand($"while true; do echo \"HTTP/1.1 200 OK\r\n\r\n\" | nc -l -p {HttpPort}; done") .WithPortBinding(HttpPort, true) .Build(); diff --git a/tests/Testcontainers.Tests/Unit/Configurations/WaitUntilHttpRequestIsSucceededTest.cs b/tests/Testcontainers.Tests/Unit/Configurations/WaitUntilHttpRequestIsSucceededTest.cs index 691211f2f..654457be3 100644 --- a/tests/Testcontainers.Tests/Unit/Configurations/WaitUntilHttpRequestIsSucceededTest.cs +++ b/tests/Testcontainers.Tests/Unit/Configurations/WaitUntilHttpRequestIsSucceededTest.cs @@ -19,7 +19,7 @@ public sealed class WaitUntilHttpRequestIsSucceededTest : IAsyncLifetime private readonly IContainer _container = new ContainerBuilder() .WithImage(CommonImages.Alpine) .WithEntrypoint("/bin/sh", "-c") - .WithCommand($"while true; do echo \"HTTP/1.1 200 OK\r\n\" | nc -l -p {HttpPort}; done") + .WithCommand($"while true; do echo \"HTTP/1.1 200 OK\r\n\r\n\" | nc -l -p {HttpPort}; done") .WithPortBinding(HttpPort, true) .Build();