Skip to content

maximedezette/fluentassertions-to-nfluent-migrator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FluentAssertions to NFluent Migrator

Hits

A simple command-line tool for migrating your code from FluentAssertions to NFluent. This tool automatically updates all using directives and assertion statements in your C# project files (.cs and .csproj files) to use NFluent syntax instead of FluentAssertions.

Features

  • Replaces using FluentAssertions with using NFluent.
  • Converts FluentAssertions assertions to equivalent NFluent assertions (e.g., .Should().Be().IsEqualTo()).
  • Supports .cs and .csproj files.
  • Process multiple files in a directory and subdirectories.

how_to_part_1

Example Usage

demo

Example migrating a project with thousands of tests (french version)

demo

⚠️ As of today, not all assertions are fully supported by the tool, and some manual transformations are likely to be required. However, it significantly eases the migration process by automating many common cases.

See the section about the supported assertions for more details.

Installation

Prerequisites

  • .NET 6.0+ SDK
  • C# development environment (e.g., Visual Studio, Rider, or Visual Studio Code)

Usage

Run the Tool

Once the project is built, you can use the tool by running the compiled executable from the command line.

  1. Clone the repository:

    git clone https://github.com/yourusername/fluentassertions-to-nfluent-migrator.git
    cd fluentassertions-to-nfluent-migrator
  2. Build the project using the .NET CLI:

    dotnet build -o ./output    

Command Format

.\output\Migrator.exe <path-to-directory>

Where is the path to the directory containing the C# project files (.cs and .csproj). The tool will process all matching files in the specified directory and its subdirectories.

Expected Output

While the tool runs, you'll see a message indicating the progress of the replacement, along with a spinner:

Replacement started
Processing .cs files...
Processing SomeFile.cs...|
Processing AnotherFile.cs.../
Processing YetAnotherFile.cs...-
...
Replacement complete.

Once the replacement is complete, it will output:

Replacement complete.

File Types Processed

.cs: C# source files containing FluentAssertions assertions.
.csproj: Project files that may include references to FluentAssertions.

File Content Changes

  • All occurrences of using FluentAssertions are replaced with using NFluent.
  • Assertions using FluentAssertions methods (e.g., .Should().Be(...)) are updated to the equivalent NFluent assertion (e.g., .IsEqualTo(...)).

Example Changes

Before:

using FluentAssertions;

public void Test()
{
    var myObject = new MyClass();
    myObject.Should().Be(expectedObject);
}

After:

using NFluent;

public void Test()
{
    var myObject = new MyClass();
    Check.That(myObject).IsEqualTo(expectedObject);
}

Customizing the Tool

You can customize or extend the tool's functionality by modifying the following classes:

  • CsFileContentReplacer: Contains the logic for replacing assertions in .cs files.
  • CsProjFileContentReplacer: Contains the logic for replacing content in .csproj files (e.g., using FluentAssertions).
  • Program: The entry point of the tool where file processing and updates are triggered.

Known Issues

Complex Expressions: In cases where assertions are deeply nested or formatted irregularly, the tool may not fully capture the exact syntax. You may need to review the resulting code to ensure correctness.

This tool is under development, some FluentAssertions assertions may not be correctly replaced yet.

Contributions

Feel free to fork this repository and submit pull requests for any features or fixes you think are useful!

It's a very simple project, here is how you can add a transformation:

  • Write a unit test like the following:
  [Fact]
  public void Should_replace_ShouldBeTrue()
  {
  const string fluentAssertions = "var.Should().BeTrue();";
  const string nfluentEquivalent = "Check.That(var).IsTrue();";

        var actual = CsFileContentReplacer.Replace(fluentAssertions);
        
        Check.That(actual).IsEqualTo(nfluentEquivalent);
  }

Add the regex to the CsFileContentReplacer.cs to make the test pass:

// .Should().BeTrue() -> Check.That(var).IsTrue();
(@"(?<subject>\S(?:.*\S)?)\s*\.Should\(\)\s*\.BeTrue\s*\(\s*\)\s*;", "Check.That(${subject}).IsTrue();"),

And that's it!

If you never contributed to an open source project yet, It is a good opportunity to try because this project is very simple.

Here is a simple guide that demonstrate how to make a contribution for the first time.

If you have doubts, need help or anything do not hesitate to ask your questions in an issue, we will gladly provide all the help we can 😊

FluentAssertions to NFluent Migration Support

This document provides an overview of the migration support offered by the CsFileContentReplacer for transitioning from FluentAssertions to NFluent in C# projects. While the tool automates the replacement of many common assertions, there are limitations, and some manual adjustments may be necessary.

Supported Transformations

The following FluentAssertions methods are currently supported and are automatically replaced by their NFluent equivalents:

General Assertions

FluentAssertions NFluent
.Should().NotBeNull() Check.That(var).IsNotNull();
.Should().BeNull() Check.That(var).IsNull();
.Should().Be(value) Check.That(var).IsEqualTo(value);
.Should().NotBe(value) Check.That(var).IsNotEqualTo(value);
.Should().BeGreaterThan(value) Check.That(var).IsGreaterThan(value);
.Should().BeGreaterOrEqualTo(value) Check.That(var).IsGreaterOrEqualTo(value);
.Should().BeLessThan(value) Check.That(var).IsLessThan(value);
.Should().BeLessOrEqualTo(value) Check.That(var).IsLessOrEqualTo(value);
.Should().BeEquivalentTo(object) Check.That(var).HasFieldsWithSameValues(object);
.Should().Contain(value) Check.That(var).Contains(value);
.Should().NotContain(value) Check.That(var).Not.Contains(value);
.Should().ContainSingle() Check.That(var).HasSize(1);
.Should().OnlyContain(value) Check.That(var).ContainsOnlyElementsThatMatch(value);
.Should().HaveCount(value) Check.That(var).HasSize(value);
.Should().HaveSameCount(value) Check.That(var).HasSameSizeAs(value);
.Should().HaveCountGreaterThan(value) Check.That(var).WhoseSize().IsStrictlyGreaterThan(value);
.Should().HaveCountGreaterOrEqualTo(value) Check.That(var).WhoseSize().IsGreaterOrEqualThan(value);
.Should().BeEmpty() Check.That(var).IsEmpty();
.Should().NotBeEmpty() Check.That(var).IsNotEmpty();
.Should().StartWith(value) Check.That(var).StartsWith(value);
.Should().EndWith(value) Check.That(var).EndsWith(value);

String Assertions

FluentAssertions NFluent
.Should().BeEmpty() Check.That(var).IsEmpty();
.Should().NotBeEmpty() Check.That(var).Not.IsEmpty();
.Should().HaveLength(value) Check.That(var).HasSize(value);
.Should().BeNullOrWhiteSpace() Check.That(var).IsNullOrWhiteSpace();
.Should().NotBeNullOrWhiteSpace() Check.That(var).Not.IsNullOrWhiteSpace();

Boolean Assertions

FluentAssertions NFluent
.Should().BeTrue() Check.That(var).IsTrue();
.Should().BeFalse() Check.That(var).IsFalse();
.Should().NotBeTrue() Check.That(var).Not.IsTrue();
.Should().NotBeFalse() Check.That(var).Not.IsFalse();

Exception Assertions

FluentAssertions NFluent
.Should().Throw<ExceptionType>() Check.ThatCode(action).Throws<ExceptionType>();
.Should().ThrowExactly<ExceptionType>() Check.ThatCode(action).ThrowsExactly<ExceptionType>();
.Should().NotThrow() Check.ThatCode(action).DoesNotThrow();
.Should().ThrowAsync<ExceptionType>() Check.ThatCode(() => action()).ThrowsType(typeof(ExceptionType));
.Should().NotThrowAsync() Check.ThatCode(() => action()).DoesNotThrow();
.Should().Throw<ExceptionType>().WithMessage("...") Check.ThatCode(action).Throws<ExceptionType>().AndWhichMessage().Matches("...");
.Should().ThrowAsync<ExceptionType>().WithMessage("...") Check.ThatCode(() => action()).ThrowsType(typeof(ExceptionType)).AndWhichMessage().Matches("...");

Nullable Assertions

FluentAssertions NFluent
.Should().HaveValue() Check.That(var).HasValue();
.Should().NotHaveValue() Check.That(var).Not.HasValue();
.Should().Match(x => condition) Check.That(var).Matches(x => condition);

Collection Assertions

FluentAssertions NFluent
.Should().ContainKey(value) Check.That(var.Keys).Contains(value);
.Should().NotContainKey(value) Check.That(var.Keys).Not.Contains(value);
.Should().BeOfType<T>() Check.That(var).IsInstanceOfType(typeof(T));
.Should().BeOfType(value) Check.That(var).IsInstanceOfType(value);
.Should().Equal(value) Check.That(var).IsEqualTo(value);
.Should().NotEqual(value) Check.That(var).IsNotEqualTo(value);
.Should().ContainSingle() Check.That(var).HasSize(1);
.Should().BeNullOrEmpty() Check.That(var).IsNullOrEmpty();
.Should().NotBeNullOrEmpty() Check.That(var).Not.IsNullOrEmpty();

Limitations

While the CsFileContentReplacer automates many assertions, some complex scenarios may require manual intervention, such as:

  1. Unsupported Assertions: Certain FluentAssertions methods are not yet supported.
  2. Complex Lambda Expressions: Assertions using intricate lambda expressions may not be transformed correctly.
  3. Formatting: Multi-line or poorly formatted assertions might produce unexpected output.

Example of Partial Support

For multi-line assertions, while the tool handles most cases, some extra spaces may appear in the output and need to be manually fixed:

Input:

complexVar.Should()
    .BeEquivalentTo(
        new[]
        {
            Id = 1,
            Name = "Test"
        });

Output:

Check.That(complexVar).HasFieldsWithSameValues(new[] { Id = 1, Name = "Test" });

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages