$30 off During Our Annual Pro Sale. View Details »

Becoming a SharePoint Ninja

neraath
March 02, 2013

Becoming a SharePoint Ninja

SharePoint has made developing in an agile environment notoriously difficult. Specifically, test-driven and behavior-driven development have been avoided due to the complexity of the API and the environmental requirements. Yet, numerous paths exist for SharePoint developers to pursue in order to apply these high value practices to their projects. In this session, we'll discuss how Microsoft's Fakes framework will enable your team to begin unit testing. However, we'll spend most of our time going over architectural patterns that separate your business logic from SharePoint APIs, making it much easier to unit test your code, and enable your team to become test- and behavior-driven. We'll conclude with some common agile practices that are still relevant to SharePoint developers to keep their velocity high.

neraath

March 02, 2013
Tweet

More Decks by neraath

Other Decks in Programming

Transcript

  1. Becoming a SharePoint
    Ninja
    Agile Development Techniques for SharePoint
    Chris Weldon

    View Slide

  2. Your Guide: Chris Weldon
    • Fightin’ Texas Aggie
    • Microsoft MVP
    • .Net and SharePoint Developer
    • UNIX and Windows Sysadmin
    • Sr. Consultant at Improving Enterprises
    [email protected]

    View Slide

  3. Promotion
    • @neraath
    • #spsatx
    • #agilerocks
    • #thisguyisawesome
    • #boringpresentation
    • #terriblepresenter

    View Slide

  4. Agile, Microsoft, Open Technologies, UX
    Applied Training, Coaching, Mentoring
    Certified Consulting
    Rural Sourcing
    Recruiting Services

    View Slide

  5. Overview
    • Learn value of agile testing techniques
    • Address difficulties of testing logic that leverages
    SharePoint
    • Moles Fakes Framework
    • Design patterns to improve testability
    •Code Heavy

    View Slide

  6. Assumptions
    • You develop software
    • You know the SharePoint API

    View Slide

  7. Agile
    Being

    View Slide

  8. “Working software is the
    primary measure of
    progress”

    View Slide

  9. Tests
    Tests

    View Slide

  10. Types of Tests
    Unit UI
    Performance Functional
    Load

    View Slide

  11. Unit
    Testing
    TDD
    leads to

    View Slide

  12. TDD
    Continuous
    Integration
    leads to

    View Slide

  13. “Fail Fast”
    This Closes our Feedback Loop

    View Slide

  14. • Every commit (to the trunk) should be built
    • Keep the build fast
    • Notify (and make visible to) the entire
    team
    • Intrusively notify the team of failures
    • Make sure to fix the build after it’s broken
    “Fail Fast”

    View Slide

  15. View Slide

  16. Standard Testing Practices
    A Common Problem
    namespace SharePointLogic
    {
    public class ClassWithDependencies
    {
    private SqlDatabase database;
    public ClassWithDependencies()
    {
    this.database = new SqlDatabase();
    }
    public INode GetNodeByName(string name)
    {
    return this.database.Where(x => x.Name.Equals(name))
    .Select();
    }
    }
    }

    View Slide

  17. • What if no database locally?
    • Did you write test logic to rebuild the database
    before each test run?
    • What if this dependency is a physical piece of
    hardware?
    Standard Testing Practices
    A Common Problem

    View Slide

  18. Standard Testing Practices
    How to Solve
    namespace SharePointLogic
    {
    public class ClassWithDependencies
    {
    private IDataRepository repository;
    public ClassWithDependencies(IDataRepository repo)
    {
    this.repository = repo;
    }
    public INode GetNodeByName(string name)
    {
    return this.repository.Where(x => x.Name.Equals(name))
    .Select();
    }
    }
    }

    View Slide

  19. Standard Testing Practices
    How to Solve
    namespace SharePointLogicTests
    {
    [TestClass]
    public class ClassWithDependenciesTests
    {
    [TestMethod]
    public void TestGetNodesByName()
    {
    // Arrange.
    INode node = new SharePointNode();
    IDataRepository repository =
    (IDataRepository)MockRepository.Stub();
    repository.Stub(x => x.Where).Returns(repository);
    repository.Stub(x => x.Select).Returns(node);
    repository.Replay();
    // ...

    View Slide

  20. // Act.
    ClassWithDependencies testClass = new ClassWithDependencies(repository);
    INode testNode = testClass.GetNodeByName("Test");
    // Assert.
    Assert.AreEqual(node, testNode);
    }
    }
    }
    Standard Testing Practices
    How to Solve

    View Slide

  21. • Most of SharePoint object model has NO interfaces
    • Worse, most also are Sealed classes, meaning no
    extending and overriding the SharePoint behavior
    • Most SharePoint objects require active connection
    and instance of SharePoint on local server
    • Unlike database projects, resetting and recreating
    state in SharePoint is way more difficult
    Standard Testing Practices
    What about SharePoint?

    View Slide

  22. Standard Testing Practices
    A SharePoint Common Problem
    public string GetNameOfSharePointWebSite(string url)
    {
    using (SPSite site = new SPSite(url))
    {
    using (SPWeb web = site.OpenWeb())
    {
    return web.Name;
    }
    }
    }

    View Slide

  23. A Trickier Problem
    public IList GetUsersInSiteCollection(string siteUrl) {
    using (SPSite site = new SPSite(siteUrl) {
    site.CatchAccessDeinedError = false;
    using (SPWeb web = site.RootWeb) {
    try {
    if (web.DoesUserHavePermissions(SPBasePermissions.ManageWeb)) {
    SPUsercollection users = web.Users;
    List usersWithAccess = new List();
    foreach (SPUser user in users)
    {
    if (web.DoesUserHavePermissions(user.LoginName,
    SPBasePermissions.ManageWeb)) {
    usersWithAccess.Add(user);
    }
    }
    return usersWithAccess;
    }
    } catch (UnauthorizedAccessException e) {
    return new List();
    }
    }
    }
    }

    View Slide

  24. How to Test: Fakes
    • Fakes is, simply put, a mocking and stubbing
    framework
    • Different than other traditional mocking
    frameworks
    • Uses detours to custom delegates via runtime
    instrumentation

    View Slide

  25. DEMO
    SharePoint & Fakes
    Example

    View Slide

  26. Fakes
    • As your dependency on SharePoint Object Model
    grows, more detours required for testing
    • In most cases, more tedious than beneficial
    • If only could have most of the basic SharePoint
    behaviors pre-generated
    • Solution:
    Microsoft.SharePoint.Behaviors
    Microsoft.SharePoint.Emulators

    View Slide

  27. Observations
    • Even behaviors are not complete
    • A lot of mocking activity may get repeated
    • Unit test setup logic gets refactored into common
    assemblies
    • Save time: create scenarios
    • Use BDD-style approach for testing

    View Slide

  28. Gotchas
    • More moles unit tests = much longer test execution
    time
    • TDD is (still) hard
    • Continuous Integration
    • This will take time to learn, research, and debug
    • Pay attention when it stops adding value
    • The GAC

    View Slide

  29. “Continuous attention to
    technical excellence
    and good design enhances
    agility. “

    View Slide

  30. Another Problem
    public IList GetMachinesWithManufacturer(Manufacturer mft) {
    using (MachinesSiteDataContext context = new
    MachinesSiteDataContext(SPContext.Current.Web.Url)) {
    try {
    var machines = from machine in context.Machines
    where machine.Active && machine.Manufacturer == mft
    select machine;
    return machines.ToList();
    } catch (UnauthorizedAccessException e) {
    return new List();
    } catch (Exception e) {
    throw;
    }
    }
    }

    View Slide

  31. Agile Architecture
    • Introduce abstractions
    • Facades
    • Repository Pattern
    • Dependency Injection / Service Locator

    View Slide

  32. Abstraction
    public interface IMachineRepository {
    IList GetMachinesWithManufacturer(Manufacturer mft);
    }
    public class MachineRepository : IMachineRepository {
    public IList GetMachinesWithManufacturer(Manufacturer mft) {
    // ...
    }
    }

    View Slide

  33. Abstraction
    public class MachineWebPart {
    private IMachineRepository machineRepo;
    public MachineWebPart() {
    IServiceLocator locator = SharePointServiceLocator.GetCurrent();
    this.machineRepo = locator.GetInstance();
    }
    protected IList GetMachinesToRender(Manufacturer mft) {
    return this.machineRepo.GetMachinesWithManufacturer(mft);
    }
    }

    View Slide

  34. DEMO
    Abstraction

    View Slide

  35. This (technically) isn’t new
    www.microsoft.com/spg/

    View Slide

  36. Q&A

    View Slide

  37. Thank You!
    spkr8.com/neraath

    View Slide