Skip to content

[Feature]: Add differ extensibility for MSTest assertions #6771

@Youssef1313

Description

@Youssef1313

Summary

One current issue for assertions is the level of clarity of error messages. There is probably no one solution that fits all scenarios.

Background and Motivation

We should aim for a good experience when a test fails. For that, a degree of extensibility might be best.

Proposed Feature

public sealed class Assert
{
+    public void AddExtension(IAssertDiffExtension assertDiffExtension);
}

+ public interface IAssertDiffExtension
+ {
+     // TODO: Should this take the original objects instead?
+     bool IsSupported(Type typeOfExpected, Type typeOfActual);
+     string Diff(object expected, object actual);
+ }

Multiple extensions can be added during AssemblyInitialize. When an assert fails and wants to diff two objects, we will loop over all registered diff extensions (in reverse order). The first found extension that returns true from IsSupported will be used (which is the last registered because we loop in reverse order - more on the motivation of reverse ordering later in the proposal).

  • This allows differs to be implemented outside of MSTest.TestFramework, as separate packages. There can be some provided by us, and others provided by the community.
    • One example is using DiffPlex here, potentially with different options that users can configure. For example, users who knows they have lots of multi-line string comparisons can install a differ that plays more nice with that, etc.
  • Having the extensibility here allows TestFramework to not require additional dependencies (e.g, DiffPlex). The additional dependency is installed only when user explicitly wants the DiffPlex differ extension.
  • The actual storage of the extensions can be an async local.
    • When installing in AssemblyInitialize, it makes it available to all tests.
    • Two different test classes can be running in parallel, and each test class could install a different differ because of the nature of the tests in those specific test classes.
    • That is why the "last registered" wins rule. If I install a differ in AssemblyInitialize (registered first), I want it to apply it everywhere. If later I installed one in ClassInitialize, I want that to be "more specific" and win.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: MSTestIssues with MSTest that are not specific to more refined area (e.g. analyzers or assertions)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions