Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Anthony Dang 1404 posts 2558 karma points MVP 3x c-trib
    Jul 19, 2013 @ 12:14
    Anthony Dang
    2

    Umbraco and TDD - An open discussion

    This is an open discussion...

    How are you currently doing TDD with Umbraco? 

    What are you actually testing, and how?

    How would you like to do TDD with Umbraco?

     

    What we would like to test:

    Tree traversal - We have config nodes which we often need to get values from. If the tree structure changes, we want to know that our traversal code still works.

    Content creation - We want to know that our code actually calls the Umbraco API

    Events - We would love to test events eg. before save, after publish etc.

     

     

  • Ravi Motha 290 posts 500 karma points MVP 7x c-trib
    Jul 19, 2013 @ 12:20
    Ravi Motha
    0

    That sounds like testing of the umbraco functionality rather that trests that are relevenat for "your" web site.

    generally it would be tests for logging in  (front-end , not cms)

    general user events - forgotten passwords

    connections to 3rd party sources  and data retrieval and integrity for order processing

  • John 79 posts 115 karma points
    Jul 19, 2013 @ 12:38
    John
    0

    I have only just started to use the IContentService stuff but have rewritten a couple of our old Document-orientated methods to use it.  For example, one of these was a helper method to manage an A-Z index.  I have unit tested both of these (one of them using TDD, one of them not because I wasn't sure if it would work).  It's great that we can now do this kind of thing with Umbraco - big leap forwards from the old Document API.

    For my service i used constructor injection and passed in an IContentService.  I could then pass in a mocked version of this using Moq to do my tests.  So it can provide data to my service, but I can also verify whether particular methods are called.

    I created some test data builder objects for building the service so I could pass in if I wanted a home page, or a page with an A-Z entry or whatever.  It works well enough but it's not very scalable for other tests because it's very specific to what I was doing.  The problem is that the service gets the children, parent, descendants and ancestors so it's a little hard to know how to create the objects without it becoming a mess.

    I was thinking of creating some kind of IContent implementation complete with Children, Parent, Ancestors and Descendants and then writing an implementation of IContentService that worked with it - possibly deriving from Mock<IContentService>, or encapsulating it or something.  (That way I could create a FakeContent, add children to it etc. and now have to setup the content service each time)  Not really put any effort into it yet though.

    I would be interested to know if anyone else has done this kind of thing.

  • Peter Duncanson 430 posts 1360 karma points c-trib
    Jul 19, 2013 @ 12:43
    Peter Duncanson
    0

    I did a little testing for the uComponents stuff that mocked out some bits of the Umbraco library etc. that worked pretty good.

    I created a simple wrapper that used either canned data or the Umbraco methods. All the methods I tested used this wrapper. This meant I only needed to wrap what the code needed and nothing more and could swap it out for a mock object pretty easy for testing. I really like this way of talking to a wrapper for anything that I'm dependant on to isolate my code. Do this with most things (like the TeaCommerece JS API for instance which protected us from a few API changed back in the early days). Means only one place to change your code and again easier to mock/change out. A lot of people say "yeah but when do you actually ever change anything" which I understand to a point but it does not take too much extra time if done well (and simply) and for those times you do it makes it nice and easy.

    Ideally I try to avoid talking directly to Umbraco as much as possible, where I do need to do it I like to stick it in a wrapper or a limited number of entry point methods that other methods can then use. Keeps our exposure to change low and if we need patch anything up we only have a small number of places to do it so less chance of something getting missed.

    For testing if Umbraco does what it is supposed to that should ideally be done by Umbraco's unit tests (which are getting better and better) but a little sanity checking does not go a miss.

    Can always do more, should always do more but times a killer ain't it.

  • Ravi Motha 290 posts 500 karma points MVP 7x c-trib
    Jul 19, 2013 @ 12:56
    Ravi Motha
    0

    I have to sayI think Pete's approach is the most logical,  but it depends on what you are building  eg a web application where there is a lot of necessary  and rigourous testing needed, but doing it the OffRoad way means you have fewer pressure points to test on and obviously lower exposure to change

  • Anthony Dang 1404 posts 2558 karma points MVP 3x c-trib
    Jul 19, 2013 @ 13:22
    Anthony Dang
    0

    I think of Umbraco as a datastore to persist and get data.

    When we use Entity Framework or Peta Poco, we still have linq statements and other logic.

    I'd like to mock away DynamicNode/IPublishedContent somehow and test that my own logic is correct.  

    Someone actually suggested that doing all of this in xpath might be easier to test as you can pass in raw xml.

     

  • Peter Duncanson 430 posts 1360 karma points c-trib
    Jul 19, 2013 @ 14:04
    Peter Duncanson
    0

    I like to always keep it simple. My way of testing can be a bit weird to those who first see it, looks like my code is going around hte houses a little but I do it the way I do as I've been bitten before and its hard won lessons.

    Any method that is doing some logic I'll try to have it as a static stand alone method if I can at all help it and pass in the data it needs to chew through as simple strings, bools, etc. and once its done what it needs to do it too will return either an object, string, bool, etc. Nothing too fancy and thats on purpose, less to mock out, less to complicate things, less to go wrong. Other methods that actually "do" something with the outcome of that logic can then work on getting the values to poke into it and reacting to what it returns. Talking to Umbraco "should just work" so I never bother testing that stuff, but logic to work out if a hotel is available or not can get tricky really quickly so we stick that in a method and test it. We can have extension methods or helper methods that call our logic method to make it all read nice too. Makes for nice code and easy testing should you need to. I find these days though I do less and less of it and make it far more targetted when I do (http://offroadcode.com/blog/2012/4/24/i-don't-write-many-unit-tests-anymore/)

  • Brendan Rice 538 posts 1099 karma points
    Jul 20, 2013 @ 00:06
    Brendan Rice
    0

    What you would normally do is make all the services either parameters on the constructor or (better) use properties for them. If you use a mocking framework in your tests, you can set up expectations for the service methods and return whatever data/object/collection you want from the service. Have a look at the Moq quickstarts for examples - https://code.google.com/p/moq/wiki/QuickStart.

    This approach would fit really well with Pete's coding style where you break thing down into smaller methods that only do one thing, meaning you can test that one thing.

    From my experience Unit tests are good up to a point, they almost force good practice if done right. My issue with them are that they don't test the code is doing what is supposed to according to the spec (the business rules), this gap is filled with Behaviour Driven Development (BDD), and done right in an Agile environment can replace the spec as all the tests are human readable business rules. BDD is probably better saved for compicated project with lots of business rules.

  • Charles Afford 1163 posts 1709 karma points
    Jul 21, 2013 @ 17:50
    Charles Afford
    0

    problem i have is getting the umbraco context (becuase i wanted to assert that the doc types, properties and values are expected .  For email and such.  Any ideas?  Just going to read the posts :).

  • Brendan Rice 538 posts 1099 karma points
    Jul 22, 2013 @ 22:43
    Brendan Rice
    1

    Hi Charles, Chris McKee has a Gist that may help:

    https://gist.github.com/ChrisMcKee/4961877

    Services seem to be the way to go.

    The way I would see this working in a unit test would be this:

    1. Mock out the IContentService
    2. In your test make a call to the mocked IContentService to get node by id (example), this is where you could set an expectation and return a mock object
    3. On that mock object you could set expectations to check that properties were getting set correctly

    Does this help any? 

    p.s. can someone hit me with a little Karma, I am sitting on 404 and it's freaking me out a little :) 

     

  • Anthony Dang 1404 posts 2558 karma points MVP 3x c-trib
    Jul 24, 2013 @ 11:51
    Anthony Dang
    0

    Ok so how would you TDD Umbraco event hooks?

     

  • Brendan Rice 538 posts 1099 karma points
    Jul 24, 2013 @ 14:00
    Brendan Rice
    0

    It depends if you want to test if the actual event is hooked up properly in the constructor. But in theory it is exactly the same as testing a normal method, the mock object you pass to that method may just be different. You may have to stub the objects you pass rather than mock them (worth reading up abotu the difference between stubs and mocks).

     

  • Brendan Rice 538 posts 1099 karma points
    Jul 24, 2013 @ 23:42
    Brendan Rice
    0

    I would hiughly recommend reading "The Art of Unit Testing" by Roy Osherove. There is a lot of best practice and patterns in it that will save you a bit of fumbling about.

    Another good one is "XUnit Test Patterns", though it is better as a reference, bit of a beast.

Please Sign in or register to post replies

Write your reply to:

Draft