Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jun 11, 2025

This PR adds support for handling AggregateException in Xunit.SkippableFact. When a test throws an AggregateException containing skip exceptions, the test will now be properly skipped instead of failing.

Problem

Previously, tests that threw AggregateException containing skip exceptions would fail instead of being skipped:

[SkippableFact]
public void TestWithAggregateException()
{
    var skipException = new SkipException("Should skip this test");
    var otherException = new InvalidOperationException("Some error");
    var aggregateException = new AggregateException(skipException, otherException);
    throw aggregateException; // Would FAIL instead of SKIP
}

This was particularly problematic when using Task.WhenAll or similar patterns that aggregate multiple exceptions, where one of the exceptions was a skip condition.

Solution

The implementation adds a new case to SkippableTestMessageBus.QueueMessage() that:

  1. Detects when the outer exception is System.AggregateException
  2. Iterates through the inner exceptions within the aggregate
  3. If any inner exception matches a configured skip exception type, skips the test
  4. Uses the message from the first matching skip exception as the skip reason

Examples

All of these scenarios now work correctly:

// Single skip exception in aggregate - SKIPPED
[SkippableFact]
public void SingleSkipInAggregate()
{
    var aggregate = new AggregateException(new SkipException("Reason"));
    throw aggregate;
}

// Mixed exceptions with skip - SKIPPED (skip takes precedence)
[SkippableFact] 
public void MixedExceptionsWithSkip()
{
    var skip = new SkipException("Skip reason");
    var error = new InvalidOperationException("Error");
    throw new AggregateException(skip, error);
}

// Custom skip exception types - SKIPPED
[SkippableFact(typeof(NotImplementedException))]
public void CustomSkipType()
{
    var skip = new NotImplementedException("Not implemented");
    var error = new ArgumentException("Invalid arg");
    throw new AggregateException(skip, error);
}

// No skip exceptions - FAILED (as expected)
[SkippableFact]
public void NoSkipExceptions()
{
    var error1 = new InvalidOperationException("Error 1");
    var error2 = new ArgumentException("Error 2");
    throw new AggregateException(error1, error2); // Still fails
}

Implementation Details

  • Minimal changes: Only 13 lines added to core implementation
  • Consistent pattern: Follows existing ThrowsException handling approach
  • Backward compatible: All existing functionality preserved
  • Comprehensive tests: Added 7 test cases covering various scenarios including nested aggregates

The implementation follows the requirement to skip if ANY inner exception is a skip exception (not requiring ALL to be skip exceptions), which aligns with typical test failure scenarios.

Fixes #31.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 2 commits June 11, 2025 20:34
Co-authored-by: AArnott <3548+AArnott@users.noreply.github.com>
Co-authored-by: AArnott <3548+AArnott@users.noreply.github.com>
Copilot AI changed the title [WIP] Support AggregateExceptions? Add support for AggregateException in SkippableFact Jun 11, 2025
Copilot AI requested a review from AArnott June 11, 2025 20:37
@AArnott AArnott marked this pull request as ready for review June 11, 2025 23:05
@AArnott AArnott enabled auto-merge (squash) June 11, 2025 23:06
@AArnott AArnott merged commit 4678496 into main Jun 11, 2025
5 checks passed
@AArnott AArnott deleted the copilot/fix-31 branch June 11, 2025 23:07
CurtHagenlocher pushed a commit to apache/arrow-dotnet that referenced this pull request Dec 29, 2025
Updated
[Xunit.SkippableFact](https://github.com/AArnott/Xunit.SkippableFact)
from 1.5.23 to 1.5.61.

<details>
<summary>Release notes</summary>

_Sourced from [Xunit.SkippableFact's
releases](https://github.com/AArnott/Xunit.SkippableFact/releases)._

## 1.5.61

## What's Changed
* Document support for class-level OS targeting by @​AArnott in
AArnott/Xunit.SkippableFact#50
* Add support for AggregateException in SkippableFact by @​Copilot in
AArnott/Xunit.SkippableFact#80
* Fix wrong failed state for rider by @​JKamsker in
AArnott/Xunit.SkippableFact#105

## New Contributors
* @​renovate[bot] made their first contribution in
AArnott/Xunit.SkippableFact#64
* @​github-actions[bot] made their first contribution in
AArnott/Xunit.SkippableFact#72
* @​Copilot made their first contribution in
AArnott/Xunit.SkippableFact#80
* @​JKamsker made their first contribution in
AArnott/Xunit.SkippableFact#105

**Full Changelog**:
AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61

Commits viewable in [compare
view](AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Xunit.SkippableFact&package-manager=nuget&previous-version=1.5.23&new-version=1.5.61)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
github-merge-queue bot pushed a commit to microsoft/typechat.net that referenced this pull request Dec 29, 2025
Updated
[Xunit.SkippableFact](https://github.com/AArnott/Xunit.SkippableFact)
from 1.5.23 to 1.5.61.

<details>
<summary>Release notes</summary>

_Sourced from [Xunit.SkippableFact's
releases](https://github.com/AArnott/Xunit.SkippableFact/releases)._

## 1.5.61

## What's Changed
* Document support for class-level OS targeting by @​AArnott in
AArnott/Xunit.SkippableFact#50
* Add support for AggregateException in SkippableFact by @​Copilot in
AArnott/Xunit.SkippableFact#80
* Fix wrong failed state for rider by @​JKamsker in
AArnott/Xunit.SkippableFact#105

## New Contributors
* @​renovate[bot] made their first contribution in
AArnott/Xunit.SkippableFact#64
* @​github-actions[bot] made their first contribution in
AArnott/Xunit.SkippableFact#72
* @​Copilot made their first contribution in
AArnott/Xunit.SkippableFact#80
* @​JKamsker made their first contribution in
AArnott/Xunit.SkippableFact#105

**Full Changelog**:
AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61

Commits viewable in [compare
view](AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Xunit.SkippableFact&package-manager=nuget&previous-version=1.5.23&new-version=1.5.61)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
CurtHagenlocher pushed a commit to apache/arrow-adbc that referenced this pull request Jan 2, 2026
Updated
[Xunit.SkippableFact](https://github.com/AArnott/Xunit.SkippableFact)
from 1.5.23 to 1.5.61.

<details>
<summary>Release notes</summary>

_Sourced from [Xunit.SkippableFact's
releases](https://github.com/AArnott/Xunit.SkippableFact/releases)._

## 1.5.61

## What's Changed
* Document support for class-level OS targeting by @​AArnott in
AArnott/Xunit.SkippableFact#50
* Add support for AggregateException in SkippableFact by @​Copilot in
AArnott/Xunit.SkippableFact#80
* Fix wrong failed state for rider by @​JKamsker in
AArnott/Xunit.SkippableFact#105

## New Contributors
* @​renovate[bot] made their first contribution in
AArnott/Xunit.SkippableFact#64
* @​github-actions[bot] made their first contribution in
AArnott/Xunit.SkippableFact#72
* @​Copilot made their first contribution in
AArnott/Xunit.SkippableFact#80
* @​JKamsker made their first contribution in
AArnott/Xunit.SkippableFact#105

**Full Changelog**:
AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61

Commits viewable in [compare
view](AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Xunit.SkippableFact&package-manager=nuget&previous-version=1.5.23&new-version=1.5.61)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
CurtHagenlocher pushed a commit to adbc-drivers/bigquery that referenced this pull request Jan 2, 2026
Updated
[Xunit.SkippableFact](https://github.com/AArnott/Xunit.SkippableFact)
from 1.5.23 to 1.5.61.

<details>
<summary>Release notes</summary>

_Sourced from [Xunit.SkippableFact's
releases](https://github.com/AArnott/Xunit.SkippableFact/releases)._

## 1.5.61

## What's Changed
* Document support for class-level OS targeting by @​AArnott in
AArnott/Xunit.SkippableFact#50
* Add support for AggregateException in SkippableFact by @​Copilot in
AArnott/Xunit.SkippableFact#80
* Fix wrong failed state for rider by @​JKamsker in
AArnott/Xunit.SkippableFact#105

## New Contributors
* @​renovate[bot] made their first contribution in
AArnott/Xunit.SkippableFact#64
* @​github-actions[bot] made their first contribution in
AArnott/Xunit.SkippableFact#72
* @​Copilot made their first contribution in
AArnott/Xunit.SkippableFact#80
* @​JKamsker made their first contribution in
AArnott/Xunit.SkippableFact#105

**Full Changelog**:
AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61

Commits viewable in [compare
view](AArnott/Xunit.SkippableFact@v1.5.23...v1.5.61).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Xunit.SkippableFact&package-manager=nuget&previous-version=1.5.23&new-version=1.5.61)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support AggregateExceptions?

2 participants