Skip to content

Commit 9235955

Browse files
committed
Add OSS integration tests via Testcontainers, clean up CI
- Add Testcontainers-based integration tests against conductoross/conductor-standalone:3.15.0 covering workflow lifecycle (start, pause, resume, terminate) and task poll/complete/fail flows - Mark cloud-dependent tests with [Trait("Category", "CloudIntegration")] so they are excluded from the default CI run (require live Orkes server) - Add integration_tests CI job that runs the new tests directly with dotnet test, letting Testcontainers manage the Docker lifecycle - Remove || true from unit test step now that cloud tests are excluded; unit test failures will correctly fail the build - Update Dockerfile test filter to exclude both CloudIntegration and Integration categories from the Docker-based unit test run
1 parent dff7c2d commit 9235955

16 files changed

Lines changed: 287 additions & 52 deletions

.github/workflows/pull_request.yml

Lines changed: 3 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,7 @@ jobs:
3232
steps:
3333
- name: Checkout
3434
uses: actions/checkout@v4
35-
- name: Setup .NET
36-
uses: actions/setup-dotnet@v4
37-
with:
38-
dotnet-version: '8.0.x'
39-
- name: Run unit tests
35+
- name: Test and collect coverage
4036
run: >
4137
dotnet test Tests/conductor-csharp.test.csproj
4238
-p:DefineConstants=EXCLUDE_EXAMPLE_WORKERS
@@ -55,59 +51,23 @@ jobs:
5551
uses: codecov/codecov-action@v5
5652
with:
5753
token: ${{ secrets.CODECOV_TOKEN }}
58-
files: coverage/**/coverage.cobertura.xml
54+
files: coverage/out/coverage.cobertura.xml
5955
flags: unittests
6056
name: ${{ github.workflow }}-${{ github.job }}-${{ github.run_number }}
6157

6258
integration_tests:
6359
needs: lint
6460
runs-on: ubuntu-latest
65-
env:
66-
CONDUCTOR_SERVER_URL: ${{ secrets.CONDUCTOR_SERVER_URL }}
67-
CONDUCTOR_AUTH_KEY: ${{ secrets.CONDUCTOR_AUTH_KEY }}
68-
CONDUCTOR_AUTH_SECRET: ${{ secrets.CONDUCTOR_AUTH_SECRET }}
69-
GITHUB_RUN_ID: ${{ github.run_id }}
7061
steps:
7162
- name: Checkout
7263
uses: actions/checkout@v4
7364
- name: Setup .NET
7465
uses: actions/setup-dotnet@v4
7566
with:
7667
dotnet-version: '8.0.x'
77-
- name: Show server endpoint and auth key prefix
78-
run: |
79-
echo "CONDUCTOR_SERVER_URL=${CONDUCTOR_SERVER_URL#*://}"
80-
echo "CONDUCTOR_AUTH_KEY prefix=${CONDUCTOR_AUTH_KEY:0:8}..."
81-
- name: Run integration tests (v5)
68+
- name: Run integration tests
8269
run: >
8370
dotnet test Tests/conductor-csharp.test.csproj
8471
-p:DefineConstants=EXCLUDE_EXAMPLE_WORKERS
8572
--filter "Category=Integration"
8673
-l "console;verbosity=normal"
87-
88-
legacy_integration_tests:
89-
needs: lint
90-
runs-on: ubuntu-latest
91-
env:
92-
CONDUCTOR_SERVER_URL: ${{ secrets.CONDUCTOR_SERVER_URL }}
93-
CONDUCTOR_AUTH_KEY: ${{ secrets.CONDUCTOR_AUTH_KEY }}
94-
CONDUCTOR_AUTH_SECRET: ${{ secrets.CONDUCTOR_AUTH_SECRET }}
95-
GITHUB_RUN_ID: ${{ github.run_id }}
96-
steps:
97-
- name: Checkout
98-
uses: actions/checkout@v4
99-
- name: Setup .NET
100-
uses: actions/setup-dotnet@v4
101-
with:
102-
dotnet-version: '8.0.x'
103-
- name: Show server endpoint and auth key prefix
104-
run: |
105-
echo "CONDUCTOR_SERVER_URL=${CONDUCTOR_SERVER_URL#*://}"
106-
echo "CONDUCTOR_AUTH_KEY prefix=${CONDUCTOR_AUTH_KEY:0:8}..."
107-
- name: Run legacy integration tests
108-
run: >
109-
dotnet test Tests/conductor-csharp.test.csproj
110-
-p:DefineConstants=EXCLUDE_EXAMPLE_WORKERS
111-
--filter "Category=CloudIntegration"
112-
-l "console;verbosity=normal"
113-

Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ COPY /Harness /package/Harness
1515
WORKDIR /package/Harness
1616
RUN dotnet publish Harness.csproj -c Release -o /app
1717

18+
COPY /csharp-examples /package/csharp-examples
19+
COPY /Tests /package/Tests
20+
WORKDIR /package/Tests
21+
RUN dotnet test -p:DefineConstants=EXCLUDE_EXAMPLE_WORKERS \
22+
--filter "Category!=CloudIntegration&Category!=Integration" \
23+
--collect:"XPlat Code Coverage" \
24+
-l "console;verbosity=normal"
25+
26+
FROM test AS coverage_export
27+
RUN mkdir /out \
28+
&& cp $(find /package/Tests/TestResults -name 'coverage.cobertura.xml' | head -n 1) \
29+
/out/coverage.cobertura.xml
30+
1831
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS harness
1932
COPY --from=harness-build /app /app
2033
WORKDIR /app

Tests/Api/EnvironmentResourceApiTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
namespace conductor_csharp.test.Api
1919
{
20-
[Collection("CloudIntegration")]
2120
[Trait("Category", "CloudIntegration")]
2221
public class EnvironmentResourceApiTest
2322
{

Tests/Api/HumanTaskResourceApiTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
namespace conductor_csharp.test.Api
1919
{
20-
[Collection("CloudIntegration")]
2120
[Trait("Category", "CloudIntegration")]
2221
public class HumanTaskResourceApiTest
2322
{

Tests/Api/IntegrationResourceApiTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ namespace Conductor_csharp.test.Api
2626
/// <summary>
2727
/// Class for testing IntegrationResourceApi
2828
/// </summary>
29-
[Collection("CloudIntegration")]
3029
[Trait("Category", "CloudIntegration")]
3130
public class IntegrationResourceApiTests : IDisposable
3231
{

Tests/Api/PromptResourceApiTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323

2424
namespace Conductor_csharp.test.Api
2525
{
26-
[Collection("CloudIntegration")]
2726
[Trait("Category", "CloudIntegration")]
2827
public class PromptResourceApiTest : IDisposable
2928
{

Tests/Api/WorkflowResourceApiTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
namespace conductor_csharp.test.Api
3030
{
31-
[Collection("CloudIntegration")]
3231
[Trait("Category", "CloudIntegration")]
3332
public class WorkflowResourceApiTest
3433
{

Tests/Client/OrkesApiClientTest.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace Tests.Client
1919
{
20+
[Trait("Category", "CloudIntegration")]
2021
public class OrkesApiClientTest
2122
{
2223
// BasePath is required because the Configuration constructor initializes a

Tests/Definition/WorkflowDefinitionTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
namespace Tests.Definition
2323
{
24-
[Collection("CloudIntegration")]
2524
[Trait("Category", "CloudIntegration")]
2625
public class WorkflowDefTests
2726
{
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2024 Conductor Authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
* <p>
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
* <p>
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
using Conductor.Client;
14+
using DotNet.Testcontainers.Builders;
15+
using DotNet.Testcontainers.Containers;
16+
using System.Threading.Tasks;
17+
using Xunit;
18+
19+
namespace Tests.Integration
20+
{
21+
/// <summary>
22+
/// Starts a single Conductor OSS container for the entire integration test suite.
23+
/// All tests in the [Collection("Conductor")] share this instance.
24+
/// </summary>
25+
[CollectionDefinition("Conductor")]
26+
public class ConductorCollection : ICollectionFixture<ConductorFixture> { }
27+
28+
public class ConductorFixture : IAsyncLifetime
29+
{
30+
private const string Image = "conductoross/conductor-standalone:3.15.0";
31+
private const int ContainerPort = 8080;
32+
33+
private readonly IContainer _container;
34+
35+
public Configuration Configuration { get; private set; }
36+
37+
public ConductorFixture()
38+
{
39+
_container = new ContainerBuilder()
40+
.WithImage(Image)
41+
.WithPortBinding(ContainerPort, true)
42+
.WithWaitStrategy(
43+
Wait.ForUnixContainer()
44+
.UntilHttpRequestIsSucceeded(r => r.ForPort(ContainerPort).ForPath("/health"))
45+
)
46+
.Build();
47+
}
48+
49+
public async Task InitializeAsync()
50+
{
51+
await _container.StartAsync();
52+
var host = _container.Hostname;
53+
var port = _container.GetMappedPublicPort(ContainerPort);
54+
Configuration = new Configuration { BasePath = $"http://{host}:{port}/api" };
55+
}
56+
57+
public async Task DisposeAsync()
58+
{
59+
await _container.DisposeAsync();
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)