<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Miško Hevery &#187; Flex</title>
	<atom:link href="http://misko.hevery.com/category/flex/feed/" rel="self" type="application/rss+xml" />
	<link>http://misko.hevery.com</link>
	<description>Testability Explorer</description>
	<lastBuildDate>Fri, 30 Jul 2010 02:29:04 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Testing UI &#8211; part 1</title>
		<link>http://misko.hevery.com/2008/07/05/testing-ui-part1/</link>
		<comments>http://misko.hevery.com/2008/07/05/testing-ui-part1/#comments</comments>
		<pubDate>Sun, 06 Jul 2008 03:14:53 +0000</pubDate>
		<dc:creator>misko</dc:creator>
				<category><![CDATA[Flex]]></category>

		<guid isPermaLink="false">http://s90424825.onlinehome.us/blog/?p=36</guid>
		<description><![CDATA[Lately I have been getting a lot of questions on how to test User Interface(UI) code. People always claim that UI testing is very hard or even that it is not possible. I think that with the right kind of design, UI testing is just as easy as testing any other piece of code. Let [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I have been getting a lot of questions on how to test User Interface(UI) code. People always claim that UI testing is very hard or even that it is not possible. I think that with the right kind of design, UI testing is just as easy as testing any other piece of code. Let me show you how I do unit-testing of UI in Adobe FLEX which uses ActionScript as its programming language.</p>
<p>Lets say we wish to test a common UI component such as a login page.</p>
<p align="center"><img src="http://misko.hevery.com/wp-content/uploads/2008/08/login.png" alt="" width="251" height="87" /></p>
<p>The important thing is to separate the graphical UI from the control logic and data. This can be achieved with the standard Model View Controller design pattern. Where Model is the data (username/password), View is the visual components (TextField, Button) and Controller is what glues the pieces into an interactive UI (What happens when I click Login button.) However, <strong>from testing point of view there is one important caveat which can not be broken!</strong> The source code dependence <strong>must</strong> be expressed in following order.</p>
<p align="center">View -&gt; Controller -&gt; Model</p>
<p>In other words Controller and Model can never know about the View! Neither direct or transitive dependencies are allowed. (i.e. Controller knows about X and X knows about View is just as bad as Controller knows about View). Similarly the Controller knows about the Model but model does not know about the Controller (although that requirement is not as strict.) Often times I merge the Model and the Controller into a single class if I don&#8217;t expect any reuse of the Model. Such as in this case of a login page.</p>
<p>Lets start with a Controller/Model</p>
<pre class="code">package example.flextesting {
  [Bindable]
  public class LoginPage {

    public var username:String;
    public var password:String;
    public var showError:Boolean;

    public var authenticator:Function;

    public function login():void {
      showError = authenticator(username, password);
    }

  }
}</pre>
<p>Notice how closely the Controller mimics the actual UI. Each entry field gets a field, each UI state (showError) gets its field as well, and finally each action gets a method. Also notice the <tt>[Bindable]</tt> annotation which allows any class to listen to modification in object state. In out case we want the View to be able to listen to state changes of the Controller without the controller explicitly knowing about the View.</p>
<p>Now that we have a Controller lets look at the View:</p>
<pre class="code">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;mx:VBox
  xmlns:mx="http://www.adobe.com/2006/mxml"
  xmlns:flextesting="example.flextesting.*"&gt;
  &lt;flextesting:LoginPage id="controller"/&gt;
  &lt;mx:Form&gt;
    &lt;mx:FormItem label="Username:"&gt;
      &lt;mx:TextInput text="{controller.username}"
        change="controller.username = event.currentTarget.text"/&gt;
    &lt;/mx:FormItem&gt;
    &lt;mx:FormItem label="Password:"&gt;
      &lt;mx:TextInput text="{controller.password}"
        change="controller.password = event.currentTarget.text"
        displayAsPassword="true"/&gt;
    &lt;/mx:FormItem&gt;
    &lt;mx:FormItem label="Label"&gt;
      &lt;mx:HBox&gt;
        &lt;mx:Button label="Login" click="controller.login()"/&gt;
        &lt;mx:Label text="Login Failed"
          visible="{controller.showError}"
          color="#FF0000" fontWeight="bold"/&gt;
      &lt;/mx:HBox&gt;
    &lt;/mx:FormItem&gt;
  &lt;/mx:Form&gt;

&lt;/mx:VBox&gt;</pre>
<p align="center"><img src="http://misko.hevery.com/wp-content/uploads/2008/08/login.png" alt="Login" width="251" height="87" /></p>
<p align="center"><img src="http://misko.hevery.com/wp-content/uploads/2008/08/loginfailed.png" alt="Login with Error" width="249" height="86" /></p>
<p>Notice that the View has a direct access to the controller Also notice that all of the <tt>TextInput</tt>s are bound to the corresponding fields on the Controller (In ActionScript the <tt>{controller.username}</tt> mans that the value is bound at runtime to the destination. Meaning any changes in username/password will be reflected in the text fields.) Because ActionScript data binding is not bidirectional, we also register change events on the <tt>TextInput</tt> which which copy any changes in the UI back to the controller. We then bind the &#8220;Login&#8221; button to the Controller <tt>login()</tt> method. Finally we bind the error message &#8220;Login Failed&#8221; visibility to <tt>controler.showError</tt>.</p>
<p>All this binding achieves that the Controller is fully separated from the view. So from now we can forget about the view and just worry about testing the Controller. Now many people will argue that I still can have errors in the wiring / binding process. True, but from my personal experience most errors are in the logic not in the boring wiring code. The wiring code either is broken and it does not compile or it compiles and chances are it is right. By ignoring the wiring and the graphical portion of the UI It is unlikely that I have left too many bugs in the code. Also even if I test the View I still don&#8217;t know if it &#8220;looks right&#8221; which only a human can do. So I simply take a very pragmatic approach and draw the line at the View. I get 90% of benefits with very little cost. Turns out that there are scenario based frameworks out there which will allow you to write test with full View code coverage, but those are not unit-tests and hence I will not go into them here.</p>
<p>As you may have guessed the Controller will mimic the View very closely. This is actually very desirable as you don&#8217;t want to have &#8220;impendence mismatch&#8221; when trying to do the wiring. Any &#8220;impendence mismatch&#8221; will result in marshaling code which may turn your simple binding problem into a hidden controller and hence moves logic from the true home of Controller into the bindings/view which is undesirable.</p>
<p>Lets see how the above helps testing as this very simple test shows&#8230;</p>
<pre class="code">package example.flextesting {
  import flexunit.framework.TestCase;

  public class LoginPageTest extends TestCase {

    public function testLogin():void {
      var loginPage:LoginPage = new LoginPage();
      loginPage.username = "user";
      loginPage.password = "pass";

      var log:String;
      loginPage.authenticator = function(u,p) {
        log = u + "/" + p;
        return true;
      }

      assertEquals("user/pass", log);
      assertTrue(loginPage.showError);
    }

  }
}</pre>
<p>Notice the since the Controller mimics the View the Controller forms a kind of a domain-specific-language (DSL) which is actually very useful in scripting serration tests and also in understanding what the test is doing.</p>
<p>Finally lets look at one last thing, and that is how the whole thing is wired up. Your controller will need to collaborate with your application service objects. This implies that the control is dependency-injection (DI) heavy and should therefore be injected into the view. As usual you will need a single top level factory which instantiates all of the services, Controllers, Views and service and then inject all of the references into appropriate places. Here is the FLEX equivalent of the &#8220;main method&#8221;.</p>
<pre class="code">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;mx:Application
   xmlns:mx="http://www.adobe.com/2006/mxml"
   xmlns:flextesting="example.flextesting.*"&gt;
&lt;mx:Script&gt;
  &lt;![CDATA[
    function authenticator(username:String, password:String):Boolean {
      return username != password;
    }
  ]]&gt;
&lt;/mx:Script&gt;
  &lt;flextesting:LoginView&gt;
    &lt;flextesting:controller&gt;
      &lt;flextesting:LoginPage authenticator="{authenticator}"/&gt;
    &lt;/flextesting:controller&gt;
  &lt;/flextesting:LoginView&gt;
&lt;/mx:Application&gt;</pre>
<p>Without going too much into the details of FLEX the tag element is equivalent to the <tt>new</tt> operator. So</p>
<pre class="code">&lt;flextesting:LoginPage authenticator="{authenticator}"/&gt;</pre>
<p>is same as</p>
<pre class="code">var loginPage:LoginPage = new LoginPage();
loginPage.authenticator = authenticator;</pre>
<p>Therefore the above example is the place where all of the components get instantiated and the references get passed around to appropriate objects. (Good old dependency-injection).</p>
<p>&#8211; Misko Hevery</p>
]]></content:encoded>
			<wfw:commentRss>http://misko.hevery.com/2008/07/05/testing-ui-part1/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
