Acceptance Criteria for Social sign-in integration

Earlier in the year I was developing some business logic to integrate social (in this case Facebook) sign-in with a website’s existing “local account”. At the time I created a set of acceptance criteria in conjunction with the product owner in order to work through the rather complex logic that results (as you will see there are quite a few permutations and it gets quite complex to express this understandably).

I recently started working on specifying some work that involves social sign-in integration and it occurred to me that the previous work I had done is probably quite relevant and reusable in other situations. To that end I’ve included the acceptance criteria below in case it’s helpful for anyone.

Note: Don’t hesitate to adjust it according to your needs; some of it is specific to the implementation that I did earlier in the year. I would say it’s worth using it as a base to consider some of the possibilities when linking your website’s login with social sign-in.

GIVEN a user is not logged in
AND doesn't have a "local account"
WHEN the user authenticates their facebook account
THEN a new "local account" will be created for them linked to their facebook account
AND the user will be logged into the new "local account"
 
 
GIVEN a user is logged in
AND has not linked a facebook account
WHEN the user authenticates their facebook account
THEN the user will be prompted for their password to link their facebook account
 
 
GIVEN a user is logged in
AND has linked their facebook account
WHEN the user authenticates their facebook account
THEN they will be redirected to the Home page
 
 
GIVEN a user is not logged in
AND has linked a facebook account
WHEN the user authenticates their facebook account
THEN the user is logged into their "local account"
 
 
GIVEN a user has linked a facebook account
AND a second user is logged in
WHEN the second user tries to authenticate that facebook account
THEN the second user will be displayed a message indicating that facebook account is linked to another account
 
 
GIVEN a user is logged in
AND has a facebook email that matches the email of a non-Facebook-linked "local account"
WHEN the user authenticates their facebook account
THEN the user will be displayed a message indicating that email address is used by another user
 
 
GIVEN a user is not logged in
AND has a facebook email that matches the email of a non-Facebook-linked "local account"
WHEN the user authenticates their facebook account
THEN the user will be prompted for their password to link their facebook account and log in
 
 
GIVEN a user is logged in
AND has not linked a facebook account
AND they have authenticated their facebook account
WHEN the user submits their password
THEN the user's facebook account will be linked to their "local account"
 
 
GIVEN a user is not logged in
AND has a facebook email that matches the email of a non-Facebook-linked "local account"
AND they have authenticated their facebook account
WHEN the user submits their password
THEN the user's facebook account will be linked to their "local account"
AND they will be logged in

AutofacContrib.NSubstitute v3 release

I’d like to announce a new release for the AutofacContrib.NSubstitute library. The library was in need of a bit of love because it forced you to use a really old NSubstitute version.

I’ve made the following changes:

  • Deprecated the AutoMock class in favour of AutoSubstitute (in keeping with the theme of the NSubstitute library).
  • Added a new constructor that allows you to make modifications to the ContainerBuilder before the IContainer is built.
  • Dependency on the latest version of NSubstitute and removed the hard restriction on the NSubstitute and Autofac version numbers so the package is compatible with the latest versions of those libraries.
  • Moved the source to Github
  • Added some documentation and an example class showing some usage examples

Enjoy!

Robust testing

My favourite kind of test is one that automatically applies itself to any changes in your codebase. That way you write the test once and then you can forget about it because it will always give you the assurance that it is testing what you intended it to. Reflection can be really handy for this because it allows you to scan your assembly for classes that you want to apply your test to for instance. I will post a blog post momentarily with an example.

In instances where you can’t automatically apply the test I find it useful to put code in the test that will fail the test if your implementation changes. For example if you are testing the filters that are returned from a filter provider and you are checking for the two filters that you are expecting are provided then you might put in a further check to ensure that only 2 filters are provided so that the test fails if you add more filters. Adding more filters is probably the expected behaviour, but at least it forces you to stop and think about whether the new behaviour what you expect based on your expression of the design of the system (the tests). In the case of the filters, if you are say providing different filters depending on different conditions it’s certainly reasonable that an error could be introduced into the code resulting in incorrect filters being provided for some conditions that you want your test to catch.

In saying that, the danger that you may come across when you make your tests explicit is you may find yourself having to constantly make tedious updates to the tests for minor code changes that you often make. If you find yourself in this situation it’s important to reassess the test and either make it automatically apply based on your implementation, as mentioned above, or adjust the test to make it less restrictive or remove it completely (obviously you still want to have confidence in your codebase so you need to weigh up the tediousness of the test with the value of what is being tested). This is why controller testing is often not worth it (check out the controller testing library I have just released though, which goes some way towards addressing that).

At the end of the day, I think a pragmatic approach is required for writing tests and deciding what should and shouldn’t be tested and how strictly it should be tested based in balancing cost/maintainability of the testing against the value that the tests provide. If you can write tests that are flexible enough to automatically apply as you write new code then that is the best possible result!

FluentMVCTesting: Fluent, terse and maintainable ASP.NET MVC controller testing

I would like to announce the release of a software library I have been using for the last year or so as open source via NuGet / Github: FluentMVCTesting.

The motivation behind this library is to provide a way to test MVC actions quickly, tersely and maintainably. Most examples I find on MVC controller testing are incredibly verbose, repetitive and time-consuming to write and maintain.

Given how quickly you can write controller actions and how simple they are (assuming you are following best practices and keeping them lean) the time to test them generally isn’t worth it given you can glance at most of your controller actions and know they are right or wrong instantly.

This library aims to make the time to implement the tests inconsequential and then the value your tests are providing is worth it.

The other problem that I’ve noticed with most examples of controller testing is that there are a lot of magic strings being used to test view and action names; this library also aims to (where possible) utilise the type system to resolve a lot of those magic strings, thus ensuring your tests are more maintainable and require less re-work when you perform major refactoring of your code.

I came up with this library after using the MVCContrib.TestHelper library for quite a while, but becoming frustrated with it; the library was initially created during the experiment I conducted to try and create terse controller tests (which I still have to write a follow-up post for at some point!). I have been using the library for over a year on a number of projects both personally and professionally.

A small code snippet to whet your appetite (go to the NuGet site for more detailed documentation and examples):

// Check that a post to the Login action with model errors returns the Login view passing through the model
var vm = new LoginViewModel();
_controller.WithModelErrors().WithCallTo(c => c.Login(vm)).ShouldRenderDefaultView().WithModel(vm);

// Check that a post to the Login action without model errors redirects to the site homepage
_controller.WithCallTo(c => c.Login(new LoginViewModel())).ShouldRedirectTo<HomeController>(c => c.Index());

Enjoy!