There’s actually news in the world of SpecsFor! .NET Standard support has arrived, plans for the next version are becoming a little more concrete… read on if you want to catch up!

The Journey to .NET Standard

“One can only slack for so long…” – Me, when I finally started work on .NET Standard support for SpecsFor

I am probably one of the worst open-source project maintainers, ever. I’ve let SpecsFor languish without .NET Standard support for far too long.

I had my reasons though. Prior to 2018, most of my production work still targeted .NET 4.7. To be perfectly honest, I didn’t even like .NET Core until 2.1. I feel like we’re just now hitting the point where it’s an actual, viable, stable solution. I’m only just now diving in to the pool all the way.

So there was that lack of motivation, but then there were also the dependencies!

SpecsFor is actually built on top of several different libraries: NUnit, Jeremy Miller’s StructureMap, kzu’s Moq, Derek Greer’s ExpectedObjects, and Eric Hexter’s Should. SpecsFor has varying degrees of dependencies on each of these libraries. You might (correctly) say it is tightly coupled to each of these projects.

This made perfect sense to me at the time. SpecsFor was originally meant to be a highly opinionated framework: you wrote specs using a specific combination of tools, in a specific way, with some glue in the middle to help make things work together nicely.

That’s an awesome idea, and it works fine… until one of those dependencies stops being maintained. That is exactly what happened to Should. In order for SpecsFor to target .NET Standard, I would have to break that dependency on Should.

That turned out to be more difficult than you might think, and in the end, I actually ended up forking Should, reworking that for .NET Standard, and shipping that as its own NuGet package, Should-DotNetStandard.

This is a temporary solution for the 6.0 release. I don’t plan to support Should-DotNetStandard for long. In fact, I don’t plan for SpecsFor to remain coupled to much of anything in the future. But we’ll get to that in a second! Let’s talk about ASP.NET MVC.

Saying Goodbye to SpecsFor.Mvc

As much as it pains me, I’m planning to retire SpecsFor.Mvc. I’ll continue to fix bugs and accept pull requests for the foreseeable future, but it will not be getting ASP.NET Core support. If you want to use it for ASP.NET MVC 5, feel free to do so! But don’t expect to see it working with ASP.NET Core.

I have my reasons for retiring this project. It was always difficult to maintain and support, but more than that, I just don’t feel that there’s much of a fit for it in ASP.NET Core. Microsoft decided to basically abandon the whole strongly-typed approach to things when they deprecated HtmlHelpers and went with TagHelpers in ASP.NET Core. Beyond even that, there’s the fact that most apps, at least the ones I work with, are built on front-end frameworks like Angular, and those frameworks have their own tools for UI testing.

So that’s that: SpecsFor.Mvc is still out there and will still work for ASP.NET MVC 5 apps. I’ll still try to fix bugs as they are found, and I’m still accepting pull requests. In fact, I’m shipping a small update today thanks to a pull request from Nick Divinci, plus a few minor improvements to the code itself.

But, unless someone wants to step in and champion the work (or pay me to champion it?), it won’t be following its sibling into the land of .NET Standard.

With that depressing bit out of the way, let’s talk about what’s next for SpecsFor!

SpecsFor vNext

My focus with the SpecsFor 6.0 release is to get things working stably as a .NET Standard package. I don’t plan to add new features to this version. I just want to get it all working, and working well, on .NET Core, .NET Full, etc.

I have very different, probably overly-ambitious, goals for SpecsFor 7.0.

For SpecsFor 7.0, I want to accomplish two contradictory goals at once: provide a solution that is flexible and can be used with the tools of your choice, and provide a highly-opinionated solution with the latest-and-greatest tooling. How can I do both of these things at once? Here’s what I’m thinking:

  • SpecsFor.Core – The core “engine” of SpecsFor. No dependency on anything else, just some abstractions.
  • SpecsFor.Assertions – Framework-agnostic test helpers. Things like ShouldLookLike and other common helpers would live in this package.
  • SpecsFor.Web – Framework-agnostic helpers to simplify common ASP.NET Core testing scenarios.
  • SpecsFor.EF – Framework-agnostic helpers to simplify common Entity Framework testing scenarios, enabling simple, easy integration testing.

Those will be the “core” packages, with as few dependencies as I can get away with in each. The idea is that you can pick and choose what you need, configure it to use whatever testing framework, mocking framework, and assertion library that you want. I hope to have packages available for common configurations, probably something like:

  • SpecsFor.NUnit – Wiring to enable SpecsFor to work on top of NUnit.
  • SpecsFor.XUnit – Wiring to enable SpecsFor to work on top of XUnit.
  • SpecsFor.StructureMap – Configures SpecsFor to use an auto-mocking StructureMap container for creating everything (just like it does today).
  • SpecsFor.SimpleInjector – Configures SpecsFor to use an auto-mocking SimpleInjector container.
  • SpecsFor.Moq – Configures SpecsFor to use Moq for creating mocks.
  • SpecsFor.FakeItEasy – Configures SpecsFor to use FakeItEasy for creating mocks.

You get the idea: small, modular packages, that you can mix and match to fit however you want to write your specs.

But I still plan to have a “mega” package:

  • SpecsFor – The highly-opinionated kitchen sink. Built on SpecsFor.Core, wired up to use a specific testing framework, a specific set of assertions, a specific mocking library, etc.

I’m not sure exactly which tools I’ll choose for this mega package yet. I know I want to use Shouldly for its awesome exception messages. Other than that, I may end up keeping the current set of tooling. I’m also tempted by XUnit, but its approach to testing is not really compatible with SpecsFor, and I’m still not sure how I’m going to make SpecsFor work on top of it. If you think I should ditch one tool for another, let me now.

It’s going to be a lot of work, but I think that will greatly open up the places that SpecsFor can be applied. Plus it’ll be fun (I think)!

Interested in Helping?

All of that said, 7.0 is going to be a lot of work. I’d love to get some help on this. If you’re interested in championing any one of these packages, or helping with the core redesign, please contact me! And if you work for a company that is using (or interested in using) SpecsFor, and you’d like to sponsor some of the new work, let me know! 😃