diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 01e1194..3ba3486 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -27,8 +27,9 @@ jobs:
- name: Build
run: dotnet build --configuration Release --no-restore
+ # Integration tests call the public services.odata.org sample services and are run locally, never in CI.
- name: Test
- run: dotnet test --configuration Release --no-build --verbosity normal
+ run: dotnet test --configuration Release --no-build --verbosity normal --filter-not-trait "Category=Integration"
- name: Pack
run: dotnet pack --configuration Release --no-build --output ./artifacts
@@ -84,6 +85,7 @@ jobs:
--coverage-settings PanoramicData.OData.Client.Test/coverage.config
--coverage-output-format cobertura
--coverage-output coverage.cobertura.xml
+ --filter-not-trait "Category=Integration"
# continue-on-error: a Codacy outage must not turn a passing test run red. The
# trade-off is that an expired or missing project token fails silently, so
diff --git a/PanoramicData.OData.Client.Test/IntegrationTests/CrudIntegrationTests.cs b/PanoramicData.OData.Client.Test/IntegrationTests/CrudIntegrationTests.cs
index 1ff372c..ca57fbe 100644
--- a/PanoramicData.OData.Client.Test/IntegrationTests/CrudIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/IntegrationTests/CrudIntegrationTests.cs
@@ -7,6 +7,7 @@ namespace PanoramicData.OData.Client.Test.IntegrationTests;
/// Uses the TripPin read-write sample service which provides a unique session per request.
/// Note: The TripPin service has specific behavior - entities may not persist across calls.
///
+[Trait("Category", "Integration")]
public class CrudIntegrationTests : TestBase, IAsyncLifetime
{
private ServiceProvider? _serviceProvider;
diff --git a/PanoramicData.OData.Client.Test/IntegrationTests/FluentApiIntegrationTests.cs b/PanoramicData.OData.Client.Test/IntegrationTests/FluentApiIntegrationTests.cs
index 7d14303..e36c612 100644
--- a/PanoramicData.OData.Client.Test/IntegrationTests/FluentApiIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/IntegrationTests/FluentApiIntegrationTests.cs
@@ -10,6 +10,7 @@ namespace PanoramicData.OData.Client.Test.IntegrationTests;
///
/// Initializes a new instance of the test class.
///
+[Trait("Category", "Integration")]
public class FluentApiIntegrationTests(ODataClientFixture fixture) : TestBase, IClassFixture
{
diff --git a/PanoramicData.OData.Client.Test/IntegrationTests/MetadataIntegrationTests.cs b/PanoramicData.OData.Client.Test/IntegrationTests/MetadataIntegrationTests.cs
index e497d12..7b68421 100644
--- a/PanoramicData.OData.Client.Test/IntegrationTests/MetadataIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/IntegrationTests/MetadataIntegrationTests.cs
@@ -9,6 +9,7 @@ namespace PanoramicData.OData.Client.Test.IntegrationTests;
///
/// Initializes a new instance of the test class.
///
+[Trait("Category", "Integration")]
public class MetadataIntegrationTests(ODataClientFixture fixture) : TestBase, IClassFixture
{
diff --git a/PanoramicData.OData.Client.Test/IntegrationTests/PaginationIntegrationTests.cs b/PanoramicData.OData.Client.Test/IntegrationTests/PaginationIntegrationTests.cs
index 7dfa605..6b65bcc 100644
--- a/PanoramicData.OData.Client.Test/IntegrationTests/PaginationIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/IntegrationTests/PaginationIntegrationTests.cs
@@ -9,6 +9,7 @@ namespace PanoramicData.OData.Client.Test.IntegrationTests;
///
/// Initializes a new instance of the test class.
///
+[Trait("Category", "Integration")]
public class PaginationIntegrationTests(ODataClientFixture fixture) : TestBase, IClassFixture
{
diff --git a/PanoramicData.OData.Client.Test/IntegrationTests/QueryOptionsIntegrationTests.cs b/PanoramicData.OData.Client.Test/IntegrationTests/QueryOptionsIntegrationTests.cs
index b0422d3..df13a2a 100644
--- a/PanoramicData.OData.Client.Test/IntegrationTests/QueryOptionsIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/IntegrationTests/QueryOptionsIntegrationTests.cs
@@ -6,6 +6,7 @@ namespace PanoramicData.OData.Client.Test.IntegrationTests;
/// Integration tests for OData V4 query options using the public sample service.
/// Tests $filter, $select, $expand, $orderby, $top, $skip, $count, $search.
///
+[Trait("Category", "Integration")]
public class QueryOptionsIntegrationTests : TestBase, IClassFixture
{
private readonly ODataClientFixture _fixture;
diff --git a/PanoramicData.OData.Client.Test/IntegrationTests/RawQueryIntegrationTests.cs b/PanoramicData.OData.Client.Test/IntegrationTests/RawQueryIntegrationTests.cs
index 2e6b67d..b65d59f 100644
--- a/PanoramicData.OData.Client.Test/IntegrationTests/RawQueryIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/IntegrationTests/RawQueryIntegrationTests.cs
@@ -10,6 +10,7 @@ namespace PanoramicData.OData.Client.Test.IntegrationTests;
///
/// Initializes a new instance of the test class.
///
+[Trait("Category", "Integration")]
public class RawQueryIntegrationTests(ODataClientFixture fixture) : TestBase, IClassFixture
{
diff --git a/PanoramicData.OData.Client.Test/IntegrationTests/TripPinIntegrationTests.cs b/PanoramicData.OData.Client.Test/IntegrationTests/TripPinIntegrationTests.cs
index 04e7ee3..b84260a 100644
--- a/PanoramicData.OData.Client.Test/IntegrationTests/TripPinIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/IntegrationTests/TripPinIntegrationTests.cs
@@ -6,6 +6,7 @@ namespace PanoramicData.OData.Client.Test.IntegrationTests;
/// Integration tests using the TripPin sample service for advanced OData V4 scenarios.
/// TripPin provides more complex entity relationships and features.
///
+[Trait("Category", "Integration")]
public class TripPinIntegrationTests : TestBase, IAsyncLifetime
{
private ServiceProvider? _serviceProvider;
diff --git a/PanoramicData.OData.Client.Test/ODataClientIntegrationTests.cs b/PanoramicData.OData.Client.Test/ODataClientIntegrationTests.cs
index 71086df..7e9962d 100644
--- a/PanoramicData.OData.Client.Test/ODataClientIntegrationTests.cs
+++ b/PanoramicData.OData.Client.Test/ODataClientIntegrationTests.cs
@@ -13,6 +13,7 @@ namespace PanoramicData.OData.Client.Test;
/// Initializes a new instance of the class.
///
/// The OData client fixture providing a configured client instance.
+[Trait("Category", "Integration")]
public class ODataClientIntegrationTests(ODataClientFixture fixture) : TestBase, IClassFixture
{