Skip to content
Alex Povar edited this page Oct 18, 2017 · 4 revisions

v3.0

Using Semantic Versioning, the shift from the 2.x version line to AutoFixture 3.0 marks not only new features, but also breaking changes. Actually, there are more breaking changes than new features, and you could even argue that some of the new features constitute breaking changes.

Since AutoFixture's versioning scheme changed to Semantic Versioning, the minor version has grown from 2.2 to 2.16, indicating at least 14 new features as well as numerous bug fixes. While we have been able to continue to add new features to the 2.x line, we've been saving up a collection of breaking changes. Some of these changes open up new possibilities for future development, so while we could have continued to add new features to 2.x, the time has come to collect these desirable breaking changes together and release a new major version of AutoFixture.

However, because of the way Semantic Versioning works, and since AutoFixture is released in a Continuous Delivery fashion, it means that the AutoFixture 3.0 release is mostly about breaking changes.

Why upgrade?

If AutoFixture 3.0 mostly consists of breaking changes and has few new features, why should you upgrade? It sounds like all work with few benefits.

That may be true, but on the other hand, if you want to stay current with AutoFixture, you will have to upgrade, since the 3.0 version is going to be the foundation for all new features. There will be no more new features or bug fixes for 2.x.

We realize that this may be painful, although we've gone to great lengths to minimize the impact of the breaking changes. Still, the last breaking change introduced to AutoFixture was more than a year ago, and we have no plans of introducing new breaking changes in the near future.

Where do I get it?

AutoFixture is available on NuGet, as it has always been. If you need a .zip file with all the binaries, see Releases.

Please provide feedback

If you decide to take the limited beta for a spin, please provide feedback if you encounter issues that are not covered by these release notes.

What's new in AutoFixture 3.0?

The following is an overview of the new features in AutoFixture 3.0. After the initial list, each new feature is described in more detail under its own headline.

Fixture can now resolve itself

AutoFixture 2.x couldn't resolve itself. While a Fixture instance was able to create an instance of the Fixture class (but returning a new instance of Fixture), it couldn't handle requests for IFixture or ISpecimenBuilderComposer. This was particularly a problem when requesting an instance of the Generator class, or when working with the AutoFixture.Idioms library.

This often required a customization like this:

public class SpecimenBuilderComposerCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Inject<ISpecimenBuilderComposer>(fixture);
    }
}

AutoFixture 3.0 will automatically return itself when a Fixture, IFixture or ISpecimenBuilder is requested, making customizations such as the above example redundant.

Iterators are stable and finite by default

In AutoFixture 2.x, enumerables were dynamic by design. In AutoFixture, the default behavior is to return a stable, finite sequence.

Thus, the StableFiniteSequenceCustomization is now redundant.

Various collections are filled by default

In AutoFixture 2.x, collections were empty by default. More specifically, concrete collections such as List<T>, Collection<T>, arrays, etc. would be created, but tend to be empty. Abstract 'collections' such as IList<T>, IEnumerable<T>, ICollection<T> wouldn't be created at all, because a default Fixture can't resolve interface types.

In AutoFixture 3.0, a default Fixture instance resolves and populates such collection types. Thus, the MultipleCustomization is now redundant.

Default URI scheme is now "http"

In AutoFixture 2.x, the default URI scheme was "scheme". This tended to cause problems when testing against e.g. the ASP.NET Web API, where the only allowed URI schemes are "http" and "https".

This required you to write a Customization like this:

public class HttpSchemeCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Inject(new UriScheme("http"));
    }
}

While a URI can have many different schemes, the most common scheme seems to be "http", so it makes sense to make this the default instead of the neutral, but entirely made-up scheme "scheme".

Thus, in AutoFixture 3.0, the default URI scheme is "http", and Customizations like the above HttpSchemeCustomization are now redundant.

Breaking Changes

The following is an overview of the breaking changes in AutoFixture 3.0. After the initial list, each breaking change is described in more detail under its own headline.

CreateAnonymous is now Create

The original naming of the CreateAnonymous method was inspired by the pattern language presented in xUnit Test Patterns, where an Anonymous Value is an object (or primitive) where you don't care about the exact value of the object - exactly what AutoFixture creates.

Unfortunately, feedback indicated that many newcomers to AutoFixture found the CreateAnonymous name intimidating. In order to make the API more friendly, the CreateAnonymous method has been renamed to Create.

The most common symptom of this is this compiler error:

Instance argument: cannot convert from 'Ploeh.AutoFixture.Fixture' to Ploeh.AutoFixture.Kernel.ISpecimenContext'

Just replace CreateAnonymous with Create

Numbers are random

Numbers (integers, bytes, decimals, floats, etc.) are now created using a random algorithm. In keeping with the original concept of Constrained Non-determinism numbers are generated within proper ranges:

  • The first numbers are generated within the range of [1, 255], as this is a set of values that are valid for all numeric data types. The smallest numeric data type in .NET is System.Byte, which fits in this range.
  • When the first 255 integers have been used, numbers are subsequently picked from the range [256, 32767], which corresponds to the remaining positive numbers available for System.Int16.
  • Etc. Thus, while numbers are still initially going to fall in the Equivalence Set of small, positive integers they are no longer guaranteed to arrive in any order. The 2.x behavior can be re-applied by adding a NumericSequenceGenerator to the Fixture's Customizations:
fixture.Customizations.Add(new NumericSequenceGenerator());

The best option is to encapsulate this in a Customization, like this:

public class NumericSequenceCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(new NumericSequenceGenerator());
    }
}

Supplying a custom range

To supply a custom range, customize an instance of the Fixture class with an instance of the RandomNumericSequenceGenerator and pass to its constructor a sequence of integer numbers (e.g. -100, 100, 255).

The sequence must be two positive or negative numbers optionally followed by a series of greater numbers.

var fixture = new Fixture();
fixture.Customizations.Add(
    new RandomNumericSequenceGenerator(-100, 100, 255));

var i = fixture.CreateAnonymous<int>();
// Prints -> -95
var l = fixture.CreateAnonymous<long>();
// Prints -> 47
var f = fixture.CreateAnonymous<float>();
// Prints -> -82.0

After applying the customization, numbers are now created in the range of [-100, 100]. However, when requesting more numbers than the range size the range is automatically changed to [101, 255].

DateTimes are random

Just like numbers, DateTime instances are now generated randomly, in the interval of 2 years in the past to 2 years into the future, from the date a test is executed. The reasoning is that a good default Equivalance Set for dates (and times) consists of dates in close proximity with the present. Most systems should be able to handle such 'current' dates.

If you don't like the range, you can customize the Fixture with a different DateTime range:

fixture.Customizations.Add(new RandomDateTimeSequenceGenerator(minDate, maxDate));

Or, even better, encapsulate it in a Customization.

In case you need to re-apply the 2.x behavior for DateTime instances, this is possible with the IncrementingDateTimeCustomization:

var fixture = new Fixture().Customize(new IncrementingDateTimeCustomization());

or, if you want the really old behaviour from AutoFixture 2.1 and before:

var fixture = new Fixture().Customize(new CurrentDateTimeCustomization());

chars are random

Just like numbers and DateTime instances, char values are now generated randomly in the range of printable ASCII characters ['!', '~'].

In case you need to re-apply the 2.x behavior for char instances, this is possible:

fixture.Customizations.Add(new CharSequenceGenerator());

ISpecimenBuilderComposer no longer exists

The ISpecimenBuilderComposer interface has been removed. The interface was defined like this:

public interface ISpecimenBuilderComposer
{
    ISpecimenBuilder Compose();
}

The types that most prominently implemented this interface was Fixture (and IFixture) as well as the composers that are part of the Build<T> Fluent-style DSL.

These types now directly implement ISpecimenBuilder, so instead of having to invoke Compose on an ISpecimenBuilderComposer you can now pass an ISpecimenBuilder directly.

SemanticComparison now only ships in its own NuGet package

While the Ploeh.SemanticComparison library sprang out of the work done with AutoFixture, it doesn't share any code with AutoFixture. It's the oldest companion library for AutoFixture, and originally it was bundled with AutoFixture simply because in the beginning, it was implemented directly in the AutoFixture code base. When it was spun out to a separate library, it remained bundled with AutoFixture.

Through all of 2.x, SemanticComparison has been included in the AutoFixture NuGet package, for no other reason that these two libraries were historically bundled.

Starting with AutoFixture 3.0, the AutoFixture NuGet package only contains AutoFixture itself. SemanticComparison is available via the SemanticComparison NuGet package.

AutoFixture now requires .NET 4.0

AutoFixture 2.x was compiled against .NET 3.5. A survey among users of AutoFixture performed more than a year ago showed that no users actually wrote unit tests on .NET 3.5. While AutoFixture 3.0 doesn't yet use any .NET 4.0 features, future versions in the 3.x line may, so AutoFixture and all companion libraries are now compiled against .NET 4.0.

This means that in order to use AutoFixture, your unit tests must target .NET 4.0 or higher. Your System Under Test can be whatever you can make work; AutoFixture has no requirements in that regard.