Content

Showing posts with label xing. Show all posts
Showing posts with label xing. Show all posts

11/18/2011

Windows Phone Login

In this article i will write about our lessons learned - WP7 login page development.

Windows Phone apps are composed of pages that exist on a backstack and
can be reversed by user with the hardware back key.

There are some screens you do not want to come back. Like the login screen.
After successfully logged in, the login screen should removed from the backstack.
But explicit navigating away and from the login screen will cause to infinitly growing up your backstack. There are some solutions of keeping screens out of the backstack.

The Xing-App main page is a panorama control. The first approach for a login was kind of interesting.
We implement the login screen as a panorama item. This item is visible when you are not logged in. After successfully logged in, the item is hidden. The other items have the inverse behavior. 
In this solution we prevent the backstack problem.

While thinking about a different solution, we discussed the difference between transition and navigation. Navigation is a transition between different places. A Page is a place with a state.
But what is with this stateless pages? Here we have this splash screen or our login screen.
A common way to implement a login screen is as the first page of your app.

But is it really what you want?
While thinking about this, we came to that point the login screen can come up from everywhere in our app. The login screen has no place and it is stateless.


source: http://blogs.msdn.com/b/ptorr/archive/2010/08/28/introducing-the-concept-of-places.aspx





It is useful for example when you loose your access key and you have to login again.
The login page will popup at this place and you can continue after success.
The Silverlight Popup control is a great solution for showing content that (partially) covers the screen without doing a full navigation.You can also override the back key pressed event to handle the hardware back key to have more control over the popup.

This login behavior can also be useful for other platforms.

8/03/2011

Unit Testing for Windows Phone


In this article I am going to talk about unit testing for Windows Phone 7.
First, there is no option for a windows phone test project within the IDE.

In our XING-App we use Silverlight Unit Test Framework and NUnit as the provider for test metadata.
We have an additional test project to run unit tests called TestRunner. 
Reference these Microsoft.Silverlight.Testing.dll and Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll assemblies from the Silverlight Unit Test Framework to these project.

Note: You will get a warning about adding silverlight 3 assembly, it is fine and you can click yes to continue.

Set up the testpage
Hide the system tray to have more space if you like.

Register NUnit as the provider for test metadata (attributes etc).  That tells the silverlight testing framework to use the NUnit test attributes instead of the default MSTest attributes.

tell the silverlight testing framework to use the NUnit test attributes
  1.             UnitTestSystem.RegisterUnitTestProvider(
  2.                 new NUnitProvider());

We use an additional project for the unit tests. 
So we need to add assemblies, that contains the tests. 

Add unit tests
  1. settings.TestAssemblies.Add(typeof(Hook).Assembly);

Now any NUnit test fixture you add to the project should work.
Note that you can only have NUnit tests or MSTest tests in a project, not a mixed combination.

Create the testpage and let the unit testing framework take over.

Set the testpage
  1.  var testPage = UnitTestSystem.CreateTestPage(settings)
  2.      as MobileTestPage;
  3.  BackKeyPress += (x, xe) => xe.Cancel =
  4.      testPage.NavigateBack();
  5.  (Application.Current.RootVisual
  6.      as PhoneApplicationFrame).Content = testPage;

Using NUnit
Download the binaries from the nunit-silverlight project and add NUnit.Silverlight.Compatibility.dll and  NUnit.Silverlight.Metadata.dll as reference to the test project.
Tag your unit tests to run specific subsets of tests. When you start your TestRunner-App you can choose to only run tests with a certain tag, a certain set of tags, or not run tests with specific tags

Tagging a testmethod
  1. [Test]
  2. [Tag("UnitTestTag")]
  3. public void AlwaysPass()
  4. {
  5.     Assert.IsTrue(true, "method intended to always pass");
  6. }

Integration Tests
Now combine unit tests (modules) and test it!
For the integration tests we follow our created test plan to chose aggregates.


Id
XXXX


Test Type
Explorative / Serversimulation


Title
Logon is necessary after logout.
Test Goal
Ensure that the user has to log on again after he performs a log off.
Precondition
Same as XXXX
Steps
Automated Test: IntegrationTests.
Expected Result
The network news page is shown.
Note



Our WP7-App has a lot of asynchronous method calls like web service calls.
To test asynchronous methods you will first have to make sure your TestClass inherits from SilverlightTest.
Next, you will need to mark the test method as asynchronous. Finally, you will have to call EnqueueTestCompleted() to tell the test when it has completed.
If you do not call this then the test will never complete.

The XING-App make use of a TestBase class. This class inherits from SilverlightTest and overrides EnqueueConditional.
To make sure all tests end, EnqueueConditional becomes a timeout mechanism. The test will fails and EnqueueTestCompleted is called and the test is really completed.

Asynchronous testmethod timeout
  1.             var timer = new DispatcherTimer();
  2.             timer.Interval = new TimeSpan(0, 0,
  3.                 ConditionalTimeout);
  4.             timer.Tick += delegate
  5.             {
  6.                 // remember
  7.                 // to stop timer or it'll tick again
  8.                 timer.Stop();
  9.                 throw new TimeoutException();
  10.             };
  11.             EnqueueCallback(timer.Start);
  12.             base.EnqueueConditional(conditionalDelegate);
  13.             EnqueueCallback(timer.Stop);

Fake test server
We are in the test process and we do not want to run the tests against the live XING-Server, so we need such as a fake XING server. This fake server also helped us in the development process.
During the development we got no test XING-Accounts. The only way to test was with our live accounts. 

Our fake server is a normal web service and is similar to the XING API. We also have functions like:
  • make many users
  • make visit
  • make many messages
  • make number of contacts
These helper functions are very useful to use this test server and to write easily these integration tests.
It was also very useful to test functionality against this test server. For example, if you need some contact requests.






7/05/2011

XING-App for Windows Phone 7 Architecture



In this article I will write about our architecture for the XING-App for WP7 developed by Zühlke.
Most existing apps need connectivity to run properly. You start your app and the first you see is a "loading"-icon and in many cases working without any connection is impossible.
The default state of the XING-App is offline. First we load the local cache and display the content. The user decides when to synchronize with the server. Especially for XING it is quite useful to be able to have a quick look in your XING-Network at all times, even if you're offline. Also you will have no roaming problems. When you run the app for the first time or have no data locally cached then the app initially synchronizes with the server and saves the data in the local cache.

The application is developed using the MVVM-Pattern shown in the picture below.


Services contain web service calls. All method calls contain a success callback and an error callback. Service methods are only called from background threads. The web service responses are parsed and translated into objects. 

sample service call
  1.     IsSyncing = true;
  2.     contactService.GetContacts(
  3.         userScope.UserId, updatedContacts =>
  4.         {
  5.             this.userScope.Contacts.Data = updatedContacts;
  6.             userScope.Contacts.LastUpdated = DateTime.UtcNow;
  7.             IsSyncing = false;
  8.             HandleSuccessHandlers();
  9.             Status = StoreStatus.Online;
  10.         },
  11.         Dispatch.Action<Exception>(ex =>
  12.         {
  13.             RemoveSuccessHandle(callback);
  14.             IsSyncing = false;
  15.             HandleError(ex);
  16.         }));


Stores observe the access to a web service and manage the cache.  
The store decides if the data will come from the cache or from the web service. After the application starts the data is loaded from isolated storage. When the application is shut down,  data is saved into isolated storage. Each store has a LocalStorage class for loading and saving. These classes load the content from their own file and save the data using a BinarySerializer. The store contains the information when the data was last synchronized. And each store has its own validation time for the cache.
A store has an Offline-, Online or Broken-State.

 
The store has no UI code like INotifyPropertyChanged or ICollectionChanged. Views receive the requested data from the success callback. Each store method is called with a success callback, most likely from the ViewModel, PropertyChanged event is called to inform the UI. If an error occurs the StatusChanged event from the Store is called. In our XING-App each ViewModel implements the StatusProvider interface to handle the status changed in the UI. Therefore each page has a statusbar to display the current status. For example if there is currently no connectivity the offline status is displayed along with the time when the data was last synchronized. The color of the status depends on its state.


sample store call
  1.     IsSyncing = true;
  2.     visitStore.GetMoreVisits(loadedVisits =>
  3.     {
  4.         AppendVisits(loadedVisits);
  5.         RaisePropertyChanged("HasMoreData");
  6.         IsSyncing = false;
  7.     });

Store methods and events are only called from the UI-Thread.
The stores do not know one another.
If several methods are called in a row then the success callbacks are queued. The first web request is called and no further success callback are called during the synchronization. After the web response the upcoming success callbacks are called.
In order to ensure a better response and a better feedback of our data for the UI, the success callback is first called with the data from the local cache. The success callback is called again after the web request has sent its response.  


The ViewModel prepares the data for the UI. If a store method is called to receive data, we will actually send a web request.
All methods in the ViewModel are called from the UI-Thread. ViewModels do not know one another. You can use a message infrastructure to inform other ViewModels and your business logic is done.