Showing posts with label testing. Show all posts
Showing posts with label testing. Show all posts

Saturday, July 21, 2012

Source control/backup and testing.

So for most of my projects I have a Mercurial repository for version control (totally saved my ass when I found a bug in the submitted version of Pax while halfway through unsuccessfully updating the code to 7.1), but no backup. I thought about setting up remote repositories (I have hosting with Nearly Free Speech), but I also remembered that GitHub had recently released their Windows client. I was unable to download/install the client over the coffeeshop wifi so had to set that up at home later - now you can see the code at https://github.com/jacalata/FlashCards. If that works nicely I'll put my Pax code up there as well.

I have created a test project for my Pax app in the past, but...a long time in the past. So I found this guide (http://blogs.msdn.com/b/amit_chatterjee/archive/2011/06/26/unit-testing-the-windows-phone-7-applications.aspx) as a reminder, and also found that the dll's I had were all 7.0 projects, so updated them. Added the first couple of unit tests, more to go.  Does feel better knowing I have a test framework though :)

Sunday, February 12, 2012

Implementing asynchronous testing

So when I had got my test project set up so it at least ran, I started creating a whole set of tests, most of which just do Assert.Inconclusive("Not yet implemented"). Now I'm going through and implementing them one by one.

Class - ScheduleViewModel contains a private instance of the class Schedule. When I call ScheduleViewModel.Load(), it calls Schedule.Load(), which fires an event on completion and then the method ScheduleViewModel.LoadingComplete() handles that event. Unfortunately,  without just making everything public (or internal, but that's not much cleaner) I can't make my test aware of this event, so that it can wait to assess the results of LoadingComplete()

So what I think I'm doing here, is changing the method ScheduleViewModel.LoadingComplete to catch the event from schedule, and throw another one that will be caught by a new ScheduleViewModel.LoadReallyComplete method. This new event will be visible to the test code, so we can wait on it.

 test method:
            _viewModel = new ScheduleViewModel(pivotView, pivotParam);
            Assert.IsNotNull(_viewModel);
 
             // make sure we wait for the ScheduleLoadingComplete to happen            
            _viewModel.VM_ScheduleLoadingComplete += 
                new EventHandler<ScheduleLoadingEventArgs>(ScheduleCallback);
            _viewModel.LoadSchedule();
            // wait for our method to trigger on the event and set this to true
            EnqueueConditional(() => _callbackDone);
 
            foreach (var slice in _viewModel.EventSlices)
            {
                Assert.IsNotNull(slice);
            }
 
        //event handler helper - triggered by the ScheduleLoading event in the ScheduleViewModel, sets _callbackDone to true
        public void ScheduleCallback(object sender, ScheduleLoadingEventArgs e)
        {
            _callbackDone = true;
        } 


class under test:
  public event EventHandler<ScheduleLoadingEventArgs> VM_ScheduleLoadingComplete;
 
        // this method will be called when the Schedule instance finishes loading. It will then throw its own event
        // that will trigger the LoadPopulatedSchedule() method  
        public void Schedule_ScheduleLoadingComplete(object sender, ScheduleLoadingEventArgs e)
        {
            // throw an event for finished loading
            if (VM_ScheduleLoadingComplete != null)
            {
                VM_ScheduleLoadingComplete(this, e);
            }
        }
 
        public void LoadPopulatedSchedule(object sender, ScheduleLoadingEventArgs e)
        {
//does a lot of stuff            // Fire Event on UI Thread
            view.Dispatcher.BeginInvoke(() =>
            {
                view.OnLoadComplete();
            });
        }



Now that I'd come this far, however, I realised that I actually want to fire my event for the test right at the end of LoadPopulatedSchedule, where I'm currently firing the UI event. So I could get rid of my 'trigger on one event, raise another' method, and add the new event to the end of LoadPopulatedSchedule, right after the UI Dispatcher invoke.(It seems like I should be able to make the test trigger on the UI event, but for now this seems close enough)

Of course, once I had everything triggering correctly on events, it turned out that I actually hadn't initialised the data structure correctly in the first place, and then that I was looking at the wrong set of results, and then that I wasn't correctly clearing my test data so that every subsequent test failed. And once I'd solved all them, I found that the UI method being dispatched was calling a method that referred to variables instantiated in the xaml, so were failing with null references when run under the test harness.


Reading material from this session:
basic stack overflow question
http://blogs.infosupport.com/unit-testing-with-silverlight/
http://www.codebadger.com/blog/post/2009/09/08/Unit-Testing-Silverlight-ViewModels-%28MVVM%29-That-Make-Asynchronous-Calls.aspx

Saturday, February 11, 2012

Beginning to test

For the first two releases, I had only manual tests. This was clearly inadequate - I want to make some major changes to the app, and it's going to be pretty annoying to have to go and walk through all the app functionality after each change. I test software for a living, and I strongly believe in testing early and often - I am in theory a fan of test driven development, but I totally fell over when it came to actually building a new project from scratch. Time to fix that.

I began looking into all the test frameworks available for Windows Phone apps. There are several, and I didn't really know which way was going to be 'best' or 'easiest'. I already had the Silverlight Toolkit installed, and was working in a theoretically MVVM framework, so I looked for approaches designed to work with that. I found (among many others) these guides:
I then walked through the setup outlined in the TDD Kata, as far as the beginning of Test #1. Around this stage, I spent maybe two hours trying to get my classes to implement the interface as described, but getting blocked by the way they all inherited from phone specific classes.. So I moved away from getting 'unit tests' per the usual definition here, and wrote some more general tests - mostly only the simple ones that didn't require me building any fake objects. A few specific points that tripped me up
- A test failure (Assert.Fail or even Assert.Inconclusive) is treated as an exception during debugging, and there appears to be no way to turn this off. If, like me, you just wrote a bunch of tests that fail and you want to debug a specific one, you'll just have to Continue a lot.
- to use the (Tag[""]) functionality, you need "using Microsoft.Silverlight.Testing" and not just "using Microsoft.Silverlight.UnitTesting".

The next week, I realised that I wanted to get my app update published, and I didn't want to publish all the new test code I was writing. To get the update published ASAP, I created a new WindowsPhone Test Project, pulled out all the test code (handily saved into the Test folder for easy extraction) and shipped the existing app with a link to my survey added.

When I launched the new test project, I found that it crashed immediately when it started running the tests - and I couldn't run it in debug mode to figure out why. While looking for tips on how I should have set up this project, I found that the creator of this project, Jake Ginnivan, had done the 'building testable phone objects' work for me in the Windows Phone Essentials toolkit. Eventually I discovered that the problem was the exceptions thrown by failed tests (noted earlier) - so the Test Project was essentially useless to me. It's possible I simply missed the option to run it in debug mode, but my solution was to create a regular Windows Phone App project, and put the tests in there where I could safely run under debug mode. While investigating this I found another tutorial - Catel - Part 8 of n: WP7 Mango and unit testing the camera.

So, the current status of the project is
- need to reimplement my core MVVM framework with testable objects
- need to write actual unit tests around each base class
- I have about half the broader tests passing.Currently I'm working on one that fails because it doesn't wait for the asynchronous object population to complete. I think that's worth a whole new post.

While poking around in all these investigations, I also installed these useful looking dev tools, which I haven't yet explored: