Archive for the 'TDD' Category

09
May
10

Windows Phone 7, MVVM and TDD (Part 7 – VisualStateManager transitions)

by Peter Daukintis

So all that remains is to transition between the login ui to a welcome screen. I guess there are a number of ways of approaching this but I have decided to use the visual state manager. First, I take a copy of the ContentGrid and delete all of it’s contents, I add two text blocks – one with the text welcome in and the other data bound to the username text property in the view model.

WP7LoginContentGrid

Next, we navigate to the States panel in Expression Blend and create a new VisualStateGroup, to which we add two states; LoggedIn and NotLoggedIn.

WP7VSMUI

First, we will animate the login controls away. Select the LoggedIn state (this will put the state into recording mode), set the centre of projection to 0, 0, 0 and rotate the grid 90 degrees about the y-axis. This should produce a barn-door like animation. Click on the ‘Turn on transition preview’ button at the top of the States panel. Then clicking between the two states should display the animation.

WP7BarnDoor

Now, select the NotLoggedIn state and also select the ContentGrid_Copy and set its Opacity to zero. Now click on LoggedIn to preview the animation which should fade up the Welcome text as the login controls swing away. Also, with the NotLoggedIn state selected I scale the Welcome text text block up to 3 in x and y axes and I do a similar with the user name text block. This will result into the text elements flying into the screen whilst gradually fading in.

WP7Animating

This shows the animation part way through. But one problem remains – how do we trigger this from the View Model ?

Behaviors to the rescue again – there are some Expression samples here http://expressionblend.codeplex.com/releases/view/30080 amongst them is the DataStateBehavior. This enables, as it suggests, driving state changes from data. I downloaded the source and included it in my solution, Blend discovers it and makes it available via it’s behaviors dialog. You just drag the behavior onto the page and configure it’s parameters. I bound it to an IsLoggedIn property in my view model. Here’s the generated xaml

        <i:Interaction.Behaviors>
            <MvvmLight3_Behaviours:DataStateBehavior 
            Binding="{Binding IsLoggedIn}" 
            FalseState="NotLoggedIn" 
            TrueState="LoggedIn" 
            Value="true"  />

Another useful behavior is the GoToStateAction which you can use to configure the initial state.

And that is the end of this series of posts – I hope this has provided some ideas in how you might go about MVVM + TDD on Windows Phone 7.

Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

Windows Live Tags: MVVM,Part,VisualStateManager,Peter,Daukintis,transition,manager,ContentGrid,contents,text,data,panel,Expression,Blend,VisualStateGroup,LoggedIn,NotLoggedIn,Select,mode,projection,grid,axis,barn,door,animation,Click,Turn,preview,ContentGrid_Copy,zero,Welcome,Also,user,result,View,Model,Behaviors,DataStateBehavior,solution,IsLoggedIn,Here,Interaction,FalseState,TrueState,Value,Another,GoToStateAction,series,ideas,transitions,degrees,parameters,login,behavior

06
May
10

Windows Phone 7, MVVM and TDD (Part 6 – loading screen)

By Peter Daukintis

First we need to create the loading screen user control which is heavily based upon the one used here http://www.orktane.com/Blog/post/2010/01/23/iPhone-Sudoku-in-Silverlight-using-MVVM.aspx.

WP7LoginLoadingControl

It consists of a grid containing eight rectangles which have associated animations that cycle through different greyscales/transparencies. The code-behind shows that the user control implements the IBusyIndicator from  http://babaandthepigman.spaces.live.com/blog/cns!4F1B7368284539E5!244.entry.

    public partial class BusyIndicator : UserControl, IBusyIndicator
    {
        private readonly List<object> _tokens;

        public BusyIndicator()
        {
            // Required to initialize variables
            InitializeComponent();
            _tokens = new List<object>();
            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
                LayoutRoot.Visibility = Visibility.Collapsed;
        }

        #region Implementation of IBusyIndicator

        public void Hide(object token)
        {
            _tokens.Remove(token);
            if (_tokens.Count == 0)
            {
                LayoutRoot.Visibility = Visibility.Collapsed;
                CycleStoryboard.Stop();
            }
        }

        public void Show(object token)
        {
            _tokens.Add(token);
            if (LayoutRoot.Visibility != Visibility.Visible)
            {
                LayoutRoot.Visibility = Visibility.Visible;
                CycleStoryboard.Begin();
            }
        }

        #endregion
    }

 

Also, I will add one to the visual tree

            <myControls:BusyIndicator x:Name="BusyIndicator" d:IsHidden="True"/>

and in the MainPage code behind I will register the control with the service locator so the service can be made available:

            ServiceLocator.SetBusyIndicatorService(BusyIndicator);

This should enable the loading screen…but wait, somehow I’ve got this far without actually creating a UserRepository – so here goes…

    public class UserRepository : IUserRepository
    {
        public bool Login(string username, string password)
        {
            Thread.SpinWait(100000);
            return (username == "fred" && password == "fred");
        }
    }

and, in the MVVM Light supplied ViewModelLocator (which constructs our MainViewModel), we can pass a new UserRepository into the constructor..

        public static void CreateMain()
        {
            if (_main == null)
            {
                _main = new MainViewModel(new UserRepository());
            }
        }

And that’s it for the loading screen!

Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

Windows Live Tags: MVVM,Part,Peter,Daukintis,user,Blog,Sudoku,grid,cycle,code,implements,IBusyIndicator,BusyIndicator,UserControl,List,InitializeComponent,System,ComponentModel,DesignerProperties,GetIsInDesignMode,LayoutRoot,region,Implementation,Hide,Remove,Count,CycleStoryboard,Stop,Visible,Begin,Also,tree,Name,IsHidden,True,MainPage,ServiceLocator,SetBusyIndicatorService,UserRepository,IUserRepository,Login,password,Thread,SpinWait,ViewModelLocator,MainViewModel,CreateMain,_main,animations,username

06
May
10

Windows Phone 7, MVVM and TDD (Part 5 – creating the basic UI)

by Peter Daukintis

Okay, so we haven’t touched on any of the user interface yet but this supports the theory that we should be able to develop the user interface independently of the code. So, these are the areas we need to create for the user interface:

  • Create the user name and password inputs
  • Create a way to execute the login command
  • Create a busy indicator UserControl
  • Create a transition to a welcome screen after successfully logging in

I am going to use Expression Blend 4 RC for this part of the post as I can work more quickly inside Blend – also you will need Microsoft Expression Blend Add-in Preview 2 for Windows Phone and Microsoft Expression Blend Software Development Kit Preview 2 for Windows Phone all of which can be downloaded here http://www.microsoft.com/expression/windowsphone/.

Opening the solution up in Expression Blend looks like this:

WP7LoginRxpressionBlend

So, let’s start by dragging some input controls and a button:

            <TextBlock Text="{Binding Welcome}"
                       Style="{StaticResource PhoneTextNormalStyle}"
                       HorizontalAlignment="Center"
                       VerticalAlignment="Center"
                       FontSize="30" Margin="0,592,-12,6" />
            <Button Content="{Binding LoginButtonName}" Margin="187,239,7,0" VerticalAlignment="Top" Height="114">
            </Button>
            <TextBox Height="31" HorizontalAlignment="Left" Margin="137,57,0,0" 
                     Text="{Binding UsernameText, Mode=TwoWay, UpdateSourceTrigger=Explicit}" 
                     VerticalAlignment="Top" Width="336">
            </TextBox>
            <PasswordBox Height="31" HorizontalAlignment="Left" Margin="137,144,0,0" 
                     Password="{Binding PasswordText, Mode=TwoWay, UpdateSourceTrigger=Explicit}" 
                     VerticalAlignment="Top" Width="336" PasswordChar="*">
            </PasswordBox>
            <TextBlock HorizontalAlignment="Left" Margin="18,79,0,0"
                       Text="{Binding UsernameLabel}" VerticalAlignment="Top" TextAlignment="Right" />
            <TextBlock HorizontalAlignment="Left" Margin="33,167,0,0"
                       Text="{Binding PasswordLabel}" VerticalAlignment="Top" />

and adding some additional properties to our view model:

        public string ApplicationTitle { get { return "Application"; } }

        public string ListName { get { return "Login:"; } }

        public string LoginButtonName { get { return "Login"; } }

        public string Welcome { get { return "Welcome to My Application"; } }

        public string UsernameLabel { get { return "User Name :"; } }

        public string PasswordLabel { get { return "Password :"; } }

results in the following user interface (the view model is already bound to the DataContext of the page using the MVVM Light ViewModelLocator class):

WP7BasicUI

So, the text input parameters are bound we need to bind the click from the login button to the Login Command exposed by the MainViewModel. We will wire the button up using the EventToCommand behavior included in the MVVM Light framework. Silverlight behaviors allow some functionality to be associated with a FrameworkElement by dragging it from the toolbox onto the element in Expression Blend. To achieve this carry out the following:

WP7LoginBlendBehaviors

  • Drag EventToCommand out onto the Login button.
  • With the EventToCommand object selected in the Objects & Timelines view configure it via the properties pane.

     

    WP7LoginCommandProps

  • Click on the small blob to the right of the Command input box and choose data-binding from the options to display the data-binding dialog:

     

    WP7LoginDataBindingDlg

    from here you can see all of the view model properties and can select the LoginCommand property to complete the data-binding….nice.

    • Set the MustToggleIsEnabled to true as we want to automatically disable the button if the command is unavailable and also set the Event Name to Click if it isn’t already.

    Unfortunately, this is not enough for the behaviour I was looking for since in Silverlight there is no option to set the UpdateSourceTrigger to fire when the property changes, the best we can do is when the control loses focus. As a result the login button does not disable/enable when the fields are empty – until focus is lost from the input controls. To remedy this I have added some custom behaviors:

    namespace WP7Login.Behaviors
    {
        public class DataBindTextBoxOnPropertyChangedBehaviour : Behavior<TextBox>
        {
            public BindingExpression BindingExpression { get; set; }
    
            protected override void OnAttached()
            {
                base.OnAttached();
    
                BindingExpression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
                AssociatedObject.TextChanged += AssociatedObject_TextChanged;
            }
    
            protected override void OnDetaching()
            {
                base.OnDetaching();
                BindingExpression = null;
            }
    
            private void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
            {
                if (BindingExpression != null)
                {
                    BindingExpression.UpdateSource();
                }
            }
        }
    }
    

     

    and a similar one aimed at a password box. Once recompiled these will be available via the Assets panel in Blend and can be dragged onto the user name input and the password input boxes appropriately.

    Also, CanExecute in MainViewModel must be implemented

            private bool CanExecuteLogin()
            {
                return UsernameText.Length > 0 && PasswordText.Length > 0;
            }
    
    

    And also the RaiseExecuteChanged event must be raised in response to the data in the text boxes changing – this can be achieved by the following:

                PropertyChanged += MainViewModel_PropertyChanged;
    
    

    Subscribe to the property changed event on the view model with this handler:

            void MainViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (e.PropertyName == "UsernameText" || 
                    e.PropertyName == "PasswordText")
                {
                    var relayCommand = LoginCommand as RelayCommand;
                    if (relayCommand != null)
                    {
                        relayCommand.RaiseCanExecuteChanged();
                    }
                }
            }
    

    Finally we get the required behaviour – if either username text box or the password box is empty the login button is disabled otherwise it is enabled as we type.

    So, that’s the basic user interface in place – next we move to the loading screen and the transition when logged in….

  • Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

    Windows Live Tags: MVVM,Part,Peter,Daukintis,Okay,haven,user,interface,supports,theory,code,Create,password,indicator,UserControl,transition,Expression,Blend,Microsoft,Preview,Software,Development,solution,TextBlock,Text,Welcome,Style,StaticResource,PhoneTextNormalStyle,HorizontalAlignment,Center,VerticalAlignment,FontSize,Margin,Button,Content,LoginButtonName,TextBox,Left,UsernameText,Mode,TwoWay,UpdateSourceTrigger,Explicit,Width,PasswordBox,PasswordText,PasswordChar,UsernameLabel,TextAlignment,PasswordLabel,ApplicationTitle,Application,ListName,Login,Name,DataContext,ViewModelLocator,Command,MainViewModel,wire,EventToCommand,framework,FrameworkElement,element,reference,archive,Open,Assets,panel,Drag,Objects,Timelines,pane,Click,data,LoginCommand,Event,behaviour,option,result,custom,Behaviors,DataBindTextBoxOnPropertyChangedBehaviour,Behavior,BindingExpression,AssociatedObject,GetBindingExpression,sender,TextChangedEventArgs,UpdateSource,Once,Also,CanExecute,CanExecuteLogin,Length,response,Subscribe,handler,PropertyChangedEventArgs,PropertyName,RelayCommand,areas,parameters,options,boxes

    05
    May
    10

    Windows Phone 7, MVVM and TDD (Part 4 – Loading…)

    By Peter Daukintis

    I decided to explore the Service Locator pattern to implement handling of the busy indicator. This involves considering the busy indicator as a service which can be called upon by the view model. Again it is implemented behind an interface to support unit testing. The interface looks like this:

        public interface IBusyIndicator
        {
            void Hide(object token);
            void Show(object token);
        }
    
    

    I based this solution on this source http://www.orktane.com/Blog/post/2010/01/23/iPhone-Sudoku-in-Silverlight-using-MVVM.aspx although my implementation is slightly different. So, the idea is that I have a UserControl which implements the IBusyIndicator interface. The user control gets added into the visual tree via the xaml and is registered into a static service locator class. The view model can request the service interface and make calls into it. The runtime objects can be faked to support unit testing.

    Here’s the very simple ServiceLocator:

        public static class ServiceLocator
        {
            private static IBusyIndicator _busyIndicator;
    
            public static void SetBusyIndicatorService(IBusyIndicator busyIndicator)
            {
                _busyIndicator = busyIndicator;
            }
    
            public static IBusyIndicator BusyIndicatorServiceStatic
            {
                get
                {
                    return _busyIndicator;
                }
            }
        }
    
    

    With this new interface we can extend the Execute login command functionality. Calls to

                ServiceLocator.BusyIndicatorServiceStatic.Show(_token);
    
    

    and the corresponding hide can be made in the Execute flow. Now, this will cause NullReference exceptions in the Login command tests so we’d better go and fix these up. The following line can be inserted before the view model creation in each test method that will execute the login command

                ServiceLocator.SetBusyIndicatorService(new FakeBusyIndicator());
    
    

    where FakeBusyIndicator is defined as follows:

        public class FakeBusyIndicator : IBusyIndicator
        {
            #region Implementation of IBusyIndicator
    
            public void Hide(object token) { }
            public void Show(object token) { }
    
            #endregion
        }
    
    


    Also, the addition of a mock busy indicator:

        public class MockBusyIndicator : IBusyIndicator
        {
            public int HideCount { get; private set; }
            public int ShowCount { get; private set; }
    
            #region Implementation of IBusyIndicator
    
            public void Hide(object token) { ++HideCount; }
            public void Show(object token) { ++ShowCount; }
    
            #endregion
        }
    
    

    enables the following unit test to be implemented.

            [TestMethod]
            [Asynchronous]
            public void LoginCommand_ExecuteWithValidParameters_CausesCorrectBusyIndicatorShowHide()
            {
                var fakeUserRepository = new FakeUserRepository();
    
                var mockBusyIndicator = new MockBusyIndicator();
                ServiceLocator.SetBusyIndicatorService(mockBusyIndicator);
    
                var mainViewModel = new MainViewModel(fakeUserRepository) { UsernameText = "user", PasswordText = "pwd" };
                mainViewModel.LoginCommand.Execute(null);
    
                EnqueueConditional(() => mainViewModel.IsLoading == false);
                EnqueueCallback(() => Assert.IsTrue(mockBusyIndicator.HideCount > 0 && mockBusyIndicator.ShowCount > 0 &&
                    mockBusyIndicator.HideCount == mockBusyIndicator.ShowCount));
                EnqueueTestComplete();
            }
    
    

    A quick run of the test project shows all tests pass!

    WP7LoginAllSuccess

    So, that’s about it for the view model and the unit tests – next for the fun bit of creating the user interface and wiring up the data-binding of the view model.

    Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

    Windows Live Tags: MVVM,Part,Peter,Daukintis,Service,Locator,indicator,Again,interface,unit,IBusyIndicator,Hide,solution,Blog,Sudoku,implementation,UserControl,implements,user,tree,objects,Here,ServiceLocator,_busyIndicator,SetBusyIndicatorService,BusyIndicatorServiceStatic,Execute,_token,NullReference,Login,creation,method,FakeBusyIndicator,region,Also,addition,MockBusyIndicator,HideCount,ShowCount,TestMethod,Asynchronous,LoginCommand_ExecuteWithValidParameters_CausesCorrectBusyIndicatorShowHide,FakeUserRepository,MainViewModel,UsernameText,PasswordText,LoginCommand,EnqueueConditional,EnqueueCallback,Assert,IsTrue,EnqueueTestComplete,data,busyIndicator,endregion

    04
    May
    10

    Windows Phone 7, MVVM and TDD (Part 3 – LoginCommand)

    by Peter Daukintis

    Now, to support the login functionality I will add a password property in exactly the same way (test first) as the username text property from part 2 (http://babaandthepigman.spaces.live.com/blog/cns!4F1B7368284539E5!237.entry). Also I will supplement the tests with tests to check the values are set, similar to the following:

            [TestMethod]
            public void UsernameText_SetValue_ResultsInNewValue()
            {
                var mainViewModel = new MainViewModel();
    
                mainViewModel.UsernameText = "fred";
                Assert.AreEqual("fred", mainViewModel.UsernameText);
            }

    Now I have all the required user input properties, I will turn my attention towards how the login command will get invoked. Following the MVVM style we would like to expose some implementation code to be available to be data-bound to the user interface. Now in WPF, this can be achieved via the ICommand interface which can be bound to the ui. However, Windows Phone is based upon Silverlight 3 which has no support for the ICommand interface. There are a number of ways to hook this functionality in yourself but I will use one way provided for me by the MVVM Light framework. First I will implement the ICommand supporting code then we will see how to wire it all up.

    So, first create a new ICommand property for the login command:

            public ICommand LoginCommand { get; set; }
    

    And, in the MainViewModel constructor instantiate it with a RelayCommand:

                LoginCommand = new RelayCommand(ExecuteLogin, CanExecuteLogin);
    
    

    supplied by the MVVM Light framework. (For further information on the RelayCommand see http://babaandthepigman.spaces.live.com/blog/cns!4F1B7368284539E5!167.entry and http://msdn.microsoft.com/en-us/magazine/dd419663.aspx).

    Basically the ExecuteLogin and CanExecuteLogin are delegates which clients can supply to be called when the ICommand interface is called (ICommand has two methods CanExecute and Execute).

    These two methods declared in the MainViewModel keep everything compiling:

            private bool CanExecuteLogin() { return true; }
            private void ExecuteLogin() {  }
    
    

    Now, I have enough to begin writing tests for the login command.

    I can start my first test off with something like this:

            [TestMethod]
            public void LoginCommand_ExecutedWithValidLogin_ResultsInSuccessfulLogin()
            {
                var mainViewModel = new MainViewModel();
                mainViewModel.LoginCommand.Execute(null);
            }
    
    

    But, I am now forced to think about how my login will be provided and also what state it will act upon, since currently I have no state or behaviour to assert on in my tests. Ultimately, the login functionality will be provided by my model layer so to enable a clear separation of concerns I will use an IUserRepository interface to provide the functionality (see http://babaandthepigman.spaces.live.com/blog/cns!4F1B7368284539E5!202.entry for a discussion on why this would be a good idea). The IUserRepository is defined as follows:

        public interface IUserRepository
        {
            bool Login(string username, string password);
        }
    
    

    and our login function in our view model can call it and not really worry about how or where it is implemented.

    So, our first naive implementation of the ExecuteLogin call will just call IUserRepository::Login. But first it needs a reference to one and to keep everything nice and flexible we will allow one to be passed in to the constructor of the view model.

    So, pass it in and initialise a private field.

           public MainViewModel(IUserRepository repository)
            {
                Repository = repository;
    

    Then, our ExecuteLogin call can become:

            private void ExecuteLogin()
            {
                IsLoggedIn = Repository.Login(UsernameText, PasswordText);
            }
    

    Where IsLoggedIn is a boolean property. Back to our unit tests which will need refactoring since they will no longer compile. In order to get them compiling we need to supply a reference to an IUserRepository when we construct the view model. So we will create a Fake user repository like this:

        public class FakeUserRepository : IUserRepository
        {
            public Func<string, string, bool> LoginAction { get; set; }
    
            #region Implementation of IUserRepository
    
            public bool Login(string username, string password)
            {
                if (LoginAction != null)
                    return LoginAction(username, password);
                return true;
            }
    
            #endregion
        }
    
    

    This allows our test to modify the logic inside the Login call by providing a delegate which may be useful moving forwards. So, now in our tests each call to construct the view model can be replaced by:

                var fakeUserRepository = new FakeUserRepository();
                var mainViewModel = new MainViewModel(fakeUserRepository);
    
    

    and the test method we were working on can become this:

            [TestMethod]
            public void LoginCommand_ExecutedWithValidLogin_ResultsInSuccessfulLogin()
            {
                var fakeUserRepository = new FakeUserRepository();
                var mainViewModel = new MainViewModel(fakeUserRepository);
    
                mainViewModel.UsernameText = "fred";
                mainViewModel.PasswordText = "fred";
    
                mainViewModel.LoginCommand.Execute(null);
    
                Assert.IsTrue(mainViewModel.IsLoggedIn);
            }
    
    

    Now, we need to think a bit as the ExecuteLogin call is going to block the UI thread whilst it executes which is clearly no good in our Silverlight environment. So, if we make the login call asynchronous how will we be able to unit test it? Well, the Silverlight Unit Test framework supports this and this is how it’s done:

    Firstly, my ExecuteLogin method becomes:

            private void ExecuteLogin()
            {
                var backgroundWorker = new BackgroundWorker();
                backgroundWorker.DoWork += BackgroundWorkerDoWork;
                backgroundWorker.RunWorkerCompleted += BackgroundWorkerRunWorkerCompleted;
                backgroundWorker.RunWorkerAsync(new Userdata { Username = UsernameText, Password = PasswordText });
            }
    
            void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
            {
                var argument = e.Argument as Userdata;
                if (argument == null)
                {
                    e.Result = false;
                    return;
                }
    
                var password = argument.Password;
                var username = argument.Username;
    
                e.Result = Repository.Login(username, password);
            }
    
            private void BackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                var result = (bool)e.Result;
                IsLoggedIn = result;
    
                if (IsLoggedIn == false)
                {
                    UsernameText = string.Empty;
                    PasswordText = string.Empty;
                }
                else
                {
                    // navigate to another page...
                    //VisualStateManager.GoToState()
                }
            }
    
    

    With an additional helper class to pass around the user credentials:

        public class Userdata
        {
            public string Username { get; set; }
            public string Password { get; set; }
        }
    
    

    Now if I run my unit test the Login method will return immediately and the background worker will run on – we need to wait until the background worker finishes before we can assert on IsLoggedIn. The unit test becomes:

            [TestMethod]
            [Asynchronous]
            public void LoginCommand_ExecutedWithValidLogin_ResultsInSuccessfulLogin()
            {
                var fakeUserRepository = new FakeUserRepository();
                fakeUserRepository.LoginAction = (u, p) => true;
    
                var mainViewModel = new MainViewModel(fakeUserRepository) { UsernameText = "fred", PasswordText = "fred" };
    
                mainViewModel.LoginCommand.Execute(null);
    
                EnqueueConditional(() => mainViewModel.IsLoading == false);
                EnqueueCallback(() => Assert.IsTrue(mainViewModel.IsLoggedIn));
                EnqueueTestComplete();
            }
    
    

    First note the Asynchronous attribute added to the test method – this denotes that the test will run some async code. Also, notice the Enqueue… methods: The EnqueueConditional call will block until the condition calculates to true, so in our case when IsLoading is false (IsLoading is a boolean property set to true whilst loading is in progress, otherwise false) i.e. the loading is complete. Then we can correctly assert the IsLoggedIn property. For further details of the Enqueue methods see http://www.jeff.wilcox.name/2009/03/asynchronous-testing/.

    Sprinkle on a few more tests (test invalid login and CanExecute);

            [TestMethod]
            [Asynchronous]
            public void LoginCommand_ExecutedWithInValidLogin_ResultsInFailedLogin()
            {
                var fakeUserRepository = new FakeUserRepository();
                fakeUserRepository.LoginAction = (u, p) => false;
    
                var mainViewModel = new MainViewModel(fakeUserRepository);
                mainViewModel.LoginCommand.Execute(null);
                EnqueueConditional(() => mainViewModel.IsLoading == false);
                EnqueueCallback(() => Assert.IsFalse(mainViewModel.IsLoggedIn));
                EnqueueTestComplete();
            }
    
            [TestMethod]
            public void LoginCommand_CanExecuteReturnsTrue_GivenValidUsernameAndPassword()
            {
                var fakeUserRepository = new FakeUserRepository();
    
                var mainViewModel = new MainViewModel(fakeUserRepository) { UsernameText = "user", PasswordText = "pwd" };
    
                bool canExecute = mainViewModel.LoginCommand.CanExecute(null);
                Assert.IsTrue(canExecute);
            }
    

    Results in the following ‘green’ tests…hmmm…satisfying….

     

    WP7LoginGreenTests

    Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

    Windows Live Tags: MVVM,Part,LoginCommand,password,text,spaces,Also,TestMethod,UsernameText_SetValue_ResultsInNewValue,MainViewModel,UsernameText,Assert,AreEqual,user,attention,expose,implementation,code,data,interface,ICommand,hook,framework,wire,RelayCommand,ExecuteLogin,CanExecuteLogin,magazine,clients,CanExecute,Execute,LoginCommand_ExecutedWithValidLogin_ResultsInSuccessfulLogin,behaviour,layer,separation,IUserRepository,discussion,Login,needs,reference,repository,IsLoggedIn,PasswordText,Where,Back,unit,Fake,FakeUserRepository,Func,LoginAction,region,logic,method,IsTrue,environment,Test,supports,BackgroundWorker,DoWork,BackgroundWorkerDoWork,RunWorkerAsync,Userdata,Username,sender,DoWorkEventArgs,argument,Result,RunWorkerCompletedEventArgs,VisualStateManager,GoToState,helper,credentials,background,worker,Asynchronous,EnqueueConditional,EnqueueCallback,EnqueueTestComplete,Enqueue,Sprinkle,LoginCommand_ExecutedWithInValidLogin_ResultsInFailedLogin,IsFalse,LoginCommand_CanExecuteReturnsTrue_GivenValidUsernameAndPassword,Results,methods,babaandthepigman,blog,constructor,bool,boolean

    04
    May
    10

    Windows Phone 7, MVVM and TDD (Part 2 – The first test)

    by Peter Daukintis

    First, I will create a new project in Visual Studio using the MVVM Light project templates (MVVM Light is not a requirement really it just makes the implementation of MVVM less repetitive – any compatible MVVM framework would do, or you could just roll your own).

    NewMVVMLightProject

    I got a compatibility warning dialog when I executed this step as the version of the MVVM Light has not been updated to support the Windows Phone application manifest. This is easily fixed by adding the following to the WMAppManifest.xml file in the project.

        <Capabilities>
          <Capability Name="ID_CAP_NETWORKING" />
          <Capability Name="ID_CAP_LOCATION" />
          <Capability Name="ID_CAP_SENSORS" />
          <Capability Name="ID_CAP_MICROPHONE" />
          <Capability Name="ID_CAP_MEDIALIB" />
          <Capability Name="ID_CAP_GAMERSERVICES" />
          <Capability Name="ID_CAP_PHONEDIALER" />
          <Capability Name="ID_CAP_PUSH_NOTIFICATION" />
          <Capability Name="ID_CAP_WEBBROWSERCOMPONENT" />      
        </Capabilities>
    

     

    Build and run the application which will start up the emulator and you should see something similar to the following:

    MVVMLightAppBaseline

    Now add the unit test project as follows:

    • Add a new ‘Windows Phone Application’ project to your solution
    • WP7LoginAddTestProject
    • Rename to WP7Login.Tests
    • Delete the MainPage.xaml file
    • Set the RootVisual to a page created by the unit test framework:
      • Reference the assemblies for the Silverlight Unit Testing Framework to the project (Microsoft.Silverlight.Testing & Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight)
      • AddUnitTestAssembliesForWP7

    Edit the app.xaml.cs App constructor so it looks like this (i.e. add the code to set the RootVisual)

            public App()
            {
                UnhandledException += new EventHandler<ApplicationUnhandledExceptionEventArgs>(Application_UnhandledException);
    
                InitializeComponent();
    
                RootVisual = UnitTestSystem.CreateTestPage();
            }
    
    

    Now, set the test project as the solution startup project and run the test project. You should see something like the following:

    WP7LoginEmptyUTProjectRunning

    Since we haven’t written any tests yet there is nothing to run. So let’s start by creating a very simple test. First add a new class to the Test project called MainViewModelTests (the MVVM Light template provides us with a pre-created MainViewModel class which I will use exclusively for this demonstration). Also, the tests I will write are for demonstrative purposes – in a real life project I would strive for maximum coverage. Adorn the class with the TestClass attribute and derive it from the SilverlightTest class (from the unit test tools).

    using Microsoft.Silverlight.Testing;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace WP7Login.Tests
    {
        [TestClass]
        public class MainViewModelTests : SilverlightTest
        {
            
        }
    }
    

     

    Add a test method to the class like so…

            [TestMethod]
            public void UsernameText_SetValue_RaisesPropertyChanged()
            {
                
            }
    
    

    (I use Resharper code templates here for fast generation of the test  method signature following my preferred naming convention which is Method_Scenario_ExpectedResult).

    In order for my proposed ‘UsernameText’ property to take part in data-binding (which is crucial to support MVVM) it must support the INotifyPropertyChanged interface. My first test is to check that this works correctly.

            [TestMethod]
            public void UsernameText_SetValue_RaisesPropertyChanged()
            {
                var mainViewModel = new MainViewModel();
    
                bool propChanged = false;
                mainViewModel.PropertyChanged +=
                    (s, e) =>
                    {
                        if (e.PropertyName == "UsernameText")
                        {
                            propChanged = true;
                        }
                    };
    
                mainViewModel.UsernameText = "fred";
                Assert.IsTrue(propChanged);
            }
    
    

    This is my first go at the test. Please note that the MainViewModel class already supports the INotifyPropertyChanged interface – this is provided by the MVVM Light toolkit (by deriving from ViewModelBase). I have written this code before actually adding the property to the view model so I will also need to add the property.

     

            private string _usernameText;
    
            public string UsernameText
            {
                get { return _usernameText; }
                set
                {
                    if (_usernameText != value)
                    {
                        _usernameText = value;
                        RaisePropertyChanged(() => UsernameText);
                    }
                }
            }
    
    

    This is a standard implementation aside from the type-safe RaisePropertyChanged method. This achieves the same end result as the standard version (which takes a string of the property name as a parameter). The problem with this is that if you spell the property name wrong this can lead to some debugging pain. This is implemented as follows:

            private void RaisePropertyChanged<T>(Expression<Func<T>> action)
            {
                RaisePropertyChanged(GetPropertyName(action));
            }
    
            private static string GetPropertyName<T>(Expression<Func<T>> action) 
            {
                var expression = (MemberExpression)action.Body;
                return expression.Member.Name;
            }
    

    I added these to my view model as helpers to look up the property name automatically from the lambda expression.

    Anyway, back to the UsernameText property; once this is added I can go ahead and run the first test…Here are the results…

    WP7LoginFirstSuccessfulTest

    And, clicking on the one and only test gives some further details:

    WP7LoginFirstTestSuccessDetails

    So, that’s it – the environment is configured for basic MVVM and so we can run tests against the ViewModel.

    Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

    Windows Live Tags: MVVM,Part,Visual,Studio,requirement,implementation,framework,version,WMAppManifest,Name,ID_CAP_LOCATION,ID_CAP_SENSORS,ID_CAP_MEDIALIB,ID_CAP_GAMERSERVICES,ID_CAP_PHONEDIALER,ID_CAP_PUSH_NOTIFICATION,ID_CAP_WEBBROWSERCOMPONENT,Build,unit,Application,solution,Rename,Delete,MainPage,RootVisual,Reference,Microsoft,VisualStudio,QualityTools,Edit,code,UnhandledException,EventHandler,ApplicationUnhandledExceptionEventArgs,Application_UnhandledException,InitializeComponent,UnitTestSystem,CreateTestPage,haven,Test,MainViewModelTests,template,MainViewModel,demonstration,Also,life,coverage,Adorn,TestClass,SilverlightTest,tools,TestTools,method,TestMethod,Resharper,generation,signature,convention,Method_Scenario_ExpectedResult,UsernameText,data,interface,PropertyName,Assert,IsTrue,supports,ViewModelBase,_usernameText,result,parameter,pain,Expression,Func,action,GetPropertyName,MemberExpression,Body,Member,Anyway,Here,environment,ViewModel,templates,purposes,helpers,xaml

    04
    May
    10

    Windows Phone 7, MVVM and TDD (Part 1 – Introduction)

    by Peter Daukintis

    Before jumping into Windows Phone 7 development I need to define some ideas about a baseline architecture so I have a clear development direction to move in. This series of posts will document my thinking in this area. This is not an introductory post on any of the individual technologies and I will assume the reader has some knowledge of the basics. Here’s a list of pre-requisites:

    I intend to develop a very simple phone application using Silverlight to demonstrate and explore the architecture. The application will present a login screen and allow a user to log in. It will present some kind of busy indicator and when logged in will navigate to another screen (well, I said it would be simple :-) ).

    I will develop in a test-driven manner using a model-view-viewmodel architecture to support this. I will try to document where I have made choices along the way since I expect there will be many alternative solutions.

    Just so we’re all on the same page here’s a sneak preview of the end result.

    WP7EmulatorMenu

    Here’s a screen grab of the WP7 emulator showing the WP7Login Application and also WP7Login.Tests application. For further information about the tools and the phone emulator see http://developer.windowsphone.com/windows-phone-7-series/

    WP7LoginScreen

    Here’s the application login screen.

    WP7LoginLoading

    While it’s loading…

    WP7Welcome

    …and finally transitioning into the welcome screen.

    The unit tests will run on the phone emulator and will look like this…

    WP7LoginUnitTests

    That wraps the introduction.

    Technorati Tags: ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

    Windows Live Tags: MVVM,Part,Introduction,development,ideas,architecture,direction,series,area,reader,knowledge,basics,Here,requisites,tools,April,Refresh,FamilyID,Ultimate,Toolkit,archive,Unit,Framework,code,user,indicator,manner,Just,preview,result,Application,wraps,technologies,solutions,developer,microsoft,aspx,login,emulator

    31
    Mar
    10

    TDD Introduction

    by Peter Daukintis

    Test Driven Development

    This is a basic introduction to test-driven development describing related technologies in a simple, straightforward way. The learning curve can sometimes appear steep due to the range of associated technologies and architectural concepts that need to be understood. This post is a quick overview with some simple examples.

    Basic Principles

    TDD supports agile processes and coping with changing business requirements. It does this by enabling and promoting sound, flexible architectures which support unit testing. The test frameworks this allows, in turn, enables refactoring by providing confidence that existing functionality is not being broken. It supports a ‘clear separation of concerns’ via inversion of control patterns (http://www.martinfowler.com/articles/injection.html).  This enables dependencies to be easily replaced, promotes flexible architectures and enables runtime composition of logical components.

    Dependencies

            public IEnumerable<Stuff> GetFilteredStuff(string filter)
            {
                DatabaseLayer dbl = new DatabaseLayer();
                var stuff = dbl.GetStuffFromDB();
                return stuff.Where(stuff => stuff.Name.startsWith(filter));
            }
    

     

    This code illustrates a fixed dependency on the concrete database layer class. This prevents creation of a unit test without a database.

    Using an interface we can remove the dependency:

            public IEnumerable<Stuff> GetFilteredStuff(string filter, IDatabaseRepository repository)
            {
                if (repository.AllowsFiltering())
                {
                    var stuff = repository.GetStuffFromDb();
                    return stuff.Where(s => s.Name.StartsWith(filter));
                }
                return null;
            }
    

    Now the dependency is gone and we can unit test the method by providing a stub class which implements the IDatabaseRepository interface.

            [TestMethod]
            public void GetFilteredStuff_GivenValidFilter_ReturnsCorrectFilteredResult
            {
                IDatabaseRepsitory db = new StubDatabaseRepository();
                var result = db.GetFilteredStuff("Bob", db);
    
                // Assert expected result
            }
    

    Unit Testing

    So, working this way I can test each individual unit of logic. This promotes a flexible architecture and single responsibility classes and methods. If we were to test the original method with the database dependency by supplying a known database this would be integration testing.

    Tools

    As TDD has become more popular a network of support tools has flourished which really enable the viability of TDD. These are the main categories:

    Let’s look into each category in turn….

    Inversion of Control Containers for Dependency Injection

    To remove dependencies we can eliminate ‘new myConcreteClass’ by passing around interfaces but something has to be responsible for generating the concrete classes. In order to centralise the creation code we can make use of the factory pattern. Luckily we don’t need to write the code for the factory in this scenario since there are numerous implementations freely available. These are known as IOC (Inversion of control) containers. e.g. Unity, StructureMap, etc.

    Mocking Libraries

    Note. The terminology related to using fake implementations can be confusing: I will refer to a stub as a fake which I can configure but I will not assert against its internal state. A mock is more advanced and can track when it’s methods are called, how many times they are called, with which parameters, etc.. These values can be asserted against in your unit tests.

    In my unit tests I can use stubbed implementations for the dependent interfaces. Sometimes I would want to generate concrete stubs. However, I can use a Mocking library to automatically generate a stub. I can configure the generated stub to return what I want it to return.

    Most mocking libraries work by automatically re-implementing your interface via reflection and so are limited to stubbingmocking interfaces. Some libraries, such as Typemock Isolator and MS Moles use the .NET profiler APIs http://msdn.microsoft.com/en-us/magazine/cc301725.aspx or IL rewriting and can stub/mock any .NET class.

    Here’s an example of using a stub to test the previous example (using R|hino Mocks):

            [TestMethod]
            public void GetFilteredStuff_GivenValidFilter_ReturnsCorrectFilteredResult()
            {
                var mocks = new MockRepository();
                var repo = mocks.Stub<IDatabaseRepository>();
    
                using (mocks.Record())
                {
                    repo.Stub(t => t.AllowsFiltering()).Return(true);
                    repo.Stub(t => t.GetStuffFromDb()).Return(new List<Stuff>
                                                                  {
                                                                      new Stuff { Name = "Bob" },
                                                                      new Stuff { Name = "Fred" }
                                                                  });
                }
                using (mocks.Playback())
                {
                    var mc = new MyConcreteClass();
                    var result = mc.GetFilteredStuff("Bob", repo);
                    Assert.AreEqual(1, result);
                }
            }
    

     

    Notice that the mocking library allows me to dynamically generate the stub class which implements the IDatabaseRepository interface.

    Refactoring Tools

    Resharper is a refactoring and code productivity tool which integrates with visual studio and provides the following features:

    • Refactoring
    • Code Analysis – on the fly (squiggly lines)
    • Unit testing tools
    • Code generation tools
    • Code formatting
    • Shared coding standards

    Here’s an example of it’s usage Windows Media demo

    I personally use resharper and have found it to give a great productivity boost and generally supports my TDD coding amongst other things. (Please email me for a 10% discsount code on resharper licenses – babaandthepigman@hotmail.co.uk ).

    Calculator Kata

    To practise some TDD skills this gives an interesting exercise http://osherove.com/tdd-kata-1/ for a very simple string calculator (and some videos of people carrying out the exercise).

    That’s it for the intro….

    Technorati Tags: , test-driven,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

    Windows Live Tags: Introduction,test-driven,development,overview,Basic,Principles,supports,requirements,unit,separation,injection,composition,components,IEnumerable,GetFilteredStuff,DatabaseLayer,GetStuffFromDB,Where,Name,code,dependency,database,layer,creation,interface,IDatabaseRepository,repository,StartsWith,method,implements,TestMethod,GetFilteredStuff_GivenValidFilter_ReturnsCorrectFilteredResult,IDatabaseRepsitory,StubDatabaseRepository,result,Assert,logic,architecture,classes,integration,Tools,Inversion,Control,Containers,Wikipage,Rhino,Resharper,category,factory,scenario,StructureMap,Libraries,Note,terminology,times,Sometimes,library,Most,reflection,Some,Typemock,Isolator,APIs,magazine,Here,example,MockRepository,Stub,Record,Return,List,Playback,MyConcreteClass,AreEqual,Notice,tool,studio,features,Analysis,generation,usage,demo,Calculator,Kata,technologies,concepts,examples,articles,dependencies,methods,categories,interfaces,parameters,Moles,skills,architectures,aspx,implementations,repo




    Follow

    Get every new post delivered to your Inbox.