Setting Up NUnit 3 in Visual Studio 2012

nunit-running-in-vs2012

Setting up NUnit 3 in Visual Studio is a simple task, but if you don’t know what you need to do, there are a few ways you can easily get stuck. To help you avoid loosing time I put together all the steps you need to follow to get you up and running.

The steps to setup Visual Studio are the following:

  1. Open Visual Studio 2012
  2. In the menu bar go to TOOLS > Extensions and Updates
  3. On the sidebar select Online and then type nunit on the search bar
  4. Install NUnit Templates for Visual Studio
  5. Install NUnit3 Test Adapter
  6. Restart

OK, now your system is ready. Let’s add a test project to your solution

  1. Open your solution
  2. In the menu bar go to FILE > Add > New Project…
  3. On the sidebar select Installed > Visual C# > Test
  4. On the main panel select NUnit 3 Unit Test Project and choose a proper name (like UnitTests)
  5. In the new project you wil find a file named TestClass.cs, open it
  6. In the menu bar go to TEST > Run > All Tests

The last step will build and run all the tests in your solution (1 for now). A window with the test results should popup, otherwise go to TEST > Windows > Test Explorer to bring it up.

The test should pass and be marked as green. Otherwise write a comment to this post and I’ll help you solve this problem.

The following video shows all the steps you need to follow

Advertisements

Why don’t I unit test?

I few months ago my brother did a couple of tech talk at work introducing TDD and explaining its benefits (and those talks then became posts in this blog). Then a few weeks later we asked our colleagues, if they hadn’t started writing unit test, why was that so.

These are the most common responses to why my colleagues didn’t write tests:

  1. I don’t have time to write tests
  2. I don’t know how to test
  3. I know I should but I’m too lazy

There’s no reason to dismiss any of those reasons and in that meeting we gave each of them a response (the best we could come up with). Following you can find my summary of each response:

I don’t have time to write tests

This one is tough, it would be simple to say that the programmer is lazy and should just do it, but anyone familiar with the workload of programmers and the improvement curve will know what is happening.

We’ll talk about the improvement curve and all its causes in a future episode, but to summarize, every time you try to do something new, like improving on your workflow there will be inefficiencies, this mean that when you adopt a new methodology you will be slower and less productive than you where before. This causes those that don’t expect this to happen to get frustrated and drop the improvement before they start reaping its benefits.

You may hear about TDD and all its benefits, you may hear that it makes you go faster, and since you are overloaded with work you think “Hey I could use that!”. But when you try it and you find out you have to write twice as much code, you drop it in 0.2 seconds (then you write a blog post about why TDD is dead or why it doesn’t work for you).

To fix this you have to attack the root cause, the programmer is overloaded and has no time to sharpen the saw, an organization that wants his developers to practice TDD has to invest in this improvement curve, and reduce the workload till they learn this new methodology, only then they will be able to be more productive (that’s why it’s called investment! you get disproportionate results but it takes some upfront costs).

If the company doesn’t want to invest in this and the programmer is determined to improve his abilities then he’s the one that needs to make and investment, going the extra mile out of work till he can go back to being productive. I know, I know, this isn’t right, is the company that will reap most of the benefits so they should be investing, but this is the real world and we can’t always wait for the rest of the world to act rational and do the right thing. If the company won’t do it, you can improve on you own.

I don’t know how to test

This is similar to the previous reason, in that it takes concerned effort on your part to overcome. Finding out what does it mean to TDD is easy. Setting up your environment to test takes about 10 minutes, and you can watch a couple of videos introducing unit test, but then you have to actually write your tests.

We already went in great depth into the process but the gist of it is that you should write the test that forces you to write the code you wanted to write anyway. (you can re-read that, I’ll wait)

After that, you should write test that explore the boundaries of your problem (like passing a null, or an empty list).

Then you can continue with some simple cases and grow from there.

This is how you start, but you need to realize that you will be a noob TDDer. How much have you been programming (5 years? 15 years? more?), how much have you been TDDing? 5 minutes? 15 days?

Your first test will suck. They will be hard to follow, slow, break a lot and be full of duplication. Every time you change something you will need to fix most of them.

But this is not how TDD works in the real world, you shouldn’t give up on it just because you suck at it. It’s like changing your keyboard layout from QWERTY to DVORAK, even tough you know how to program and you know what keys you want to type, you will be slow and make a lot of mistakes, but then you will get used to it. You will learn new techniques, you will write better test, cleaner test. Only at this point unit tests will be a net positive gain for you, and once you reach this point, there’s no going back.

I know I should try but I’m too lazy

I’m not making this up, this is a real reason I was given for not writing unit test. The problem with this reason is that it is not the real one. This programmer most likely isn’t lazy, the problem is that he feels overwhelmed by the amount of work that it will mean to go full TDD, so he keeps procrastinating.

We saw in the two previous section that TDDing is simple but not easy. Specially if you are working in a legacy code base, it will be an uphill battle.

The only advise I can give you is this:

Start somewhere, do a small step and then keep improving.

Not every project is perfect for starting with TDD, not every CR is perfect for starting with TDD, but some of them are and of them most are Just OK.

You need to start somewhere, first setup your environment and do a couple of tutorials. Then choose a project where you tend to have CRs that add functionality (instead of changing existing stuff). Now setup a test project in that solution and then write a small unit test for a small piece of functionality. No need to TDD it, no need to do all of it. Just start somewhere and then… never stop improving.

Now is your turn

If you want to keep updated please subscribe.

Why Remote Provisioning Helps Testing in Sharepoint

Introduction to Remote Provisioning

Before continuing with our series on testing in sharepoint we need to do a pit stop and introduce the concept of Remote Provisioning because it is quite useful when testing your application, in particular for the integration tests.

Remote provisioning is a concept introduced in Sharepoint 2013 and fundamental when working on Add-ins. It’s the suggested way to provision all your SHP artifacts (like Content Types, Fields, or Lists). It replaces everything that was deployed thought and Elements.xml and the Feature Framework.

OK, not everything, unfortunately the API isn’t on par on some things, but usually there are workarounds.

While remote provisioning an artifact you use the Client Side Object Model (CSOM) to programmatically create the artifact you need. This gives you the flexibility to build it imperatively and not declaratively (if you wish), but more importantly this prevents all the problems related to the feature framework like what happens when you have to update an existing object. If you have worked in SHP I have probably just summoned a few nightmares for you tonight, for something that should actually be quite simple.

If you want more information on doing remote provisioning I highly suggest you check out Office Dev PnP and it’s related provisioning engine, they provided a plethora of samples and helper methods to simplify doing remote provisioning and working with CSOM in general.

Why it helps

Let’s do a thought experiment:

Let’s say that you are testing a class in sharepoint, your test fails and you fix the class. Now you want to run the test… What should you do?

If you are used to doing TDD you might answer: “Just run the test”. Well doing it the traditional way you would have deployed your application’s DLLs with the same WSP that provision your artifacts*. This means that the DLLs are in the GAC and that means that the old version will be used instead of the one you just fixed.

So your test will keep failing and if you don’t realize it you could be wasting a lot of time trying to figure out why that happened.

To fix this you either have to deploy the new version (which is slow) or you retract the WSP so that your test framework can run from the local (and recent) copy. The problem is that if you retract the WSP all your artifact are removed from the sitecollection and you might get failing tests.

By doing remote provisioning all your artifacts deployed separately to the WSP and so you can safely retract it and keep working in a fast RED-GREEN-REFACTOR cycle. Also this way the deployment of the WSP is way faster.

*For those that don’t know SHP development this is like deploying your database in the same package that deploys your application’s DLLS

Testing your logic

Well, this article will be quite short, because when you isolate yourself from sharepoint, or any other hard to test framework, you can write test the same way you would do in any other environment. Now it doesn’t matter if you are a sharepoint developer or a mvc developer, you have plain old business object everywhere and any boundary can be replaced with a test double.

Let’s see a concrete example of what I’m saying. Picking a recent example from a project I’m working on let’s implement the following requirement:

Given that a user can be in multiple groups, and that a company is related to 2 groups, find all the companies that are related to the current user

To do this we need two data sources:

  • One provides the list of groups the current user is in
  • The other provides the list of all the companies and its related groups

This data will be provided by two different repositories with the following interfaces:

public class Group
{
  public string Name { get; set; }
}

public interface IGroupRepository
{
  IEnumerable<Group> GetCurrentUserGroups();
}

public class Company
{
  public string Name { get; set; }
  public Group Reader { get; set; }
  public Group Editor { get; set; }
}

public interface ICompanyRepository
{
  IEnumerable<Company> All();
}

OK now we can start TDDing our logic. We start with the most basic test and work our way up till we are done.

public class Tests
{
  [Test]
  public void NoCompanyNoGroups_NoCompany
  {
    var sut = new UserManager(new NoCompanyRepository(), new NoGroupRepository());
    var companies = sut.GetRelatedCompanies();
    Assert.That(companies.Count(), Is.EqualTo(0));
  }
}

This obviously fails, it doesn’t even compile. Let’s pretend we have the No___Repository stubs (if you have trouble implementing them ask in the comments). Let’s write the simplest manager that can pass that test

public class UserManager
{
  private readonly ICompanyRepository companyRepo;
  private readonly IGroupRepository groupRepo;

  public UserManager(ICompanyRepository companyRepo, IGroupRepository groupRepo)
  {
    this.companyRepo = companyRepo;
    this.groupRepo = groupRepo;
  }

  public IEnumerable<Company> GetRelatedCompanies()
  {
    return new List<Company>();
  }
}

Great this passes, but obviously isn’t what we were after. Let’s write another test

 [Test]
 public void RightCompanyAndGroup_OneCompany()
 {
   var sut = new UserManager(new OneCompanyRepository(), new OneEditorGroupRepository());
   var companies = sut.GetRelatedCompanies();
   Assert.That(companies.Count(), Is.EqualTo(1));
   Assert.That(companies.First().Name, Is.EqualTo("Right"));
 }

  public class OneCompanyRepository : ICompanyRepository
  {
    public IEnumerable<Company> All()
    {
      return new List<Company>()
            {
                new Company
                {
                  Editor = new Group {Name = "Editor"}, 
                  Reader = new Group {Name = "Reader"}, 
                  Name = "Right"
                }
            };
    }
  }

  public class OneEditorGroupRepository : IGroupRepository
  {
    public IEnumerable<Group> GetCurrentUserGroups()
    {
      return new List<Group>() { new Group { Name = "Editor" } };
    }
  }

Given the new test the simplest manager can return all the companies from the repository without filter, so we need to test a negative result. The following test checks that we don’t return any company given a set of unrelated groups.

[Test]
public void CompanyAndWrongGroup_NoCompany()
{
  var sut = new UserManager(new OneCompanyRepository(), new OneUnreleatedGroupRepository());
  var companies = sut.GetRelatedCompanies();
  Assert.That(companies.Count(), Is.EqualTo(0));
}
public class OneUnreleatedGroupRepository : IGroupRepository
{
  public IEnumerable<Group> GetCurrentUserGroups()
  {
    return new List<Group>() { new Group { Name = "Unreleated" } };
  }
}

Now our implementation can finally be compleated

public IEnumerable<Company> GetRelatedCompanies()
{
  var names = groupRepo.GetCurrentUserGroups().Select(g => g.Name).ToList();
  return companyRepo.All()
    .Where(company =>
      names.Contains(company.Editor.Name) ||
      names.Contains(company.Reader.Name));
}

As you can see we have implemented a (simple) bit of business logic that in production will be dealing with objects coming from sharepoint, but that thanks to the layer of repositories, we were able to isolate and build using TDD

Low Priority Bootstrap Bug Report for the ASP.NET website team

Hi there, sorry but I wasn’t able to find a proper way to report this. I tried with a tweet, but probably was lost in a sea of other people contacting you. I hope I can get someone on the team to read this post, and if I fail maybe at least I can help someone out there with a similar problem.

At this page https://get.asp.net/ there’s an error on how bootstrap is used to build the 4 columns on the “Work with your favorite development tools” section. There are elements that are direct child of a .row but aren’t marked as .col-*. It looks like this:

<div class="row">
  <div class="col-sm-12 col-md-12 col-lg-6">
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-visualstudio"></div>
      <div class="row">
        <!-- Missing .col element -->
        <h3><a href="https://www.visualstudio.com/en-us/visual-studio-homepage-vs.aspx">Visual Studio</a></h3>
        <p class="text-left">The easiest way to get started building applications with ASP.NET is to install the latest version of Visual Studio 2015 (including the freely available Community edition). Visual Studio has the tools you need to build ASP.NET web applications.</p>
        <p class="text-muted">Works with ASP.NET 4.6 &amp; 5.0</p>
      </div>
    </div>
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-vscode"></div>
      <div class="row">
        <!-- Missing .col element -->
        <h3><a href="https://code.visualstudio.com/">Visual Studio Code</a></h3>
        <p class="text-left">Visual Studio Code is a cross-platform code editor refined and optimized for building modern web and cloud applications.</p>
        <p class="text-muted">Works with ASP.NET 5.0<br><br><br></p>
      </div>
    </div>
  </div>
  <div class="col-sm-12 col-md-12 col-lg-6">
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-yeoman"></div>
      <div class="row">
        <!-- Missing .col element -->
        <h3><a href="https://github.com/omnisharp/generator-aspnet#generator-aspnet">generator-aspnet</a></h3>
        <p class="text-left">Yeoman is a scaffolding platform built on top of Node.js that allows you to build template-based generators for projects or code files. <em>generator-aspnet</em> is a yeoman generator that allows you to scaffold ASP.NET 5 applications.</p>
        <p class="text-muted">Works with ASP.NET 5.0</p>
      </div>
    </div>
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-omnisharp-vertical"></div>
      <div class="row">
        <!-- Missing .col element -->
        <h3><a href="http://www.omnisharp.net/">OmniSharp</a></h3>
        <p class="text-left">OmniSharp is a set of tooling, editor integrations and libraries for developing in .NET. OmniSharp works with a number of editors including Atom, Brackets, Emacs, Sublime Text and Vim.</p>
        <p class="text-muted">Works with ASP.NET 5.0</p>
      </div>
    </div>
  </div>
</div>

But should actually look like this:

<div class="row">
  <div class="col-sm-12 col-md-12 col-lg-6">
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-visualstudio"></div>
      <div class="row">
        <div class="col-sm-12"> <!-- Added -->
          <h3><a href="https://www.visualstudio.com/en-us/visual-studio-homepage-vs.aspx">Visual Studio</a></h3>
          <p class="text-left">The easiest way to get started building applications with ASP.NET is to install the latest version of Visual Studio 2015 (including the freely available Community edition). Visual Studio has the tools you need to build ASP.NET web applications.</p>
          <p class="text-muted">Works with ASP.NET 4.6 &amp; 5.0</p>
        </div>
      </div>
    </div>
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-vscode"></div>
      <div class="row">
        <div class="col-sm-12"> <!-- Added -->
          <h3><a href="https://code.visualstudio.com/">Visual Studio Code</a></h3>
          <p class="text-left">Visual Studio Code is a cross-platform code editor refined and optimized for building modern web and cloud applications.</p>
          <p class="text-muted">Works with ASP.NET 5.0<br><br><br></p>
        </div>
      </div>
    </div>
  </div>
  <div class="col-sm-12 col-md-12 col-lg-6">
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-yeoman"></div>
      <div class="row">
        <div class="col-sm-12"> <!-- Added -->
          <h3><a href="https://github.com/omnisharp/generator-aspnet#generator-aspnet">generator-aspnet</a></h3>
          <p class="text-left">Yeoman is a scaffolding platform built on top of Node.js that allows you to build template-based generators for projects or code files. <em>generator-aspnet</em> is a yeoman generator that allows you to scaffold ASP.NET 5 applications.</p>
          <p class="text-muted">Works with ASP.NET 5.0</p>
        </div>
      </div>
    </div>
    <div class="col-sm-12 col-md-6">
      <div class="row icon icon-omnisharp-vertical"></div>
      <div class="row">
        <div class="col-sm-12"> <!-- Added -->
          <h3><a href="http://www.omnisharp.net/">OmniSharp</a></h3>
          <p class="text-left">OmniSharp is a set of tooling, editor integrations and libraries for developing in .NET. OmniSharp works with a number of editors including Atom, Brackets, Emacs, Sublime Text and Vim.</p>
          <p class="text-muted">Works with ASP.NET 5.0</p>
        </div>
      </div>
    </div>
  </div>
</div>

Pay attention to the extra div.col-sm-12 element inside the inner div.row.

I’ve created this crude javascript that fixes the elements in question if you’ve want to try it.

$('#editors .row .row h3').parent().each(function(){
   var $this = $(this);
   var current = $this.html();
   $this.html("<div class='col-sm-12'>"+current+"</div>");
});

 

So what’s the big deal?
Well without that col-* element bootstrap won’t add the proper padding to the elements inside each column and they tend to bump into each other. In the following gifs you can see the difference made by this change.

desktop difference

Desktop

 

tablet

Tablet

 

phone

Phone

Testing your sharepoint repositories

In this article we will see how to test your sharepoint repositories, as we said before writing unit test for them isn’t easy. I don’t think you can test drive them or that it would help, at the very least it would be too slow.

Therefore SHP repositories are a weak point in your testing strategy, but at the very same time they are the base on which the rest of your application sits on. So it is very important that you do two things:

  1. Write KISS repositories
  2. Write integration tests for them

KISS: Keep It Simple Stupid

Your repositories need to be simple, strip them of any logic that has a reason to be somewhere else. Any constraint that isn’t strictly related to the persistent layer should be checked by another layer.

They should receive an entity from above and persist it like it is, if the entity comes with errors those errors will be persisted (or the layer bellow will throw an exception).

Expose a basic API. Instead of a method Save that check if the entities exists and then decides whether to update it or create a new entity expose three basic methods (Exists, Create, Update) and let the layer above make that decision.

Once you have a KISS repository you need to secure it the best you can. This is done by writing tests integrated with sharepoint. Usually to do this you will have to do the following things:

  1. Create a test site collection
  2. Provision your artifacts (Fields, ContentTypes, Lists…)
  3. For each test
    1. Populate one or more list
    2. Run a test
    3. Clean up
  4. Delete the site collection

This is obviously a very slow process so you won’t run this tests in your normal TDD cycle, but you can run them frequently enough that you will catch most bugs before they can cause any major problem.

Now let’s put aside the theory and write some code, starting from the repository of the previous article

    private const string WebAppUrl = "http://localhost";
    private const string SiteUrl = "http://localhost/sites/Test";
    private IPersonRepository repository;
    private SPSite site;

    [SetUp]
    public void SetUp()
    {
      site = CreateSite();
      repository = new PersonRepository(site.RootWeb);
    }

    [Test]
    public void WhenAddingAPerson__ItShouldAddAPerson()
    {
      var list = site.RootWeb.Lists["Person"];
      CleanList(list);

      var person = AddPerson();

      AssertCreation(list, person);
    }

    private SPSite CreateSite()
    {
      var webapp = SPWebApplication.Lookup(new Uri(WebAppUrl));

      if (SPSite.Exists(new Uri(SiteUrl)))
        webapp.Sites.Delete(SiteUrl);

      var site = webapp.Sites.Add(SiteUrl, "contoso\\admin", "admin@contoso.com");
      site.Features.Add(new Guid("<GUID>"));
      return site;
    }

    private void CleanList(SPList list)
    {
      while (list.Items.Count > 0)
        list.Items[0].Delete();
    }

    private Person AddPerson()
    {
      var person = new Person
      {
        Address = "Address",
        BirthDate = DateTime.Now,
        Name = "Name"
      };
      repository.Create(person);
      return person;
    }

    private void AssertCreation(SPList list, Person person)
    {
      Assert.That(list.Items.Count, Is.EqualsTo(1));
      var item = list.Items[0];
      Assert.That(item["Address"], Is.EqualsTo(person.Address));
      Assert.That(item["Title"], Is.EqualsTo(person.Name));
      Assert.That(item["DateOfBirth"], Is.EqualsTo(person.BirthDate));
    }

Here we see a setup method that creates (or recreates) a site collection at every test run. To speed up the tests a bit, you can move that operation to a Fixture Setup, but that might mean that some tests pass or fail depending on the order of execution, so proceed with care. During the site creation we also enable one (or more) features that provision our sharepoint artifacts.

We then have the test method that checks that the Create method of the repository works fine by:

  1. Removing any item present on the list
  2. Calling the Create method with a valid person
  3. Checking (via standard object model) that was added an item to the expected list with the required properties.

In the same way one might test a Get method. First you clean the list, than you add the expected item (via SSOM), than you get it with your repository and assert that everything is fine. Try it doing it yourself and let me know if you have any problem.

Repository Pattern

If you have ever heard of software design patterns, you have heard of the Gang of Four and their book. It’s the bible on this matter and it would be a disservice not to reference it, but the pattern we will talk about is missing from this book. You instead can find more information here.

In short the repository is an object that sits between your application data and your business logic. It helps (among other things) remove duplicated code, improve testability and provide a strong typed business entity that helps catch errors at compile time.

Repository are used to isolate from data source like databases, file system or a Sharepoint list, and from other difficult to integrate objects like web services. When all your business logic deals with data retrieval or persistence through a repository, you can test your business logic in isolation replacing the real repository with a test double.

To have a better understanding of what’s going on let’s have a look at some code

    class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime BirthDate { get; set; }
        public string Address { get; set; }
    }

    interface IPersonRepository
    {
        Person Get(int id);
        void Create(Person person);
        void Update(Person person);
        void Delete(int id);
    }

    class PersonRepository : IPersonRepository
    {
        private readonly SPList list;
        private readonly PersonSPListItemMapper mapper;

        public PersonRepository(SPWeb web)
        {
            list = web.Lists["Person"];
            mapper = new PersonSPListItemMapper();
        }

        public Person Get(int id)
        {
            SPListItem item = list.GetItemById(id);
            Person person = mapper.From(item);
            return person;
        }

        public void Create(Person person)
        {
            SPListItem item = list.AddItem();
            mapper.Populate(item, person);
            item.Update();
        }

        public void Update(Person person)
        {
            SPListItem item = list.GetItemById(person.Id);
            mapper.Populate(item, person);
            item.Update();
        }

        public void Delete(int id)
        {
            SPListItem item = list.GetItemById(id);
            item.Delete();
        }
    }

    class PersonSPListItemMapper
    {
        public Person From(SPListItem item)
        {
            return new Person
            {
                Name = item.Title,
                Id = item.ID,
                BirthDate = (DateTime)item["DateOfBirth"],
                Address = (string)item["Address"]
            };
        }

        public void Populate(SPListItem item, Person person)
        {
            item["Title"] = person.Name;
            item["DateOfBirth"] = person.BirthDate;
            item["Address"] = person.Address;
        }
    }

Here we see, in oder, the business entity we are interested on (Person), with a few basic properties, then the interface of our repository with a few basic CRUD operations, then we implement said interface against a sharepoint list, at the end we have a utility class that’s meant only to map to and from a sharepoint item.

The repository pattern is quite simple to comprehend, what’s important is that:

  • You keep following it
  • Every object in the business layer interacts with the entities through a repository
  • Every interaction is isolated by an interface

The following is a business layer object that expects a repository in its contructor and uses it to create a Person.

    internal class PersonManager
	{
		IPersonRepository repository;
		public PersonManager(IPersonRepository repository)
		{
			this.repository = repository;
		}
		public void Create(string name, string address, DateTime birthDate)
		{
			Person person = new Person
			{
				Name = name,
				BirthDate = birthDate,
				Address = address
			}
			repository.Create(person);
		}
	}

As you can see this class has no knowledge of what is Sharepoint and can be tested quite easily by passing a spy to the constructor instead of the real implementation.

All operations to persist a business entity pass through a repository, and any data retrieved by a query comes from it. In my example you can see a simple get by id query, but more complex queries are allowed. You can implement them in two ways:

  • The repository has a method for each query
  • The repository receives a query object that contains the required information to build a query

Another important advantage of using the repository pattern is that it can provide a centralized caching layer to for the rest of the application. This way if a query has already been served the repository can return a cached result set without having to muck the details of the business layer. This is quite useful when dealing with repositories that mask web services.

In the end, repository help isolate data access code, from the rest of your application, it provides an insertion point to test your business layer but adds another abstraction layer so it can be difficult to understand for developers in your team whom are unfamiliar with this pattern. Also keep in mind that repositories tend to be hard to unit test, so it is better to write integration test for them.

How to test in sharepoint

We have talked about how to set up your test environment, how to write tests and what to do with the freedom that the test give you (write code that is clean). Now we start to get into the nitty gritty of being a code cleaner, we need to start to clean some legacy code. I’m young, so probably my experience is not the same as most professional code cleaners, but when I think of legacy code, I think of sharepoint programming.

Programming with sharepoint is hard, you need to know how to work your way around many weird behaviours is sharepoint like the fact that in a field XML schema  False != FALSE.

But you get used to that stuff. The biggest problem with sharepoint is that it wasn’t built with the idea of enabling testability. No, most interesting classes are sealed (can’t be extended), and a value that can be approximated with 100% of the classes doesn’t inherit from an interface. You have to pass around concrete classes all around your code. This is a problem because you can’t replace an SPListItem with a test double. And to make matters worst, the biggest advantage of using sharepoint is also its biggest testability problem. Sharepoint is a monster, it has every functionality you could think of: CMS, Document management, Search, OCR, Cache, line of business integration, social netnork, blog, forum, ecc. It wants you to use its features, it wants you to integrate with it, but if you do in a naive way you are lost. There’s no way you will be able to TDD your application.

Luckily there’s a better way, its hard work, specially in the beginning when you need to change your frame of mind and the way you work, but there’s a better way, and I’m here to guide you.

We will start with a brief detour talking about a building block, the repository pattern, then we will see:

  • How to test your repositories
  • How to test your business logic
  • Sharepoint tdd tips and tricks
  • Why remote provisioning helps
  • How to do remote provisioning
  • Building repositories with SPMetal
  • More ways to isolate from the framework

Clean Errors – Clean Code

If you write feature code, you also have to write error handling code. There’s no clean code without clean error handling, if you don’t do it, your user has to deal with it in the form of your application crashing.

There are a few simple rules you should follow to, starting with using exceptions rather than return codes, we already talked about it when dealing with clean functions. Using unchecked exceptions let’s you concentrate in the flow of your code without interweaving it with a myriad of if-else statements to check every return code (or worse forget to do it and propagate an error state).

You should throw your exception thinking about how your caller will deal with it. So you need to provide context about the error in the message of the exception, and don’t litter your caller with very specific exception classes, if all of them will be dealt with in the same way (log and show error).

Remember that exceptions should be used to handle the weird flow not your normal flow. Don’t use them like if statements. If you have to integrate with a library that does just that wrap it and expose a sane interface that the rest of your system can deal with.

Avoid nulls like a plague. This probably deserves a whole article but to give you the gist of it, don’t return null, return something else, like an empty list or a special case object. Don’t pass null as a parameters. You don’t want to deal with it neither the writer of the function you are calling (likely yourself), don’t pass a null as an argument, unless it’s a function of a third-party library.

Clean Formatting – Clean Code

You just need to have a look at any minified JS file to realize how important proper formatting is.I don’t think any one would be able to program a whole system constantly minified, but most don’t give a concerned effort in improving the formatting of their code base, not even using the autoformatting features of the IDEs.

So in order of effort:

  1. If you are using Visual Studio type periodically Ctrl+K, Ctrl+D. This will auto format the current file giving you a nice starting point
  2. Install Code Maid. It’s a nice Visual Studio extension that helps formatting your code, you can configure it to do many little things, like grouping methods by its visibility (public, protected, private), removing unused using statements. It’s more powerful than the standard reformatting, and can also be configured to clean up at every save.

Code Maid goes a long way in improving your formatting, but when working on a team, it’s important that most of the team members use it, if not on auto mode, at least before any check-in. Otherwise, the commits done by the team members that use it risk being dirty with a lot of reformatting.

One thing I wasn’t able to do with code maid was enforce the news paper order to my methods. What’s that? Well, you see, a news paper article is organized in a way that first it gives you broad idea, then it goes a little bit in detail, then a little more, and then you get to the full picture.

In code you have high level functions calling low-level functions. So the same principle should apply. At the top of the file you should find the high level methods, then you should go down a level, and keep going till it the end.

Code maid isn’t smart enough to look at who calls who and order the methods with that in mind, but you have a brain and should use it 🙂

Other rules you should keep in mind are:

  • Add vertical spacing between concepts
  • Group vertically related concepts
  • Declare local variables close to their use
  • Declare instance variable at the top
  • Caller function should be close to callee and should come first

As always dealing with smaller files is easier to apply this rule. As a general guideline, Uncle Bob suggest keeping them at about 200 lines, with a maximum of  500 LoC.

In the same vein he suggest to set a maximum of 100-120 characters for a line of code, while having most of it being less than 60.

indentation is really important to help legibility, so don’t collapse a scope even if it is possible.

 

if(value == null) return;
//...

While it is a valid statement the collapsed block might be overlooked by a reader wasting his time.

if(value == null)
    return;  //This is more readable
//...

Remember, trying to trick the 5 lines maximum rule for a function by collapsing statements only hinders the readability of your source file.

One last note, a project should look like it was written by a single individual, it should look consistent. Is not acceptable to have different parts of it have different coding styles. The team rules, so at the start gather your group and decided on which rules to follow, than follow them.