Skip to content

Add FrameworkConditionAttribute for conditional test execution based on .NET framework #6071

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jul 16, 2025

Summary

This PR implements FrameworkConditionAttribute, a new condition attribute that enables conditional test execution based on the .NET framework version. This provides a cleaner alternative to preprocessor directives (#if NET8_0_OR_GREATER, etc.) in test scenarios.

Problem

Currently, developers need to use preprocessor directives to conditionally compile tests for different .NET frameworks:

[TestClass]
public class MyTests
{
#if NET8_0_OR_GREATER
    [TestMethod]
    public void TestAvailableOnlyOnNet8OrGreater()
    {
        // Test code for .NET 8+ features
    }
#endif

#if !NETFRAMEWORK
    [TestMethod]
    public void TestNotAvailableOnNetFramework()
    {
        // Test code that doesn't work on .NET Framework
    }
#endif
}

This approach has several drawbacks:

  • Code is harder to read and maintain
  • IDE IntelliSense doesn't work correctly across all target frameworks
  • Tests are conditionally compiled rather than conditionally executed

Solution

The new FrameworkConditionAttribute follows the same pattern as CIConditionAttribute and OSConditionAttribute, enabling runtime conditional test execution:

[TestClass]
public class MyTests
{
    [TestMethod]
    [FrameworkCondition(Frameworks.Net8OrGreater)]
    public void TestAvailableOnlyOnNet8OrGreater()
    {
        // Test code for .NET 8+ features
    }

    [TestMethod]
    [FrameworkCondition(ConditionMode.Exclude, Frameworks.NetFramework)]
    public void TestNotAvailableOnNetFramework()
    {
        // Test code that doesn't work on .NET Framework
    }

    [TestMethod]
    [FrameworkCondition(Frameworks.NetCore | Frameworks.Net)]
    public void TestOnCoreOrNet()
    {
        // Test runs on .NET Core or .NET 5+, but not .NET Framework
    }
}

Implementation Details

New Types Added

  1. Frameworks enum - Flags enum supporting:

    • NetFramework - .NET Framework
    • NetCore - .NET Core 1.x, 2.x, 3.x
    • Net - .NET 5 and later
    • Net6OrGreater - .NET 6+
    • Net7OrGreater - .NET 7+
    • Net8OrGreater - .NET 8+
    • Net9OrGreater - .NET 9+
  2. FrameworkConditionAttribute - Condition attribute that:

    • Extends ConditionBaseAttribute
    • Supports both Include and Exclude modes
    • Uses RuntimeInformation.FrameworkDescription and Environment.Version for detection
    • Provides descriptive ignore messages

Framework Detection Logic

  • Uses RuntimeInformation.FrameworkDescription to identify framework type
  • Uses Environment.Version for version-specific detection
  • Version flags are cumulative (e.g., .NET 8 gets Net, Net6OrGreater, Net7OrGreater, Net8OrGreater)
  • Handles edge cases gracefully (unknown frameworks default to Net)

Test Coverage

Comprehensive test suite covering:

  • Constructor behavior and mode handling
  • Framework detection accuracy
  • Include/exclude mode logic
  • Multiple framework combinations
  • Edge cases and version boundaries

Benefits

  1. Cleaner code - No preprocessor directives cluttering test methods
  2. Better IDE support - IntelliSense works correctly across all target frameworks
  3. Runtime execution - Tests are compiled for all frameworks but conditionally executed
  4. Consistent pattern - Follows established ConditionBaseAttribute conventions
  5. Descriptive output - Skipped tests show clear messages about framework requirements
  6. Flexible combinations - Support for complex framework combinations using flags

Files Changed

  • Added Frameworks.cs - Framework enumeration
  • Added FrameworkConditionAttribute.cs - Main attribute implementation
  • Added FrameworkConditionAttributeTests.cs - Comprehensive test suite
  • Updated PublicAPI.Unshipped.txt - Added public API entries

Fixes #6070.


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

@Copilot Copilot AI changed the title [WIP] Add FrameworkConditionAttribute Add FrameworkConditionAttribute for conditional test execution based on .NET framework Jul 16, 2025
@Copilot Copilot AI requested a review from Evangelink July 16, 2025 14:14
Copilot finished work on behalf of Evangelink July 16, 2025 14:14

// Check for .NET 5+
if (frameworkDescription.StartsWith(".NET ", StringComparison.OrdinalIgnoreCase) ||
frameworkDescription.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're absolutely right. The check for ".NET Core" in line 82 was redundant since that case is already handled by the check on lines 75-78 which would return early. I've removed the redundant condition. Fixed in commit 4fe0d32.

/// <summary>
/// Represents .NET 5 and later versions (unified platform).
/// </summary>
Net = 1 << 2,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is confusing. This one will be net5.0 only per the current implementation. I'm also not sure if it's good to add the versions to this enum:

  1. We will have to drop entries from the enum when we are dropping support for old target frameworks.
  2. If .NET 10 is used with an MSTest version that doesn't have an enum entry for .NET 10, what the behavior will be?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're absolutely right about both concerns. I've simplified the Frameworks enum to address these issues:

  1. Removed version-specific flags: Eliminated Net6OrGreater, Net7OrGreater, Net8OrGreater, and Net9OrGreater
  2. Kept only basic framework types: NetFramework, NetCore, and Net (for .NET 5+)

This design is much cleaner and follows the same pattern as OperatingSystems enum. The Net flag now covers all .NET 5+ versions (5, 6, 7, 8, 9, etc.) without requiring new enum entries for each version. If users need version-specific logic, they can check Environment.Version in their test code.

Benefits:

  • No maintenance burden of adding/removing version flags
  • Forward compatibility (new .NET versions automatically work)
  • Simpler, less confusing API
  • Consistent with existing condition attribute patterns

Fixed in commit f3fa939.

@Copilot Copilot AI requested a review from Youssef1313 July 22, 2025 07:42
Copilot finished work on behalf of Youssef1313 July 22, 2025 07:42
Copy link
Member

@Youssef1313 Youssef1313 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to be revisited for UWP.

@Copilot Copilot AI requested a review from Youssef1313 July 22, 2025 07:53
Copilot finished work on behalf of Youssef1313 July 22, 2025 07:53
Copy link
Contributor Author

Copilot AI commented Jul 22, 2025

This also needs to be revisited for UWP.

Added UWP support to the FrameworkConditionAttribute. The implementation includes a new Uwp enum value and reliable UWP detection using Windows.ApplicationModel.Package.Current availability check. The UWP detection runs first in the framework detection logic to handle cases where UWP apps might have .NET Core or .NET in their framework descriptions. Comprehensive test coverage has been added for UWP scenarios. Fixed in commit af23749.

Copilot finished work on behalf of Youssef1313 July 22, 2025 08:08
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.

Add FrameworkConditionAttribute
3 participants