15 min read

This article is written by Roberto Messora, the author of the Web App Testing Using Knockout.JS book. This article will give you an overview of various design patterns used in web application testing. It will also tech you web development using jQuery.

(For more resources related to this topic, see here.)

Presentation design patterns in web application testing

The Web has changed a lot since HTML5 has made its appearance. We are witnessing a gradual shift from a classical full server-side web development, to a new architectural asset that moves much of the application logic to the client-side.

The general objective is to deliver rich internet applications (commonly known as RIA) with a desktop-like user experience. Think about web applications such as Gmail or Facebook: if you maximize your browser, they look like complete desktop applications in terms of usability, UI effects, responsiveness, and richness.

Once we have established that testing is a pillar of our solutions, we need to understand which is the best way to proceed, in terms of software architecture and development. In this regard, it’s very important to determine the very basic design principles that allow a proper approach to unit testing. In fact, even though HTML5 is a recent achievement, HTML in general and JavaScript are technologies that have been in use for quite some time.

The problem here is that many developers tend to approach the modern web development in the same old way. This is a grave mistake because, back in time, client-side JavaScript development was a lot underrated and mostly confined to simple UI graphic management.

Client-side development is historically driven by libraries such as Prototype, jQuery, and Dojo, whose primary feature is DOM (HTML Document Object Model, in other words HTML markup) management. They can work as-is in small web applications, but as soon as these grow in complexity, code base starts to become unmanageable and unmaintainable. We can’t really think that we can continue to develop JavaScript in the same way we did 10 years ago. In those days, we only had to dynamically apply some UI transformations. Today we have to deliver complete working applications.

We need a better design, but most of all we need to reconsider client-side JavaScript development and apply the advanced design patterns and principles.

jQuery web application development

JavaScript is the programming language of the web, but its native DOM API is something rudimental. We have to write a lot of code to manage and transform HTML markup to bring UI to life with some dynamic user interaction. Also not full standardization means that the same code can work differently (or not work at all) in different browsers.

Over the past years, developers decided to resolve this situation: JavaScript libraries, such as Prototype, jQuery and Dojo have come to light.

jQuery is one of the most known open-source JavaScript libraries, which was published for the first time in 2006. Its huge success is mainly due to:

  • A simple and detailed API that allows you to manage HTML DOM elements
  • Cross-browser support
  • Simple and effective extensibility

Since its appearance, it’s been used by thousands of developers as the foundation library. A large amount of JavaScript code all around the world has been built with keeping jQuery in mind. jQuery ecosystem grew up very quickly and nowadays there are plenty of jQuery plugins that implement virtually everything related to the web development.

Despite its simplicity, a typical jQuery web application is virtually untestable. There are two main reasons:

  • User interface items are tightly coupled with the user interface logic
  • User interface logic spans inside event handler callback functions

The real problem is that everything passes through a jQuery reference, which is a jQuery(“something”) call. This means that we will always need a live reference of the HTML page, otherwise these calls will fail, and this is also true for a unit test case. We can’t think about testing a piece of user interface logic running an entire web application!

Large jQuery applications tend to be monolithic because jQuery itself allows callback function nesting too easily, and doesn’t really promote any particular design strategy. The result is often spaghetti code.

jQuery is a good option if you want to develop some specific custom plugin, also we will continue to use this library for pure user interface effects and animations, but we need something different to maintain a large web application logic.

Presentation design patterns

To move a step forward, we need to decide what’s the best option in terms of testable code. The main topic here is the application design, in other words, how we can build our code base following a general guideline with keeping testability in mind.

In software engineering there’s nothing better than not to reinvent the wheel, we can rely on a safe and reliable resource: design patterns. Wikipedia provides a good definition for the term design pattern (http://en.wikipedia.org/wiki/Software_design_pattern):

In software engineering, a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design.

A design pattern is not a finished design that can be transformed directly into source or machine code. It is a description or template for how to solve a problem that can be used in many different situations.

Patterns are formalized best practices that the programmer can use to solve common problems when designing an application or system.

There are tens of specific design patterns, but we also need something that is related to the presentation layer because this is where a JavaScript web application belongs to.

The most important aspect in terms of design and maintainability of a JavaScript web application is a clear separation between the user interface (basically, the HTML markup) and the presentation logic. (The JavaScript code that turns a web page dynamic and responsive to user interaction.) This is what we learned digging into a typical jQuery web application.

At this point, we need to identify an effective implementation of a presentation design pattern and use it in our web applications. In this regard, I have to admit that the JavaScript community has done an extraordinary job in the last two years: up to the present time, there are literally tens of frameworks and libraries that implement a particular presentation design pattern.

We only have to choose the framework that fits our needs, for example, we can start taking a look at MyTodo MVC website (http://todomvc.com/): this is an open source project that shows you how to build the same web application using a different library each time.

Most of these libraries implement a so-called MV* design pattern (also Knockout.JS does). MV* means that every design pattern belongs to a broader family with a common root: Model-View-Controller. The MVC pattern is one of the oldest and most enduring architectural design patterns: originally designed by Trygve Reenskaug working on Smalltalk-80 back in 1979, it has been heavily refactored since then.

Basically, the MVC pattern enforces the isolation of business data (Models) from user interfaces (Views), with a third component (Controllers) that manages the logic and user-input. It can be described as (Addy Osmani, Learning JavaScript Design Patterns, http://addyosmani.com/resources/essentialjsdesignpatterns/book/#detailmvc):

A Model represented domain-specific data and was ignorant of the user-interface (Views and Controllers). When a model changed, it would inform its observers

A View represented the current state of a Model. The Observer pattern was used for letting the View know whenever the Model was updated or modified

Presentation was taken care of by the View, but there wasn’t just a single View and Controller – a View-Controller pair was required for each section or element being displayed on the screen

The Controllers role in this pair was handling user interaction (such as key-presses and actions e.g. clicks), making decisions for the View

This general definition has slightly changed over the years, not only to adapt its implementation to different technologies and programming languages, but also because changes have been made to the Controller part. Model-View-Presenter, Model-View-ViewModel are the most known alternatives to the MVC pattern.

MV* presentation design patterns are a valid answer to our need: an architectural design guideline that promotes the separation of concerns and isolation, the two most important factors that are needed for software testing. In this way, we can separately test models, views, and the third actor whatever it is (a Controller, Presenter, ViewModel, etc.).

On the other hand, adopting a presentation design pattern doesn’t mean at all that we cease to use jQuery. jQuery is a great library, we will continue to add its reference to our pages, but we will also integrate its use wisely in a better design context.

Knockout.JS and Model-View-ViewModel

Knockout.JS is one of the most popular JavaScript presentation libraries, it implements the Model-View-ViewModel design pattern.

The most important concepts that feature Knockout:JS are:

  • An HTML fragment (or an entire page) is considered as a View.
  • A View is always associated with a JavaScript object called ViewModel: this is a code representation of the View that contains the data (model) to be shown (in the form of properties) and the commands that handle View events triggered by the user (in the form of methods).
  • The association between View and ViewModel is built around the concept of data-binding, a mechanism that provides automatic bidirectional synchronization:
    • In the View, it’s declared placing the data-bind attributes into DOM elements, the attributes’ value must follow a specific syntax that specifies the nature of the association and the target ViewModel property/method.
    • In the ViewModel, methods are considered as commands and properties that are defined as special objects called observables: their main feature is the capability to notify every state modification

A ViewModel is a pure-code representation of the View: it contains data to show and commands that handle events triggered by the user.

It’s important to remember that a ViewModel shouldn’t have any knowledge about the View and the UI: pure-code representation means that a ViewModel shouldn’t contain any reference to HTML markup elements (buttons, textboxes, and so on), but only pure JavaScript properties and methods.

Model-View-ViewModel’s objective is to promote a clear separation between View and ViewModel, this principle is called Separation of Concerns.

Why is this so important? The answer is quite easy: because, in this way a developer can achieve a real separation of responsibilities: the View is only responsible for presenting data to the user and react to her/his inputs, the ViewModel is only responsible for holding the data and providing the presentation logic.

The following diagram from Microsoft MSDN depicts the existing relationships between the three pattern actors very well (http://msdn.microsoft.com/en-us/library/ff798384.aspx):

Thinking about a web application in these terms leads to a ViewModel development without any reference to DOM elements’ IDs or any other markup related code as in the classic jQuery style. The two main reasons behind this are:

      • As the web application becomes more complex, the number of DOM elements increases and is not uncommon to reach a point where it becomes very difficult to manage all those IDs with the typical jQuery fluent interface style: the JavaScript code base turns into a spaghetti code nightmare very soon.
      • A clear separation between View and ViewModel allows a new way of working: JavaScript developers can concentrate on the presentation logic, UX experts on the other hand, can provide an HTML markup that focuses on the user interaction and how a web application will look. The two groups can work quite independently and agree on the basic contact points using the data-bind tag attributes.

The key feature of a ViewModel is the observable object: a special object that is capable to notify its state modifications to any subscribers. There are three types of observable objects:

      • The basic observable that is based on JavaScript data types (string, number, and so on)
      • The computed observable that is dependent on other observables or computed observables
      • The observable array that is a standard JavaScript array, with a built-in change notification mechanism

On the View-side, we talk about declarative data-binding because we need to place the data-bind attributes inside HTML tags, and specify what kind of binding is associated to a ViewModel property/command.

MVVM and unit testing

Why a clear separation between the user interface and presentation logic is a real benefit? There are several possible answers, but, if we want to remain in the unit testing context, we can assert that we can apply proper unit testing specifications to the presentation logic, independently, from the concrete user interface.

In Model-View-ViewModel, the ViewModel is a pure-code representation of the View. The View itself must remain a thin and simple layer, whose job is to present data and receive the user interaction. This is a great scenario for unit testing: all the logic in the presentation layer is located in the ViewModel, and this is a JavaScript object. We can definitely test almost everything that takes place in the presentation layer.

Ensuring a real separation between View and ViewModel means that we need to follow a particular development procedure:

  1. Think about a web application page as a composition of sub-views: we need to embrace the divide et impera principle when we build our user interface, the more sub-views are specific and simple, the more we can test them easily. Knockout.JS supports this kind of scenario very well.
  2. Write a class for every View and a corresponding class for its ViewModel: the first one is the starting point to instantiate the ViewModel and apply bindings, after all, the user interface (the HTML markup) is what the browser loads initially.
  3. Keep each View class as simple as possible, so simple that it might not even need be tested, it should be just a container for:
    • Its ViewModel instance
    • Sub-View instances, in case of a bigger View that is a composition of smaller ones
    • Pure user interface code, in case of particular UI JavaScript plugins that cannot take place in the ViewModel and simply provide graphical effects/enrichments (in other words they don’t change the logical functioning)

If we look carefully at a typical ViewModel class implementation, we can see that there are no HTML markup references: no tag names, no tag identifiers, nothing. All of these references are present in the View class implementation. In fact, if we were to test a ViewModel that holds a direct reference to an UI item, we also need a live instance of the UI, otherwise accessing that item reference would cause a null reference runtime error during the test. This is not what we want, because it is very difficult to test a presentation logic having to deal with a live instance of the user interface: there are many reasons, from the need of a web server that delivers the page, to the need of a separate instance of a web browser to load the page. This is not very different from debugging a live page with Mozilla Firebug or Google Chrome Developer Tools, our objective is the test automation, but also we want to run the tests easily and quickly in isolation: we don’t want to run the page in any way!

An important application asset is the event bus: this is a global object that works as an event/message broker for all the actors that are involved in the web page (Views and ViewModels).

Event bus is one of the alternative forms of the Event Collaboration design pattern (http://martinfowler.com/eaaDev/EventCollaboration.html):

Multiple components work together by communicating with each other by sending events when their internal state changes (Marting Fowler)

The main aspect of an event bus is that:

The sender is just broadcasting the event, the sender does not need to know who is interested and who will respond, this loose coupling means that the sender does not have to care about responses, allowing us to add behaviour by plugging new components (Martin Fowler)

In this way, we can maintain all the different components of a web page that are completely separated: every View/ViewModel couple sends and receives events, but they don’t know anything about all the other couples. Again, every ViewModel is completely decoupled from its View (remember that the View holds a reference to the ViewModel, but not the other way around) and in this case, it can trigger some events in order to communicate something to the View.

Concerning unit testing, loose coupling means that we can test our presentation logic a single component at a time, simply ensuring that events are broadcasted when they need to. Event buses can also be mocked so we don’t need to rely on concrete implementation.

In real-world development, the production process is an iterative task. Usually, we need to:

      • Define a View markup skeleton, without any data-bind attributes.
      • Start developing classes for the View and the ViewModel, which are empty at the beginning.
      • Start developing the presentation logic, adding observables to the ViewModel and their respective data bindings in the View.
      • Start writing test specifications.

This process is repetitive, adds more presentation logic at every iteration, until we reach the final result.

Summary

In this article, you learned about web development using jQuery, presentation design patters, and unit testing using MVVM.

Resources for Article:


Further resources on this subject:


Packt

Share
Published by
Packt

Recent Posts

Top life hacks for prepping for your IT certification exam

I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…

3 years ago

Learn Transformers for Natural Language Processing with Denis Rothman

Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…

3 years ago

Learning Essential Linux Commands for Navigating the Shell Effectively

Once we learn how to deploy an Ubuntu server, how to manage users, and how…

3 years ago

Clean Coding in Python with Mariano Anaya

Key-takeaways:   Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…

3 years ago

Exploring Forms in Angular – types, benefits and differences   

While developing a web application, or setting dynamic pages and meta tags we need to deal with…

3 years ago

Gain Practical Expertise with the Latest Edition of Software Architecture with C# 9 and .NET 5

Software architecture is one of the most discussed topics in the software industry today, and…

3 years ago