Zebble
  • About Zebble
  • Compare
  • Documentation
  • Themes
  • Plug-ins
  • Contact Us

    • What is Zebble?
    • Structure of a Zebble solution
    • Zebble Designer (UWP)
    • Installing - Introduction
    • Introduction
    • ViewModel development
    • VM.EXE
    • View development
    • Dialogs
    • Lists and Collections
    • Tips and shortcuts
    • List views
    • ViewModel testing
    • Automatic Views
    • View development process
    • Hello World - Core Concepts
    • Layout: Sizing & Positioning
    • Event handling
    • Navigation
    • Alerts, Dialog, Prompt and toast
    • View lifecycle
    • Managing Files & Resources
    • Config & Debugging
    • Forms
    • Page templates
    • Device API
    • Animations
    • Web Api - Part 1 (reading data)
    • Web Api - Part 2 (post and delete)
    • Web Api - Part 3 (server vs client domain model)
    • Gesture events
    • View class
    • Zebble Markup (.zbl files)
    • Data Binding and MVVM
    • Stack class
    • Sizing and positioning
    • Layout examples
    • ScrollView class
    • Page class
    • Styling in Zebble
    • CSS property mapping to Zebble
    • Supported selectors
    • Zebble CSS: Under the hood
    • Inline styling
    • CSS real-time updates
    • Dynamic expressions in CSS
    • Gradient background colours
    • CSS Pseudo-classes support
    • Using Bold and Light Fonts in Zebble
    • Rotation in Zebble
    • Using custom fonts in Zebble
    • Flashing on tap using AutoFlash
    • Button
    • Carousel class
    • Checkbox class
    • DatePicker
    • Drawing class
    • FilePicker class
    • Grid class
    • IconButton class
    • ImageView
    • ItemPicker class
    • ListView & Grid classes
    • OptionsList
    • SearchInput class
    • Slider class
    • Switch class
    • Tabs Class
    • TextInput class
    • TextView
    • TimePicker
    • TreeView
    • Waiting Indicator
    • WebView class (displaying html)
    • C# Methods and Properties Of UI Components
    • Nav.Forward() vs Nav.Go()
    • Passing parameters to the destination page
    • Going Back
    • Showing Popup pages
    • Waiting class
    • Hardware Back button (e.g. Android)
    • NavigationBar class
    • Tabs class
    • Caching (pages)
    • Navigation without event handler
    • Use the Windows version
    • Logging messages for Debugging
    • Debugging Zebble/Plugin
    • Exception handling in Zebble
    • Debugging layout and styles
    • Zebble Device API
    • Device.Screen and orientation (landscape | portrait)
    • Code that should run on a specific platform
    • Using Lamp (aka Flash, LED and Torch)
    • Using Compass (Smooth compass)
    • Using Accelerometer (device angle)
    • Using Gyroscope (device motion speed)
    • How to Vibrate the device?
    • Launching the device browser
    • Finding device model and manufacturer
    • Responding to System events
    • Handling device shake event
    • Permissions
    • Permissions declaration (manifest files)
    • Sharing
    • Prompt for rating the app
    • Finding if Internet connection is available
    • Device messaging (Make a phone call, send SMS or Email)
    • Showing a local notification
    • Copying to Clipboard
    • Accessing device contacts
    • Reading and writing into Gallery (albums)
    • Playing & Recording Audio
    • Cache and temp files and folders
    • C# async / await
    • Understanding Zebble Threading
    • Debugging - the StackTrace problem
    • Not awaiting (running in parallel)
    • Timer (interval / scheduled running)
    • Post-render changes to the UI (dynamic)
    • Introduction of Geo location
    • Map & Location Services
    • Launch directions to a location (external)
    • Getting current Location
    • Tracking user location
    • Device.Media: Taking and picking photos
    • Playing an audio file
    • VideoPlayer class
    • Augmented reality
    • Recording audio
    • Virtual Reality
    • Speech Recognition
    • Recording or picking video
    • Playing remote videos in iOS
    • Text to speech
    • Introduction to the importance of Mobile Testing
    • Why and what to test
    • Testing mobile apps on different devices
    • Testing mobile apps
    • Xamarin Profiler
    • Performance optimization
    • Moving a view to another container at run-time
    • Attaching custom data (tag) to objects
    • Saving a view as image
    • Naming best practices
    • Fastest way to update your nuget package
    • Tips for Clean and Brief code
    • Splash screen and icon generation
    • Advice for passing Approval
    • Options for iOS app distribution
    • Test Release (internal and UAT)
    • Application Icons in IOS
    • Submitting to App Store
    • Releasing to App Store
    • Crash reporting
    • Optimized Release Build
    • Android - Generating an APK for manual installation
    • Payment (subscriptions & in-app purchases)
    • Introduction to push notifications
    • Registration process (App)
    • Push notification setup - iOS
    • Push notification setup - Android
    • Push notification setup - Windows
    • Sending a push message from the web app
    • Introduction
    • Connecting Zebble to Web API
    • Installation
    • Creating an API class
    • GET APIs
    • Calling a GET API (in the mobile app)
    • POST, PUT, PATCH and DELETE APIs
    • Domain Model
    • Web API and Authentication
    • Versioning
    • Uniquely identifying installations (token)
    • Settings file: config.xml
    • Standard Zebble settings
    • Login/Register with Facebook
    • Creating a composite component / plugin
    • Creating a Zebble component using Html and Javascript
    • CustomRenderedView: Third-party native components / plugins
    • Mapbox
    • Naming considerations
    • Random problems?
    • Display Keyboard for Visual Studio Android Emulator
    • iOS goes mad?
    • Configuring a Windows phone for ad-hoc testing
    • Fixing Error DEP0001 : Unexpected Error: -2147009287 while deploying Windows UWP app on device
    • Fixing Error DEP0001 : Unexpected Error: -1988945906 while deploying Windows UWP app on device
    • Unable tp Connect to the Mac agent from Visual Studio
    • Can't connect to the Mac agent from Visual Studio?
    • Choosing the CPU architecture
    • How to debug Zebble.Exe?
    • How to add a Device API to Zebble source?
    • About Automated UI testing
    • What should we test in mobile applications?
    • Creating an Automated UI Test in Zebble



ViewModel testing


Automated testing

Zebble provides automated UI testing support for the final application, whereby you invoke commands on the actual app UI. That style of testing is powerful, because it allows you to test the end to end functionality of the app, including logic and UI in one go. However, there are two problems with that:

  1. During ViewModel development, you will typically not have the UI to run the test against.
  2. The syntax of such tests is not strongly typed which can lead to unnecessary runtime errors (For example Tap("OK") can fail at runtime because there is no such button).

Those tests are still useful and powerful and should be used. However, you should also write unit tests against the view model alone, even before you have created the UI. This has several advantages:

  1. You can start writing tests as soon as the project starts (TDD).
  2. You have full strong typing and intellisense.
  3. They are quicker and easier to write by simply invoking viewmodel methods and property setters
  4. You can focus on the to-the-point logical flow of information irrespective of UI
  5. They run much faster and can be executed frequently

Example

In the VM project, there is a folder called Tests.

Each automated test should be a class inside that folder, inheriting from Zebble.Mvvm.TestScript.

Use standard unit testing best practices.

namespace App.Tests
{
    class FailedLoginTest : TestScript
    {
        protected override async Task SetUp()
        {
               // This method is optional. If your test requires any setup work before getting to your main test logic, you can implement it here.
              // In practice, this is more useful when creating helper TestScript base classes, from which your main test classes inherit.
        }

        protected override async Task Execute()
        {
            On<WelcomePage>().TapLogin();
            Expect(On<LoginPage>.SampleProperty == "Blah blah");
            On<LoginPage>.Email.Set("jack@gmail.com");
            On<LoginPage>.TapLogin();
            Expect("Please enter your password.");
            On<LoginPage>.Password.Set("incorrect");
            On<LoginPage>.TapLogin();
            Expect("Invalid password. Try again.");
        }
    }
}
As you can in the above example, another overload of the On<ViewModel>() method is used which gives us a shortcut to the view model instance to avoid code duplication.

It serves two purposes:

  1. Assert that the app's current active state (view model) is what you specify.
  2. Give you strongly typed access to the actual state (view model) object to invoke commands.

If the current screen in the app state is anything other than what you specify as the generic argument of the ON method, then it throws an exception.

Running a test

In VM.exe\Program.cs you can instantiate and run a test using any of the following methods:

class Program
{
    static Intention Doing = Intention.Development;

    public static async Task Main(string[] args)
    {
        Zebble.Console.Configure();
        await ViewModel.StartUp.Run();

        if (Doing == Intention.OneTest) await Test.Run<MyTest>();
        if (Doing == Intention.AllTests) await Test.RunAll();
        if (Doing == Intention.Development) await DevContext.Reach();

        if (args.None()) Zebble.Console.Start(args);
   }
}
During development time, you should change Doing to the activity that you are doing there and then:

  • OneTest: If you are developing or debugging a single test script, choose this option. Also change MyTest to the actual test.
  • AllTests: Choose this option to run all test cases in one go.
  • Development: Choose this if you're developing or debugging the view model. It is strongly recommended that you also update the script in the DevContext class to speed you up.


Test pre-conditions / setup

Often your tests will have pre conditions. You can override the SetUp() method in your TestScript classes to execute any pre-condition, so that your test code's Execute() method is semantic, lean, and focused on the actual intention and purpose of the test.

If you want to share a pre-condition in several tests, then create abstract base classes. A common example is to do "login".

/// <summary>
/// Inherit your user tests from this class.
/// </summary>
abstract class LoggedInUser : TestScript
{
    protected override async Task SetUp()
    {
        // TODO: Do the basic user login.            
    }
}

DevContext

In VM.exe project in Visual Studio, you will see a class named DevContext:

using Zebble.Mvvm;

namespace App
{
    abstract class DevContext: TestScript
    {
        // Run quick steps to get you to the context you're developing.
        public static async Task Reach()
        {
            // Run quick steps to get you to the context you're developing.
            On<WelcomePage>().TapLogin();
            On<LoginPage>().TapLogin();
            On<ShoesPage>().Items[0].Tap();
        }
    }
}

This code runs as soon as your VM.exe process starts, during development. Its purpose is to automatically run a few steps to get you to the context you're interested in.

The idea is, that as you're developing an app, you start with a basic starting page and move your way up from there. Every page, or workflow step, is developed, which then allows you to implement the next logical app function. Typically, every time you run an app, you have to take a few actions (button clicks, inputs, etc) on the pages already developed, to finally arrive at the page you're developing, i.e. the "interesting page" at that time.

The Script.cs file is a temporary, working file. It is changed continuously, and does not form a part of the final app. It's purpose is to allow you to automate those steps, and thus get you right at the final page you're currently developing and testing, without wasting time on the repeatable clicks and inputs.




‹
Zebble is a product of Geeks Ltd , a software house based in London, UK. All rights are reserved.

Telephone: +44 (0)845 643 6229

Email: hello@zebble.net

Address: 66a London Road, Morden

Greater London, United Kingdom, SM4 5BE

Privacy Statement
Terms & Conditions
Contact Us