<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5907126310633254820</id><updated>2011-11-28T02:02:43.521+02:00</updated><category term='modeling'/><category term='bug hunting'/><category term='test design'/><category term='planning'/><category term='artificial intelligence'/><category term='industry'/><title type='text'>My testing blog</title><subtitle type='html'>On software ... On testing ...On technology ... On software testing technology.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>11</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-2127611567844038289</id><published>2010-06-12T17:41:00.001+03:00</published><updated>2010-06-14T07:51:19.005+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><title type='text'>Mouse Testing</title><content type='html'>&lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/TBOnSa2zBfI/AAAAAAAAA7E/9ZCpjuswIm4/s1600-h/MouseRevenge%5B1%5D%5B4%5D.gif"&gt;&lt;img style="border-right-width: 0px; margin: 0px 25px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="MouseRevenge[1]" border="0" alt="MouseRevenge[1]" align="left" src="http://lh5.ggpht.com/_e3SRrbdPqkw/TBOnS9DOcwI/AAAAAAAAA7I/n1W3B_m7pz4/MouseRevenge%5B1%5D_thumb%5B2%5D.gif?imgmax=800" width="278" height="331" /&gt;&lt;/a&gt; I wrote in &lt;a href="http://mariusfilipontesting.blogspot.com/2010/02/power-to-shell.html" target="_blank"&gt;a previous article&lt;/a&gt; how important is for exploratory testing to be able to try ideas quickly and to use the simplest environments, tools and languages when doing testing – especially exploratory testing. I also recommended PowerShell as &lt;em&gt;the&lt;/em&gt; testing language for .NET.&lt;/p&gt;  &lt;p align="justify"&gt;In this article I try to introduce an alternative to testing with PowerShell. The alternative consists in running C# tests with only two right clicks of the mouse. In other words, mouse testing! &lt;/p&gt;  &lt;h4&gt;Ingredient No. 1: CS-Script&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://www.csscript.net/" target="_blank"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="scriptInNP[1]" border="0" alt="scriptInNP[1]" align="right" src="http://lh3.ggpht.com/_e3SRrbdPqkw/TBOB9Mw_kfI/AAAAAAAAA60/PPf3iQ5myfA/scriptInNP%5B1%5D%5B4%5D.png?imgmax=800" width="260" height="168" /&gt; CS-Script&lt;/a&gt; is a simple but effective scripting engine that transforms C# into a scripting language, with all the associated advantages. Although here is not the place to describe CS-Script, a few details are worth mentioning:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;&lt;strong&gt;Embedded dependencies:&lt;/strong&gt; CS-Script allows C# files to specify their own dependencies. Good bye project files, welcome incremental development.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;&lt;strong&gt;Windows Explorer integration:&lt;/strong&gt; CS-Script inserts in the contextual menu of Windows Explorer a special entry with the most common functionality. This makes compiling a script as easy as issuing a right click of the mouse. Moreover, the CS-Script sub-menu is &lt;em&gt;customizable&lt;/em&gt;.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;&lt;strong&gt;Conversion to Visual Studio projects:&lt;/strong&gt; as the project represented by a script and all its dependencies grows, the user can convert it into a Visual Studio project. The original C# code remains unchanged.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;The simplest way to see the power of &lt;strong&gt;CS-Script&lt;/strong&gt; is to try it. &lt;a href="http://www.csscript.net/CurrentRelease.html" target="_blank"&gt;Install CS-Script&lt;/a&gt; and save the following content into &lt;font face="Courier New"&gt;triangle.cs&lt;/font&gt;:     &lt;br /&gt;    &lt;br /&gt;&lt;code style="text-color: blue"&gt;class Triangle      &lt;br /&gt;&lt;/code&gt;&lt;code&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static bool Is(int a, int b, int c)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return a &amp;gt; 0 &amp;amp;&amp;amp; b &amp;gt; 0 &amp;amp;&amp;amp; c &amp;gt; 0 &amp;amp;&amp;amp;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; a &amp;lt; b + c &amp;amp;&amp;amp;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; b &amp;lt; a + c &amp;amp;&amp;amp;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; c &amp;lt; a + b;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;  &lt;p align="justify"&gt;Go to Windows Explorer, right click &lt;font face="Courier New"&gt;triangle.cs&lt;/font&gt; and then select &lt;code&gt;CS-Script | Compile to | DLL (Debug)&lt;/code&gt;. CS-Script will produce &lt;code&gt;triangle.dll&lt;/code&gt; and &lt;code&gt;triangle.pdb&lt;/code&gt;.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;h4&gt;Ingredient No. 2: NUnit&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://nunit.org/" target="_blank"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="logo_nunit" border="0" alt="logo_nunit" align="left" src="http://lh6.ggpht.com/_e3SRrbdPqkw/TBOcJb-pLkI/AAAAAAAAA64/62VC4xJHtR0/logo_nunit%5B4%5D.gif?imgmax=800" width="260" height="148" /&gt; NUnit&lt;/a&gt; is the de-facto standard for unit testing and, besides many qualities, it permits the execution of tests with the right click of the mouse. We shall rely on this feature to do “mouse testing”.&lt;/p&gt;  &lt;p align="justify"&gt;Before proceeding any further, CS-Script must have a grip on the DLLs that the tests employ from NUnit. For our example simply copy from the installation directory of NUnit the &lt;code&gt;.\bin\net-2.0\framework\nunit.framework.dll&lt;/code&gt; library and place it into the same directory as &lt;code&gt;triangle.cs&lt;/code&gt;.     &lt;br /&gt;&lt;/p&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h4&gt;Writing and executing the tests&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/TBOcKJYd1hI/AAAAAAAAA68/dKBpZ5Injzs/s1600-h/writing%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="writing[1]" border="0" alt="writing[1]" align="right" src="http://lh3.ggpht.com/_e3SRrbdPqkw/TBOcKsnRg1I/AAAAAAAAA7A/ktDqKOMd22g/writing%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="211" /&gt;&lt;/a&gt; Create a file named &lt;code&gt;triangle_t.cs&lt;/code&gt; into the same directory as &lt;code&gt;triangle.cs&lt;/code&gt; with the following content:     &lt;br /&gt;&lt;code&gt;     &lt;br /&gt;//css_import triangle;       &lt;br /&gt;      &lt;br /&gt;&lt;/code&gt;&lt;code&gt;using NUnit.Framework;      &lt;br /&gt;      &lt;br /&gt;&lt;/code&gt;&lt;code&gt;[TestFixture]      &lt;br /&gt;class TriangleTest       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [Test]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void Fail000()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Assert.IsFalse(Triangle.Is(0, 0, 0));       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;  &lt;p align="justify"&gt;Right click &lt;code&gt;triangle_t.cs&lt;/code&gt; in Windows Explorer then select &lt;code&gt;CS-Script | Compile to | DLL (Debug)&lt;/code&gt;) and then right click &lt;code&gt;triangle_t.dll&lt;/code&gt; in Windows Explorer and select &lt;code&gt;Run Tests&lt;/code&gt;. Windows Explorer will launch NUnit and from there you can execute the &lt;code&gt;Fail000&lt;/code&gt; test.&lt;/p&gt;  &lt;h4&gt;When two is too much&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/TBOnTYorP6I/AAAAAAAAA7U/nq1idq58ukw/s1600-h/One-EyedLisa%5B1%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="One-EyedLisa[1]" border="0" alt="One-EyedLisa[1]" align="right" src="http://lh3.ggpht.com/_e3SRrbdPqkw/TBOnT8lIIqI/AAAAAAAAA7Y/8jGX4JSh5w4/One-EyedLisa%5B1%5D_thumb.jpg?imgmax=800" width="174" height="260" /&gt;&lt;/a&gt; If issuing two right clicks to do testing feels too much of a burden, then the whole stuff (compilation and NUnit launch) can be carried out in just one right click of mouse. This version requires a little bit more work but it’s a one time effort.&lt;/p&gt;  &lt;p align="justify"&gt;Do the following steps:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="justify"&gt;Within the directory of CS-Script, create a directory named &lt;font face="Courier New"&gt;28.Test with&lt;/font&gt; under &lt;code&gt;.\bin\Lib\ShellExtensions\CS-Script&lt;/code&gt; (use a higher number if &lt;code&gt;28&lt;/code&gt; is already used). &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;Within the &lt;font face="Courier New"&gt;28.Test with&lt;/font&gt; directory create a file named &lt;code&gt;00.NUnit.c.cmd&lt;/code&gt; with the following content:         &lt;br /&gt;        &lt;br /&gt;&lt;code&gt;@echo off          &lt;br /&gt;          &lt;br /&gt;rem -------------------------------------------------           &lt;br /&gt;rem WARNING! Change the path of NUnit accordingly           &lt;br /&gt;set NUNIT_PATH=&lt;font color="#ff0000"&gt;&lt;strong&gt;%ProgramFiles%\nunit 2.5.5\bin\net-2.0&lt;/strong&gt;&lt;/font&gt;           &lt;br /&gt;rem -------------------------------------------------           &lt;br /&gt;          &lt;br /&gt;set CSPATH=           &lt;br /&gt;set CSNAME=           &lt;br /&gt;for %%I in (%1) do (           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; set CSPATH=%%~pI           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; set CSNAME=%%~nI           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; )           &lt;br /&gt;set DLLNAME=%CSPATH%%CSNAME%.dll           &lt;br /&gt;          &lt;br /&gt;@echo Copying NUnit libraries into &amp;quot;%CSPATH%&amp;quot; ...           &lt;br /&gt;copy /y &amp;quot;%NUNIT_PATH%\framework\*.dll&amp;quot; &amp;quot;%CSPATH%&amp;quot;           &lt;br /&gt;copy /y &amp;quot;%NUNIT_PATH%\lib\*.dll&amp;quot; &amp;quot;%CSPATH%&amp;quot;           &lt;br /&gt;if ERRORLEVEL 1 goto Error           &lt;br /&gt;          &lt;br /&gt;@echo Compiling %1 ...           &lt;br /&gt;cscs /cd %1           &lt;br /&gt;if ERRORLEVEL 1 goto Error           &lt;br /&gt;          &lt;br /&gt;@echo Launching NUnit with &amp;quot;%DLLNAME%&amp;quot; ...           &lt;br /&gt;&amp;quot;%NUNIT_PATH%\nunit.exe&amp;quot; &amp;quot;%DLLNAME%&amp;quot;           &lt;br /&gt;          &lt;br /&gt;:Error           &lt;br /&gt;pause&lt;/code&gt;         &lt;br /&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;Replace the path to NUnit with the directory where NUnit resides on your computer (see the &lt;font color="#ff0000"&gt;red&lt;/font&gt; text from above). &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;In Windows Explorer right click &lt;font face="Courier New"&gt;triangle_t.cs&lt;/font&gt; and then select &lt;code&gt;CS-Script | Test with | NUnit&lt;/code&gt;. The underlying script will compile and run the tests under NUnit. &lt;strong&gt;OBS:&lt;/strong&gt; this command copies locally all the DLLs from the NUnit distribution.&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;Software testing requires the ability to try quickly new ideas as the program under test is being explored by the test engineer. Simple, straightforward tools are essential for such endeavor.&lt;/p&gt;  &lt;p align="justify"&gt;With the aid of CS-Script and NUnit the software test engineer can compile and run .NET tests quickly and efficiently with just a few mouse clicks, without the need of a fully fledged development environment.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-2127611567844038289?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/2127611567844038289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/06/mouse-testing.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/2127611567844038289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/2127611567844038289'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/06/mouse-testing.html' title='Mouse Testing'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_e3SRrbdPqkw/TBOnS9DOcwI/AAAAAAAAA7I/n1W3B_m7pz4/s72-c/MouseRevenge%5B1%5D_thumb%5B2%5D.gif?imgmax=800' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-3391220288972936421</id><published>2010-04-13T23:35:00.001+03:00</published><updated>2010-05-04T12:30:07.029+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><category scheme='http://www.blogger.com/atom/ns#' term='modeling'/><title type='text'>Model-Based Long Haul Testing</title><content type='html'>&lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S8b6obM3S_I/AAAAAAAAAzQ/8EfkGGQyIt8/s1600-h/stairs3%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="stairs3[1]" border="0" alt="stairs3[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S8b6o-a5hWI/AAAAAAAAAzU/rx8wHU2Sj7Y/stairs3%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="277" height="331" /&gt;&lt;/a&gt; “Long-haul” is an important testing technique aiming to simulate product usage over an extended period of time. Such kind of testing is necessary because some difficult bugs in software may get caught via long-haul usage only.&lt;/p&gt;  &lt;p align="justify"&gt;Model-based testing is an advanced testing methodology that promises to increase the productivity of the professional tester. I discussed some aspects of modeling and model-based testing in previous articles: &lt;a href="http://mariusfilipontesting.blogspot.com/2010/02/how-much-intelligence-in-software.html" target="_blank"&gt;here&lt;/a&gt;, &lt;a href="http://mariusfilipontesting.blogspot.com/2010/02/model-based-software-testing-and.html" target="_blank"&gt;here&lt;/a&gt;, &lt;a href="http://mariusfilipontesting.blogspot.com/2010/03/frequency-based-test-strategies-with.html" target="_blank"&gt;here&lt;/a&gt; and &lt;a href="http://mariusfilipontesting.blogspot.com/2010/03/testing-modal-forms-with-nmodel.html" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;Model-based testing implies that the test developer has &lt;em&gt;less&lt;/em&gt; control over test scenarios in exchange for increased productivity. This may seem at odds with long-haul testing which requires &lt;em&gt;more&lt;/em&gt; control over the test runs.&lt;/p&gt;  &lt;p align="justify"&gt;Can we reconcile the two approaches? This article tries to give an answer.&lt;/p&gt;  &lt;h4&gt;What exactly is long haul testing?&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S8TVap6lq3I/AAAAAAAAAx4/i--NSKzxOsI/s1600-h/corbis_rf_photo_of_dog_chasing_tail%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="corbis_rf_photo_of_dog_chasing_tail[1]" border="0" alt="corbis_rf_photo_of_dog_chasing_tail[1]" align="right" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S8TVbGAt62I/AAAAAAAAAx8/-CVB0-ibNcE/corbis_rf_photo_of_dog_chasing_tail%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="183" /&gt;&lt;/a&gt;&amp;#160; Informally speaking, long haul testing is a repetition of select functional scenarios. The goal is to emulate long-term usage – days, weeks or months – without having to wait days, weeks or months. Another goal is to detect special software bugs such as memory leaks that accumulate slowly.&lt;/p&gt;  &lt;p align="justify"&gt;Let us consider Microsoft Word users. People using documents heavily may open dozens of files a day within a single Word session. We may assume that some of these people keep Word open for days or even weeks in a row. This means that Word must be able to open and then close hundreds or even thousands of documents in a single session.&lt;/p&gt;  &lt;p align="justify"&gt;We can test this via automation: we write a test script that opens and then closes a document. Then we run the script 10000 times. If each round takes less than a second then we are done in less than three hours.&lt;/p&gt;  &lt;p align="justify"&gt;Something more complex – like &lt;em&gt;open&lt;/em&gt;, &lt;em&gt;edit&lt;/em&gt; a little and &lt;em&gt;close&lt;/em&gt;? No problem. We write a little test script doing just that (&lt;em&gt;open&lt;/em&gt;, &lt;em&gt;edit&lt;/em&gt; a little, &lt;em&gt;close&lt;/em&gt;), we run it 10000 times and voilà, we have long haul testing for &lt;em&gt;open&lt;/em&gt;-&lt;em&gt;edit&lt;/em&gt; a little-&lt;em&gt;close&lt;/em&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;It seems long haul is no big deal: we take a scenario, we run it many times, we check that the system under test is nice and happy. If it is, we’re done. If not, we file a bug.&lt;/p&gt;  &lt;p align="justify"&gt;However, this is not what happens in real life. It is true that people do open and close documents and it is true that they usually edit a little in between. However, it’s not the same kind of editing that takes place. Yet, the dumb repetition of the same scenario over and over again does just that: it repeats. Quite boring.&lt;/p&gt;  &lt;p align="justify"&gt;The question is: can we diversify the enacted scenarios to resemble as much as possible what happens in the actual usage extended over a long period of time?&lt;/p&gt;  &lt;p align="justify"&gt;Yes, we can and this is where modeling comes to play.&lt;/p&gt;  &lt;h4&gt;Models as simplified behavior&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S8TaUhfNOoI/AAAAAAAAAyw/9HggjrGxr-g/s1600-h/dog_close%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="dog_close[1]" border="0" alt="dog_close[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S8TaVABKkRI/AAAAAAAAAy0/1d9brXcesd8/dog_close%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="208" /&gt;&lt;/a&gt; A model of a software system may be seen as a simplification of the system’s behavior. Therefore, analyzing the behavior of a model means, in fact, analyzing the behavior of the actual system. By consequence, long haul testing may be seen as enforcing those model behaviors that last as long as possible, up to a limit imposed by the tester.&lt;/p&gt;  &lt;p align="justify"&gt;How this “long lasting” behavior gets represented depends heavily upon the model. For state-based models, this means finding long paths within the state graph – cycles are great for such purpose. For models represented the functional way, this means detecting recursions. For models represented as iterative executions, this means detecting loops.&lt;/p&gt;  &lt;p align="justify"&gt;This article deals with state-based models with NModel because this is the framework I’ve been talking about in my previous posts.&lt;/p&gt;  &lt;h5&gt;Long paths! How long?&lt;/h5&gt;  &lt;p align="justify"&gt;When we are talking about long paths within the state graph of a model we’re actually talking about chains of states that do not end or that end as late as possible. It is impossible to process the state graph of a real life model since the number of states is virtually infinite. All we can do it is to try to &lt;em&gt;avoid&lt;/em&gt; the end states as much as possible.&lt;/p&gt;  &lt;h4&gt;Avoiding the end&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S8TVcRrmaGI/AAAAAAAAAyI/zPzMZYPwwTg/s1600-h/MobiusStrip14.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Mobius-Strip[1]" border="0" alt="Mobius-Strip[1]" align="right" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S8TVcpq7lpI/AAAAAAAAAyM/92P-7X1i6ME/MobiusStrip1_thumb2.jpg?imgmax=800" width="260" height="242" /&gt;&lt;/a&gt; Fortunately enough, NModel lets us know whether a state is final or not. Unfortunately enough, we do not have any means to “think reversely”, i.e. to go backwards from a final state towards the states that are leading to it. In the absence of such “reverse thinking” we have to resort to probabilities.&lt;/p&gt;  &lt;p align="justify"&gt;Theoretically we can assign to any state &lt;code&gt;S&lt;/code&gt; a probability of the event consisting in “the automaton reaches a final state when commencing from &lt;code&gt;S&lt;/code&gt;”. However, computing this probability is virtually impossible. We have to approximate it - we’ll see below how.&lt;/p&gt;  &lt;p align="justify"&gt;Given that it’s hard to asses the states themselves since they come in fabulous numbers, we have to replace them with state transitions – whose number is finite. We used this technique with &lt;a href="http://mariusfilipontesting.blogspot.com/2010/03/frequency-based-test-strategies-with.html" target="_blank"&gt;frequency-based testing&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;Putting in buckets&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S8TVdLLhsgI/AAAAAAAAAyQ/8TJGqGDFoBU/s1600-h/manbucketPA_450x726%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="manbucketPA_450x726[1]" border="0" alt="manbucketPA_450x726[1]" align="left" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S8TVdua7nlI/AAAAAAAAAyU/oKWR_lp7TiI/manbucketPA_450x726%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="169" height="260" /&gt;&lt;/a&gt;Assuming we are talking about actions from this point on, we can approximate the above mentioned probabilities by using a recursively defined set of distinct collections (“buckets” of actions):     &lt;br /&gt;    &lt;br /&gt;&amp;#160; 1. each action that leads to a final state at least once goes to &lt;code&gt;Bucket&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt;.     &lt;br /&gt;&amp;#160; 2. if an action &lt;code&gt;A&lt;/code&gt; gets followed by an action &lt;code&gt;B&lt;/code&gt; from &lt;code&gt;Bucket&lt;sub&gt;N&lt;/sub&gt;&lt;/code&gt;, then:     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2.1 if &lt;code&gt;A&lt;/code&gt; doesn’t belong to any “bucket”, then it goes to &lt;code&gt;Bucket&lt;sub&gt;N+1&lt;/sub&gt;&lt;/code&gt;.     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2.2 if &lt;code&gt;A&lt;/code&gt; belongs to &lt;code&gt;Bucket&lt;sub&gt;M&lt;/sub&gt;&lt;/code&gt;, then it’s moved (if necessary) to &lt;code&gt;Bucket&lt;sub&gt;min(M, N+1)&lt;/sub&gt;&lt;/code&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;Any action that remains outside the “buckets” may be considered as belonging to a “bucket” with a very high index, like &lt;code&gt;Bucket&lt;sub&gt;Count+1&lt;/sub&gt;&lt;/code&gt; where&amp;#160; &lt;code&gt;Count&lt;/code&gt; is the number of buckets. Obviously, the set of “buckets” must persist between test runs for the whole system to have any meaning.&lt;/p&gt;  &lt;p align="justify"&gt;When executed repeatedly, the transitions from one state to another will make the actions to “bubble up” from “bucket” to “bucket” towards &lt;code&gt;Bucket&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; until the whole system eventually stabilizes.&lt;/p&gt;  &lt;p align="justify"&gt;At that moment the “bucket” system tells us how probable is for a certain action to lead to a final state: the lower the index of the “bucket”, the higher the probability of the action to lead to a final state. Naturally, &lt;code&gt;Bucket&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; corresponds to the probability 1 of the event “may lead to a final state”.&lt;/p&gt;  &lt;h4&gt;In (Markov) chains&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S8cYGlt-JzI/AAAAAAAAAzY/GiuZFnhTaZU/s1600-h/chained_to_desk%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="chained_to_desk[1]" border="0" alt="chained_to_desk[1]" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S8cYG0FWKcI/AAAAAAAAAzc/uSwl-rnrDhY/chained_to_desk%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="181" /&gt;&lt;/a&gt; Not all the actions are equal within the same “bucket”. Some actions lead to “buckets” placed further away from &lt;code&gt;Bucket&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt;, other actions get closer to &lt;code&gt;Bucket&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt; (but no closer than the “bucket” immediately next to them, otherwise they move to another “bucket” further up).&lt;/p&gt;  &lt;p align="justify"&gt;It is important to choose those actions that lead to “buckets” as farthest away as possible from &lt;code&gt;Bucket&lt;sub&gt;1&lt;/sub&gt;&lt;/code&gt;. How can we know upfront to what “bucket” a certain action will lead?&lt;/p&gt;  &lt;p align="justify"&gt;We cannot know that precisely since the actual states get constructed on the fly. Yet, we can keep an &lt;em&gt;average target index&lt;/em&gt; obtained from averaging the indexes of all the “buckets” that the action has lead to in the past. The greater this average target index is, the lower the chances that the action will lead to a final state so the more eligible that action should become. This approach resembles the state machines with probabilistic transitions known as Markov chains (hence the title of the section).&lt;/p&gt;  &lt;p align="justify"&gt;Because the “bucket” of a certain action changes over time, it is not recommended to keep an average of all the target indexes from the very beginning but it’s better to use a formula that gives more weight to the newest occurrences and gradually “forgets” the oldest ones.&lt;/p&gt;  &lt;p align="justify"&gt;An appropriate formula is:&lt;/p&gt;  &lt;p align="justify"&gt;&lt;code&gt;Avg&lt;sub&gt;N&lt;/sub&gt; = Avg&lt;sub&gt;N-1&lt;/sub&gt; + (Target&lt;sub&gt;N&lt;/sub&gt;-Avg&lt;sub&gt;N-1&lt;/sub&gt;)*K&lt;/code&gt;&lt;/p&gt;  &lt;p align="justify"&gt;where &lt;code&gt;Target&lt;sub&gt;N&lt;/sub&gt;&lt;/code&gt; is the current index of the target “bucket”, &lt;code&gt;Avg&lt;sub&gt;N-1&lt;/sub&gt;&lt;/code&gt; is the previous average index and &lt;code&gt;Avg&lt;sub&gt;N&lt;/sub&gt;&lt;/code&gt; is the new average index. &lt;code&gt;K&lt;/code&gt; is a number greater than &lt;code&gt;0&lt;/code&gt; and smaller than &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;By decomposing the recursive formula from above one can see that&amp;#160; it’s actually a weighted sum of all the previous target indexes, the weights being powers of &lt;code&gt;(1-K)&lt;/code&gt;. This summed geometric progression with a factor smaller than &lt;code&gt;1&lt;/code&gt; leads to the older indexes getting “forgotten”. A value of &lt;code&gt;K&lt;/code&gt; closer to &lt;code&gt;0&lt;/code&gt; produces more stability but also more latency (more past values are relevant).&lt;/p&gt;  &lt;h4&gt;Choosing wisely&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S8TVd9MLssI/AAAAAAAAAzg/wwFixpxKBPM/s1600-h/choose1%5B1%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="choose1[1]" border="0" alt="choose1[1]" align="left" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S8TVenbywVI/AAAAAAAAAzk/t-ORURZ3hCM/choose1%5B1%5D_thumb.jpg?imgmax=800" width="260" height="240" /&gt;&lt;/a&gt; The “bucket” system adorned with average target indexes makes choosing the next action an easy task: we parse the “buckets” from the highest index towards 0 until we reach a “bucket” that has at least one action that can follow the current action. From that “bucket” we choose the eligible action with the highest average target index.&lt;/p&gt;  &lt;p align="justify"&gt;Assuming the bucket &lt;code&gt;(“bucket index”, “average target index”)&lt;/code&gt; couple is a fairly good approximation of the chance to reach a final state from a given state, it results that the final states get avoided without the cost of exploring the state space in its entirety.&lt;/p&gt;  &lt;p align="justify"&gt;The “bucket” system is not perfect, of course. The probability approximations given by the &lt;code&gt;(“bucket index”, “average target index”)&lt;/code&gt; pairs are pretty coarse in the beginning so the first runs may not be particularly long.&lt;/p&gt;  &lt;p align="justify"&gt;Yet, as the runs repeat, the “bucket” system stabilizes and it yields longer and longer sequences – up to detecting and following infinite cycles within the state graph.&lt;/p&gt;  &lt;h4&gt;Avoiding boredom&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S8TdMEiKXDI/AAAAAAAAAzo/JUwj0UW2AgA/s1600-h/sluggo%2Bon%2Brepetition%5B1%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="sluggo on repetition[1]" border="0" alt="sluggo on repetition[1]" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S8TdMqIGYRI/AAAAAAAAAzs/VKFLy1LqoPk/sluggo%2Bon%2Brepetition%5B1%5D_thumb.png?imgmax=800" width="199" height="260" /&gt;&lt;/a&gt; The bucket system is efficient at avoiding final states – hence producing longer paths – yet it has a major drawback: it is completely ignorant of how often a certain action has been selected. Recall that the average target index of an action evaluates only how far away from the final states the action will lead and not how many times the action has been executed.&lt;/p&gt;  &lt;p align="justify"&gt;The result of this ignorance is that the system may get stuck within an infinite cycle without ever trying to escape because choosing the same action or group of actions over and over again doesn’t correlate with the probability of leading towards a final state. Moreover, the chance of such dull repetitions grows tremendously if the cycle at fault is in the proximity of the start state.&lt;/p&gt;  &lt;p align="justify"&gt;So, we must provide a mechanism to “spice up” the selection of actions so that the system under test doesn’t get “bored” from being exercised the same way for a too long time.&lt;/p&gt;  &lt;p align="justify"&gt;The next section suggests some ways to do it.&lt;/p&gt;  &lt;h4&gt;“Spycing up” test scenarios&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S8TVfyxp34I/AAAAAAAAAz0/QMYmOAubVN8/s1600-h/hot-flashes-spicy-foods%5B1%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="hot-flashes-spicy-foods[1]" border="0" alt="hot-flashes-spicy-foods[1]" align="left" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S8TVgSag7aI/AAAAAAAAAz8/Fl-1ViqOYxc/hot-flashes-spicy-foods%5B1%5D_thumb.jpg?imgmax=800" width="260" height="206" /&gt;&lt;/a&gt; There is more than one way to increase the variety of path selection and to produce more lively scenarios. We discuss several of them from the most simple to more complex.&lt;/p&gt;  &lt;h5&gt;Randomizing&lt;/h5&gt;  &lt;p align="justify"&gt;The first method is to randomize. If two actions belong to the same “bucket” and have about the same average target index, then choose one randomly.    &lt;br /&gt;    &lt;br /&gt;&lt;strong&gt;Pros:&lt;/strong&gt; the method is simple.     &lt;br /&gt;&lt;strong&gt;Cons:&lt;/strong&gt; it doesn’t really avoid infinite loops if all the eligible actions lead to such loops.&lt;/p&gt;  &lt;h5&gt;Adding frequencies to the “buckets”&lt;/h5&gt;  &lt;p align="justify"&gt;The second method is to combine the average target index with the frequency computed according to the method shown &lt;a href="http://mariusfilipontesting.blogspot.com/2010/03/frequency-based-test-strategies-with.html" target="_blank"&gt;in a previous post&lt;/a&gt;. We can do that in at least two ways:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="justify"&gt;we choose &lt;em&gt;first&lt;/em&gt; by average target index (rounded to integers) and &lt;em&gt;then&lt;/em&gt; by frequency.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;we compute a number based on average target index &lt;em&gt;and&lt;/em&gt; frequency and we choose based on that number. A simple way to compute that number is to divide the average target index by the frequency. It is not advisable to do another operation because both count and reverse of frequency are akin to probability measures whereas their combination is akin to intersecting probabilistic events.&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p align="justify"&gt;The first way preserves the probability of avoiding a final state better. The second way preserves the chance to avoid boring infinite loops better.    &lt;br /&gt;    &lt;br /&gt;&lt;strong&gt;Pros:&lt;/strong&gt; the method preserves the general framework based on “buckets”.     &lt;br /&gt;&lt;strong&gt;Cons:&lt;/strong&gt; if all the states within a certain “bucket” lead to infinite cycles there’s still chance to get stuck in unproductive repetitions.&lt;/p&gt;  &lt;h5&gt;Combining “buckets”, target indexes and frequencies together&lt;/h5&gt;  &lt;p align="justify"&gt;The third method consists in maintaining a value &lt;code&gt;f(bucket_index, average_target_index, frequency)&lt;/code&gt; for each action and to choose the eligible action with the highest value for &lt;code&gt;f&lt;/code&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;That function &lt;code&gt;f&lt;/code&gt; must have the following properties:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;it must increase as the bucket index increases.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;it must increase as the average target index increases.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;it must decrease as the frequency increases.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;Here are some possible forms for the &lt;code&gt;f&lt;/code&gt; number:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="justify"&gt;linear: &lt;code&gt;f(Bucket, Avg, Freq) = A*Bucket + B*Avg - C*Freq&lt;/code&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;geometric: &lt;code&gt;f(Bucket, Avg, Freq) = A*Bucket*Avg / B*Freq&lt;/code&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;exponential: &lt;code&gt;f(Bucket, Avg, Freq) = (Bucket*Avg)&lt;sup&gt;A/Freq&lt;/sup&gt;&lt;/code&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;invers-exponential: &lt;code&gt;f(Bucket, Avg, Freq) = (Bucket*Avg)&lt;sup&gt;1-Freq/M&lt;/sup&gt;&lt;/code&gt;&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;rational: &lt;code&gt;f(Bucket, Avg, Freq) = A*Bucket*Avg*(1-1/(M-Freq))&lt;/code&gt;&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p align="justify"&gt;&lt;code&gt;M &lt;/code&gt;is a positive number larger than &lt;code&gt;max(Freq)+1&lt;/code&gt;. We can maintain a value large enough&amp;#160; by choosing initially an arbitrary value and then by increasing it whenever a frequency surpasses it.&lt;/p&gt;  &lt;p align="justify"&gt;It should be noted that the &lt;code&gt;f&lt;/code&gt; number should decrease smoothly with the frequency, otherwise the chains of states get curtailed too early. Unfortunately, only the last two formulas from above satisfy this condition.     &lt;br /&gt;    &lt;br /&gt;&lt;strong&gt;Pros:&lt;/strong&gt; the method ensures that testing is not stuck in infinite cycles since each cycle “erodes” over time.     &lt;br /&gt;&lt;strong&gt;Cons:&lt;/strong&gt; choosing an appropriate &lt;font face="Courier New"&gt;f&lt;/font&gt; function for a given state machine may not be easy or even possible.&lt;/p&gt;  &lt;h4&gt;The dangers of getting too high&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S8dIUCmlhGI/AAAAAAAAA0Q/3KQCPtHWrmc/s1600-h/istockphoto_453710-sky-is-the-limit%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="istockphoto_453710-sky-is-the-limit[1]" border="0" alt="istockphoto_453710-sky-is-the-limit[1]" align="right" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S8dIU0rHb_I/AAAAAAAAA0U/soRSI3KaGdk/istockphoto_453710-sky-is-the-limit%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="260" /&gt;&lt;/a&gt; The previous section shows how we can use action frequencies to diversify the long-haul scenarios by “eroding” cycles that get exercised too much. Also, the “erosion” may go very smoothly initially, thus protecting the cycles from getting curtailed too early.&lt;/p&gt;  &lt;p align="justify"&gt;Using unlimited action frequencies has a drawback, though: the impact of a single change decreases over time as the value of the frequency gets higher and higher. For this reason it is better to limit the frequencies. The simplest way is to limit the &lt;code&gt;M&lt;/code&gt; coefficient and whenever some frequency equals &lt;code&gt;M-1&lt;/code&gt; all the frequencies have to be divided by a value greater than &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;Long haul testing is an important part of quality assurance because it simulates usage over a long period of time and it uncovers software errors hard to detect by other means.&lt;/p&gt;  &lt;p align="justify"&gt;Long haul testing and model-based testing seem to be at odds because long haul testing requires more control over the test runs from the part of the tester whereas model-based testing implies less control over scenario generation.&lt;/p&gt;  &lt;p align="justify"&gt;This article proposes a method to reconcile long haul testing with model-based testing by using a system based on probabilistic classes named “buckets” combined with frequency considerations to preserve the variety of test scenarios during the long runs.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-3391220288972936421?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/3391220288972936421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/04/model-based-long-haul-testing.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/3391220288972936421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/3391220288972936421'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/04/model-based-long-haul-testing.html' title='Model-Based Long Haul Testing'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_e3SRrbdPqkw/S8b6o-a5hWI/AAAAAAAAAzU/rx8wHU2Sj7Y/s72-c/stairs3%5B1%5D_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-4330553912250823274</id><published>2010-03-28T06:00:00.001+03:00</published><updated>2010-06-14T16:19:55.929+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><category scheme='http://www.blogger.com/atom/ns#' term='modeling'/><title type='text'>Testing Modal Forms with NModel</title><content type='html'>&lt;p align="justify"&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S659zHA_SxI/AAAAAAAAAuY/ngHEdRHjbEA/s1600-h/book%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="book[1]" border="0" alt="book[1]" align="left" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S659zWrxl9I/AAAAAAAAAuc/2yYOkij5JmY/book%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="214" height="255" /&gt;&lt;/a&gt;The testing of graphical user interfaces is one of the most sensible and – I dare to say – unpleasant aspects of software testing.&lt;/p&gt;  &lt;p align="justify"&gt;While testing GUI manually provides instant gratification to the professional tester – who can explore and try new ideas right on the spot – it certainly produces headaches to project managers: GUI testing is one of the slowest, sometimes boring, almost always time consuming and difficult to automate areas of quality assurance.&lt;/p&gt;  &lt;p align="justify"&gt;In other words, not something to brag about.&lt;/p&gt;  &lt;p align="justify"&gt;The NModel tool provided by Microsoft Research which I wrote about in &lt;a href="http://mariusfilipontesting.blogspot.com/2010/03/frequency-based-test-strategies-with.html" target="_blank"&gt;my previous post&lt;/a&gt;, while not being created with GUI testing in mind, may be used in testing graphical user interfaces provided that the test developer is endowed with a good GUI automation library and a good understanding of modeling basics.&lt;/p&gt;  &lt;p align="justify"&gt;In this article I address the problem of testing modal forms with NModel. The testing of modal dialog boxes is the most simple kind of GUI testing. Future articles will address other areas of GUI testing with NModel.&lt;/p&gt;  &lt;h4&gt;The truth about dialogs&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S6590LES_BI/AAAAAAAAAug/5iQNgQJzGAQ/s1600-h/form2%5B1%5D%5B4%5D.gif"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="form2[1]" border="0" alt="form2[1]" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S6590Yzp8pI/AAAAAAAAAuk/osrqxl_ar64/form2%5B1%5D_thumb%5B2%5D.gif?imgmax=800" width="245" height="260" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p align="justify"&gt;A modal window (or &lt;em&gt;modal form&lt;/em&gt; or &lt;em&gt;modal dialog window&lt;/em&gt; or &lt;em&gt;modal dialog box&lt;/em&gt;) is a graphical element in a window-based computer interface that serves as data gateway from the user to the computer.&lt;/p&gt;  &lt;p align="justify"&gt;Dialog boxes have the following characteristics:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;they have clear creation and destruction times.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the hosting application freezes during the lifetime of a modal dialog box.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;dialog boxes have one purpose only: to make the user give information.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;a dialog box has two possible outcomes: either the user provides the information or the user declines to give the information. The &lt;code&gt;OK&lt;/code&gt; and &lt;code&gt;Cancel&lt;/code&gt; buttons usually fill these roles.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;Besides these main behavioral characteristics, modal dialog boxes may also:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;provide data validation for some or all the controls within.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;provide final data validation upon data approval (when the user presses &lt;font face="Courier New"&gt;OK&lt;/font&gt;).&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;       &lt;div align="justify"&gt;enable and/or disable some controls.&lt;/div&gt;     &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;provide correlation between controls (for example, a list box may be dynamically populated based on some other value).&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;accept or refuse resizing. Resizing brings the issue of control migration/anchoring/resize as well as the issue of text representation.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;contain sub-variants, i.e. sub-dialog boxes hosted by the same dialog box. It is the case of tabbed dialog boxes.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;exhibit asynchronous elements like timers and progress bars.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;For all their characteristics, modal dialog boxes represent an ideal candidate for state-based modeling and model-based automated testing:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the start and end moments of a dialog box can be easily modeled with state variables.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;there is usually only one event happening at a time (the exception are the asynchronous elements - quite rare). This makes a state-based representation easy.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the controls are usually (but not always) independent from each other, making the state space of a dialog box quite large. The size of the state space makes thorough testing a daunting task especially when some controls are not fully independent from each other.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;once thoroughly tested, a modal dialog box can be modeled from that point on simply as a function returning a tuple of values.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;automated model-based testing may produce race conditions that are nearly impossible to reproduce manually - yet revealing profound design defects in event handlers.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;because NModel takes care of computing the actual state machine of a model, modeling a dialog box is as easy as matching all the controls in the dialog box with a corresponding variable-action pair.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Alpha and Omega&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S65908w5yVI/AAAAAAAAAuo/_x1uvr4ONlQ/s1600-h/trinity-rublev%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="trinity-rublev[1]" border="0" alt="trinity-rublev[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S6591qeKHjI/AAAAAAAAAus/06nA19JP2uw/trinity-rublev%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="215" height="260" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="justify"&gt;The first thing to do when modeling a modal dialog box it to represent its beginning and its end. It’s easy to do this in NModel:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;provide two state variables in the model, the first one telling whether the dialog box has been created and the second one telling whether the dialog box has been closed:        &lt;br /&gt;        &lt;br /&gt;&lt;font face="Courier New"&gt;static bool open = false;          &lt;br /&gt;static bool closed = false;&lt;/font&gt;&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;create an action named &lt;code&gt;Open&lt;/code&gt; that “opens” the dialog box:         &lt;br /&gt;        &lt;br /&gt;&lt;font face="Courier New"&gt;static bool OpenEnabled()          &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return !open &amp;amp;&amp;amp; !closed; // the dialog has never existed           &lt;br /&gt;}           &lt;br /&gt;          &lt;br /&gt;[Action]           &lt;br /&gt;static void Open()           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; … pretend here to “open” the dialog; it is enough to reset the state variables although NModel does it …           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; open = true; // do not forget to set “open” to ‘true’!           &lt;br /&gt;}&lt;/font&gt;&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;create an action named &lt;code&gt;Close&lt;/code&gt; (it may be replaced by an &lt;code&gt;OK&lt;/code&gt; - &lt;code&gt;Cancel&lt;/code&gt; couple) that “closes” the dialog box:         &lt;br /&gt;        &lt;br /&gt;&lt;font face="Courier New"&gt;static bool CloseEnabled()          &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return open;           &lt;br /&gt;}           &lt;br /&gt;          &lt;br /&gt;[Action]           &lt;br /&gt;static void Close()           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; … pretend here to “close” the dialog; it is enough to validate data if Close() represents ‘exit with valid data’ …           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; open = false; // do not forget to set “open” to ‘false’ !           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; closed = true; // do not forget to set “closed” to ‘true’ !           &lt;br /&gt;}&lt;/font&gt;&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;prefix the enabling condition of any action with an &lt;code&gt;AND&lt;/code&gt;-ed &lt;code&gt;open&lt;/code&gt; so that no action takes place before the dialog box gets created. Assuming our action is named &lt;code&gt;Act()&lt;/code&gt; and its enabling condition is provided by function &lt;code&gt;MyCond&lt;/code&gt;, replace:     &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;static bool ActEnabled()      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return MyCond();       &lt;br /&gt;}&lt;/font&gt;     &lt;br /&gt;    &lt;br /&gt;with:     &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;static bool ActEnabled()      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return open &amp;amp;&amp;amp; MyCond();       &lt;br /&gt;}&lt;code&gt;&lt;/code&gt;&lt;/font&gt;&lt;/p&gt; &lt;/code&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;make sure that only &lt;code&gt;Open&lt;/code&gt; and &lt;code&gt;Close&lt;/code&gt; change &lt;code&gt;open&lt;/code&gt; and &lt;code&gt;closed&lt;/code&gt;.&lt;/div&gt;      &lt;p&gt;&lt;/p&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Meat on the bones&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S6592Ev6mXI/AAAAAAAAAuw/Be9xHu7hm2Y/s1600-h/BABY%20BACK%20RIBS%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="BABY%20BACK%20RIBS[1]" border="0" alt="BABY%20BACK%20RIBS[1]" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S6592aaFP-I/AAAAAAAAAu0/cAIImtzQ4jc/BABY%20BACK%20RIBS%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="200" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="justify"&gt;Once the &lt;em&gt;start&lt;/em&gt; and &lt;em&gt;end&lt;/em&gt; events have been modeled, we may proceed with modeling the rest of the dialog’s functionality.&lt;/p&gt;  &lt;p align="justify"&gt;There’s no single way to do it, yet some guidelines are good to follow:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;allow one state variable per independent or partially independent control.        &lt;br /&gt;        &lt;br /&gt;Independent controls may be acted upon by the user independently from other controls. Partially independent controls differ from totally independent controls by the fact that their value &lt;em&gt;may&lt;/em&gt; depend on other controls.         &lt;br /&gt;        &lt;br /&gt;You may ignore the controls which are &lt;em&gt;totally&lt;/em&gt; dependent on other controls unless you desire to test their values.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;provide one state action for each independent or partially independent control. Have the action to accept an argument of the same type as the data in the control. Within the action, set the value of the control and change the value of any other control that depends upon the current one. &lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;make sure that no action can be called before the dialog box got “created” (see section &lt;strong&gt;Alpha and Omega&lt;/strong&gt; from above).&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;it is good practice to provide a validation method &lt;code&gt;AssertValid&lt;/code&gt; and to call it at the end of each action. This caution makes sure there are no nonsense transitions between states. The &lt;font face="Courier New"&gt;AssertValid&lt;/font&gt; method should assert on &lt;code&gt;open&lt;/code&gt; and &lt;code&gt;close&lt;/code&gt;:         &lt;br /&gt;        &lt;br /&gt;&lt;font face="Courier New"&gt;[Conditional (“DEBUG”)]          &lt;br /&gt;static void AssertValid()           &lt;br /&gt;{           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Debug.Assert(!open || !closed);           &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; … other assertions …           &lt;br /&gt;}&lt;/font&gt;&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;When complexity unfolds&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S67_Q5OinQI/AAAAAAAAAvU/QoofvaRXEuY/s1600-h/istockphoto_10272933-box-unfolding%5B1%5D%5B3%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="istockphoto_10272933-box-unfolding[1]" border="0" alt="istockphoto_10272933-box-unfolding[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S67_RTubu5I/AAAAAAAAAvY/B0vGb-EWmTk/istockphoto_10272933-box-unfolding%5B1%5D_thumb%5B1%5D.jpg?imgmax=800" width="244" height="241" /&gt;&lt;/a&gt;A dialog box may contain tabs which increase the complexity of the form: the user may navigate freely between tabs. This ability to go back and forth as desired adds a potentially infinite chain of state clusters (each cluster corresponding to a tab being selected) which in turn makes the state machine of a tabbed dialog box very complex.&lt;/p&gt;  &lt;p align="justify"&gt;So, it seems that dialog boxes with tabs cannot be modeled as shown above.&lt;/p&gt;  &lt;p align="justify"&gt;Fortunately, there &lt;em&gt;is&lt;/em&gt; a way out. The secret resides in the fact that there is nothing miraculous about tabs, they usually exist for graphical convenience when there are too many controls to host within a form. Otherwise they are like little dialog boxes on their own.&lt;/p&gt;  &lt;p align="justify"&gt;So, the simplest method to model tabbed dialog boxes is to create a model for each tab in isolation and then to create an all encompassing model for the entire form at the end.&lt;/p&gt;  &lt;p align="justify"&gt;The final model doesn’t have to contain all the internals of the tab models. On the contrary, each tab may be abstracted away as a function returning a tuple of values or – in NModel parlance – as an action receiving as arguments the values corresponding to the controls within the tab. In fact, the final model emulates the navigation from one tab to another and not much more.&lt;/p&gt;  &lt;h4&gt;The good test driver&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S6592_RR1dI/AAAAAAAAAvc/_istSWTOOZc/s1600-h/bad-drivers-handbook1%5B1%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="bad-drivers-handbook1[1]" border="0" alt="bad-drivers-handbook1[1]" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S6593oD4fiI/AAAAAAAAAvg/DerwqhpEHqY/bad-drivers-handbook1%5B1%5D_thumb.jpg?imgmax=800" width="260" height="215" /&gt;&lt;/a&gt;&amp;#160; As shown in &lt;a href="http://mariusfilipontesting.blogspot.com/2010/03/frequency-based-test-strategies-with.html"&gt;my previous post&lt;/a&gt;, NModel needs an interface between the model and the system under test in order to do testing. This interface is named &lt;em&gt;test driver&lt;/em&gt; and it must implement the &lt;code&gt;IStepper&lt;/code&gt; interface:     &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;// code extracted from the “NModel book”      &lt;br /&gt;namespace NModel.Conformance       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public interface IStrategy       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; void Reset();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CompundTerm DoAction(CompoundTerm term);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p align="justify"&gt;The &lt;code&gt;DoAction&lt;/code&gt; method does all the work upon the system under test whereas &lt;code&gt;term&lt;/code&gt; contains all the information necessary for the action. &lt;code&gt;Reset&lt;/code&gt; brings the system under test to the initial state.&lt;/p&gt;  &lt;p align="justify"&gt;Acting upon the system under test means to send mouse click and keystrokes to the modal dialog box. It is very important to do it this way instead of calling the form’s methods directly since it’s necessary to emulate as close as possible the actual user action.&lt;/p&gt;  &lt;p align="justify"&gt;So far, so good. Provided the test developer has a good UI automation library at hand, the task seems over.&lt;/p&gt;  &lt;p align="justify"&gt;However, because emulating UI actions may be tricky, it is highly recommended to create yet another interface: one between the test driver and the system under test. This new interface sits in front of the system under test while exposing part of its functionality. I call it &lt;em&gt;the front&lt;/em&gt;.&lt;/p&gt;  &lt;h4&gt;The front&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S6594fZIwTI/AAAAAAAAAvk/ZifmGSlVcyo/s1600-h/TheFront%5B1%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="TheFront[1]" border="0" alt="TheFront[1]" align="left" src="http://lh4.ggpht.com/_e3SRrbdPqkw/S6594jEDokI/AAAAAAAAAvo/vP2o93yPCg4/TheFront%5B1%5D_thumb.jpg?imgmax=800" width="260" height="260" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="justify"&gt;The role of the front is to provide support for acting upon the system under test completely outside the NModel framework.&lt;/p&gt;  &lt;p align="justify"&gt;Such a separation is necessary in order to be able to test the GUI automation workings of each action in isolation, under the control of the test developer (by using NUnit, for instance). As a bonus, these tests make an excellent battery of smoke tests (or &lt;em&gt;BVT&lt;/em&gt;s or &lt;em&gt;base verification tests&lt;/em&gt;) for the dialog box.&lt;/p&gt;  &lt;p align="justify"&gt;Let us assume that the &lt;code&gt;Act&lt;/code&gt; action from above accepts a &lt;code&gt;string&lt;/code&gt; argument. In such case, the front class and the test driver class should contain something like that:     &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;public static class SUTFront      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static void Open() { /* open the dialog */ }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static void Close() { /* close the dialog */ }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static void Act(string s) { /* do something with ‘s’ */ }       &lt;br /&gt;}       &lt;br /&gt;      &lt;br /&gt;class SUTDriver       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public void Reset() { /* usually call SUTFront.Close() here */ }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public CompundTerm DoAction(CompundTerm term)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (Term.Name)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case “Open”: SUTFront.Open(); break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case “Close”: SUTFront.Close(); break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case “Act”:       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; string s = term[0] as string;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Debug.Assert(s != null); /* only if ‘s’ may not be ‘null’ *.       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SUTFront.Act(s);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; break;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; …       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; …       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; …       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p align="justify"&gt;So, with this approach, the actual test driver is &lt;code&gt;SUTFront&lt;/code&gt;, &lt;code&gt;SUTDriver&lt;/code&gt; acting only as a dispatcher. The benefit is that &lt;font face="Courier New"&gt;SUTFront&lt;/font&gt; can be used for other kinds of testing, apart from NModel.&lt;/p&gt;  &lt;p align="justify"&gt;It is strongly recommended to test &lt;font face="Courier New"&gt;SUTFront&lt;/font&gt; thoroughly before integrating it into &lt;font face="Courier New"&gt;SUTDriver&lt;/font&gt;. Programmatic GUI automation is not as trivial as it seems. The next section shows some of the glitches.&lt;/p&gt;  &lt;h4&gt;Traps and pitfalls in programmatic GUI automation&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S6595PC5TuI/AAAAAAAAAvs/xdsKS2BsEEQ/s1600-h/trap2%5B1%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="trap2[1]" border="0" alt="trap2[1]" align="right" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S6596hSd8XI/AAAAAAAAAvw/YD7xPc1boRY/trap2%5B1%5D_thumb.jpg?imgmax=800" width="260" height="260" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="justify"&gt;Programmatic GUI automation is difficult because no matter how good a GUI automation library is, ultimately an automation library is &lt;em&gt;not&lt;/em&gt; the same as a human user – neither in speed nor in intelligence.&lt;/p&gt;  &lt;p align="justify"&gt;These differences raise some specific challenges.&lt;/p&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h5&gt;Trap no. 1: neither human nor non-human&lt;/h5&gt;  &lt;p align="justify"&gt;In one hand, we want the emulated behavior to resemble human actions as much as possible. On the other hand, we want it to differ so that we can take advantage of the automatic nature of our tools in order to reveal more defects.&lt;/p&gt;  &lt;p align="justify"&gt;Let us consider mouse clicks, for example. Once we issue a mouse click programmatically, how long should we wait before issuing another event?&lt;/p&gt;  &lt;p align="justify"&gt;If we wait longer, then we get closer to the slow motions of a human user – but we might not be able to reproduce important race conditions. If we wait less, then we might be able to catch legitimate bugs from race conditions but we may also raise a lot of false positives - because it takes a non-zero time until the dialog box transitions from one valid state to another valid state.&lt;/p&gt;  &lt;p align="justify"&gt;Where’s the line between the two?&lt;/p&gt;  &lt;p align="justify"&gt;The truth is, there is not general answer, it depends on each case. I personally favor closeness to human behavior even though some race conditions might escape uncaught.&lt;/p&gt;  &lt;h5&gt;Trap no. 2: robotic take-over&lt;/h5&gt;  &lt;p align="justify"&gt;As efficient as it is model-based testing, it is dangerous to rely solely on it for GUI testing. In fact, it is dangerous to rely exclusively on &lt;em&gt;any&lt;/em&gt; kind of automated GUI testing.&lt;/p&gt;  &lt;p align="justify"&gt;Human check-up is necessary, either because automating is sometimes too costly or because automation is plainly not possible. For example, no GUI automation library can do verification of text meaning or usability verification. Such things require human intervention or Artificial Intelligence techniques that are beyond today’s state of the art.&lt;/p&gt;  &lt;h5&gt;Trap no. 3: model luring&lt;/h5&gt;  &lt;p align="justify"&gt;Models are addictive. They are pretty good at luring the IT professional into believing that gain with no sweat stands right behind the corner. Hence, the danger to do a model for &lt;em&gt;any&lt;/em&gt; kind of problem, no matter how trivial, is non-negligible.&lt;/p&gt;  &lt;p align="justify"&gt;The test developer should strive to keep the things simple. If a dialog box has only a few controls, if the controls are independent from each other and there’s not much dynamics involved, then using modeling is most likely inappropriate. Writing a plain vanilla test suite that simply exercises the form is a better choice in such cases.&lt;/p&gt;  &lt;p align="justify"&gt;We do have hammers, too. It doesn’t mean that everything should look like a nail.&lt;/p&gt;  &lt;h5&gt;Trap no. 4: Chinese speaking&lt;/h5&gt;  &lt;p align="justify"&gt;In my native tongue, the saying “you speak Chinese to me” means “I don’t understand anything from what you are saying”. Without care, adopting model-based techniques may lead to a very unproductive “Chinese” way of “speaking”.&lt;/p&gt;  &lt;p align="justify"&gt;The test developer using models should not forget that the outside world cares nothing about them. Our colleagues and managers want results with little concern for the method used. They want the results in &lt;em&gt;their&lt;/em&gt; terms, not ours – and it is our duty to provide the translation - otherwise we become “Chinese speakers”.&lt;/p&gt;  &lt;p align="justify"&gt;This means that, in the end, we must provide tests – and other artifacts – that can be executed and/or used by anyone, &lt;em&gt;outside&lt;/em&gt; the realm of modeling.&lt;/p&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;The GUI testing of modal dialog boxes can be accomplished with model-based techniques provided that the test developer has good quality GUI automation libraries and he understands the basics of modeling.&lt;/p&gt;  &lt;p align="justify"&gt;This article shows how NModel can be used for GUI testing of modal forms along with traps and pitfalls than one may face when tackling GUI testing with the aid of models.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-4330553912250823274?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/4330553912250823274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/03/testing-modal-forms-with-nmodel.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/4330553912250823274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/4330553912250823274'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/03/testing-modal-forms-with-nmodel.html' title='Testing Modal Forms with NModel'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_e3SRrbdPqkw/S659zWrxl9I/AAAAAAAAAuc/2yYOkij5JmY/s72-c/book%5B1%5D_thumb%5B2%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-1985069413466960255</id><published>2010-03-08T21:21:00.001+02:00</published><updated>2010-04-24T19:03:25.857+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><category scheme='http://www.blogger.com/atom/ns#' term='modeling'/><title type='text'>Frequency-Based Test Strategies with NModel</title><content type='html'>&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S5VOL3mxf0I/AAAAAAAAAsY/NnPNFX3iYOE/s1600-h/book17.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="book[1]" border="0" alt="book[1]" align="left" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S5VOMZMiUMI/AAAAAAAAAsc/wMjM0RGZctQ/book1_thumb5.jpg?imgmax=800" width="214" height="255" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="justify"&gt;As I have shown in &lt;a href="http://mariusfilipontesting.blogspot.com/2010/02/model-based-software-testing-and.html" target="_blank"&gt;my previous post&lt;/a&gt;, NModel is a viable framework for model-based testing and analysis of software programs. In this article I explore various possibilities to develop test strategies that can be implemented for the &lt;code&gt;ct.exe&lt;/code&gt; tool of NModel.&lt;/p&gt;  &lt;h4&gt;How testing works with NModel&lt;/h4&gt;  &lt;p align="justify"&gt;The idea behind testing with NModel is very simple: the test developer constructs a model of the system under test and then constructs a &lt;em&gt;test driver&lt;/em&gt; which translates the state transitions into actual commands upon the system under test. NModel is capable of traversing the state space of the model while issuing the calls upon the system under test via the test driver.&lt;/p&gt;  &lt;p align="justify"&gt;If the state space is small and the total number of paths throughout the state space is manageable, then it matters less how the paths get generated since NModel will eventually generate all the possible paths (i.e. test scenarios).&lt;/p&gt;  &lt;p align="justify"&gt;Usually the state space is extremely large so, in real life, it matters a lot how the paths get generated. The NModel element controlling the manner in which the paths get generated is called &lt;em&gt;test strategy&lt;/em&gt;. NModel comes with one strategy out of the box but the test developer can build other strategies on his own.&lt;/p&gt;  &lt;h4&gt;The &lt;code&gt;IStrategy&lt;/code&gt; interface&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S5Xc03CG2OI/AAAAAAAAAsg/xwVl5-Q5-6Q/s1600-h/strategy%5B9%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="strategy" border="0" alt="strategy" align="right" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S5Xc1X6XylI/AAAAAAAAAsk/Vic9bRlZ48o/strategy_thumb%5B7%5D.jpg?imgmax=800" width="260" height="180" /&gt;&lt;/a&gt; This interface forms the basis for any NModel test strategy. It has the following declaration in C#:     &lt;br /&gt;&lt;code&gt;     &lt;br /&gt;// code extracted from the “NModel book”       &lt;br /&gt;namespace NModel.Conformance       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public interface IStrategy       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set&amp;lt;Symbol&amp;gt; ActionSymbols { get; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IState&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CurrentState { get; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; bool&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IsInAcceptingState { get; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; void&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Reset();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; bool&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; IsActionEnabled(Action action, out string reason);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Action&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; SelectAction(Set&amp;lt;Symbol&amp;gt; actionSymbols);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; void&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DoAction(Action action);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/code&gt;&lt;/p&gt;  &lt;p&gt;&lt;code&gt;&lt;/code&gt;The methods of &lt;code&gt;IStrategy&lt;/code&gt; are self-explanatory (for information on these methods see the “NModel book” at page 201 and following). The most important method of the interface is &lt;code&gt;SelectAction(Set&amp;lt;Symbol&amp;gt;)&lt;/code&gt; since this method dictates how the &lt;code&gt;ct.exe&lt;/code&gt; tool chooses actions during continuous testing.&lt;/p&gt;  &lt;h4&gt;The &lt;code&gt;Strategy&lt;/code&gt; class&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S5Xc1rAAr7I/AAAAAAAAAso/EDPtS8DZGqE/s1600-h/permtree-anim%5B1%5D%5B3%5D.gif"&gt;&lt;img style="margin: 0px 15px 15px 0px; display: inline" title="permtree-anim[1]" alt="permtree-anim[1]" align="left" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S5Xc2MUTuII/AAAAAAAAAss/9rI8MjHHRXQ/permtree-anim%5B1%5D_thumb%5B1%5D.gif?imgmax=800" width="240" height="192" /&gt;&lt;/a&gt;This class is the “standard” strategy offered by NModel. When selecting an action it simply makes a random choice. While this strategy is simple and it ensures a pretty good state coverage, it may be inefficient: there is nothing to prevent that a state gets selected over and over again. Circumventing this disadvantage means to record the visited states one way or another.&lt;/p&gt;  &lt;p align="justify"&gt;The following sections explore possible ways to do that recording.&lt;/p&gt;  &lt;h4&gt;A dead path: storing the state paths&lt;/h4&gt;  &lt;p align="justify"&gt;The simplest way to avoid repeating the same states over and over again is to check the current state path (which is the chain of states starting with the initial state and ending with the current state) against previously generated state paths. Tempting as it is, such strategy fails for any non-trivial program: while the number of states may be large, the number of state paths is usually &lt;em&gt;huge&lt;/em&gt;.&lt;/p&gt;  &lt;h4&gt;Numeric escape: using frequencies&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S5Xc2qok7QI/AAAAAAAAAsw/Bmr9fa_N8Pg/s1600-h/2024_FreqGraph%5B1%5D%5B4%5D.gif"&gt;&lt;img style="margin: 0px 0px 15px 15px; display: inline" title="2024_FreqGraph[1]" border="0" alt="2024_FreqGraph[1]" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S5Xc3DPH5fI/AAAAAAAAAs0/jWXBhhT2Fi8/2024_FreqGraph%5B1%5D_thumb%5B2%5D.gif?imgmax=800" width="209" height="260" /&gt;&lt;/a&gt; Storing entire state paths means, in fact, storing too much information. If we settle for less when it comes to the assurance of not duplicating the paths, then it’s possible to store less information while still keeping a high chance of path non-duplication.&lt;/p&gt;  &lt;p align="justify"&gt;Any state path is nothing else than an ordered collection of states. Obviously we want to generate different, new collections with each step without keeping the whole collection. How can we do that?&lt;/p&gt;  &lt;p align="justify"&gt;The idea is to replace the collection of states with another piece of information which maintains - at least partially – the identity of the collection without the aid of elements. There is more than one solution to this problem, yet a very simple one is based on frequencies: if we choose the state that hasn’t occurred much lately then it’s a high chance we do not generate a previously generated state path.&lt;/p&gt;  &lt;p align="justify"&gt;Frequencies have two big advantages: are fixed in size and are very easy to update. State frequencies can be considered in various ways. The next sections reveal those ways.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;Brute state frequencies&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S5XrX76i38I/AAAAAAAAAs4/wmKS7JEmCbE/s1600-h/abp_hyperstates%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 20px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="abp_hyperstates[1]" border="0" alt="abp_hyperstates[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S5XrYY4IzeI/AAAAAAAAAs8/ecdU4Yu8SwQ/abp_hyperstates%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="216" height="260" /&gt;&lt;/a&gt;&amp;#160; Since the state path is made of states, it is plain natural to consider &lt;em&gt;brute&lt;/em&gt; state frequencies first. This means that the method &lt;font face="Courier New"&gt;SelectAction(Set&amp;lt;Symbol&amp;gt;)&lt;/font&gt; selects the action leading to the least frequent state. Upon encountering more than one state of the lowest frequency the strategy may choose randomly - hence increasing the chance of non-duplication.&lt;/p&gt;  &lt;p align="justify"&gt;This solution looks better than keeping whole paths yet the problem is not solved: the number of states may still be very large, virtually infinite. Maintaining a dictionary of state-frequency pairs simply does not scale for real-life cases.&lt;/p&gt;  &lt;p align="justify"&gt;This problem has a solution if we think that a state doesn’t come from nowhere. A state occurs from one of the following sources:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="justify"&gt;it is specified as an initial state of the abstract state machine.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;it is obtained from another state by applying an action upon the abstract state machine.&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p align="justify"&gt;So, for any given state &lt;code&gt;S&lt;/code&gt;, there is a correspondence between the next state and the action applied upon the state machine while being in state &lt;code&gt;S&lt;/code&gt;. This correspondence leads to another use of frequencies which has the merit of scaling to any number of states - hence for any abstract state machine – despite being less precise than state frequencies.&lt;/p&gt;  &lt;h4&gt;Action frequencies&lt;/h4&gt;  &lt;p align="justify"&gt;The idea is simple: method &lt;font face="Courier New"&gt;SelectAction(Set&amp;lt;Symbol&amp;gt;)&lt;/font&gt; selects the least frequent &lt;em&gt;action&lt;/em&gt; from the list of eligible actions. Upon encountering more than one action of the lowest frequency the strategy may choose randomly - hence increasing the chance of non-duplication.&lt;/p&gt;  &lt;p align="justify"&gt;Unlike state frequencies, this method &lt;em&gt;does&lt;/em&gt; scale since the number of actions is fixed for any given model. So, space consumption is &lt;code&gt;O(1)&lt;/code&gt;.&lt;/p&gt;  &lt;h4&gt;Balancing actions against states&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S5XraGNg84I/AAAAAAAAAto/Sn3NpLjDgoE/s1600-h/balance%5B1%5D%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="justice scale" border="0" alt="justice scale" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S5Xrat3RauI/AAAAAAAAAts/bih58F6qRYM/balance%5B1%5D_thumb%5B3%5D.jpg?imgmax=800" width="222" height="260" /&gt;&lt;/a&gt; Choosing the next action based on action frequencies is simple and practical but it has a major drawback: not all actions are created equal. The number of states they generate vary greatly – especially that, in the case of NModel, action methods accept arguments, hence there is a very wide range of changes that each action is able to perform upon the state machine.&lt;/p&gt;  &lt;p align="justify"&gt;To make the things more clear, let us consider two actions &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt;, both applicable upon the same state &lt;code&gt;S&lt;/code&gt;. Let us assume that &lt;code&gt;A&lt;/code&gt; generates 100 states and &lt;code&gt;B&lt;/code&gt; generates one state only. Let us assume that any time we choose an action we increment the appropriate frequency number by 1.&lt;/p&gt;  &lt;p align="justify"&gt;It is quite obvious that this policy favors &lt;code&gt;B&lt;/code&gt; against &lt;code&gt;A&lt;/code&gt; with a ratio of 100 to 1 since the state generated by &lt;code&gt;B&lt;/code&gt; has 100 times more chances of being elected than any state generated by &lt;code&gt;A&lt;/code&gt;. So, differentiating between &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; in terms of chances of being elected is a must. The simplest way to do it is to take into account the number of states that each action generates.&lt;/p&gt;  &lt;p align="justify"&gt;Unfortunately, it is nearly impossible to accurately predict the number of states generated by an action because:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the number of states generated by an action may depend upon the previous states.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;action methods may have parameters and the number of generated states may depend on those parameters in ways that make any prediction very hard to make.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the states are not equally important. For instance, out of the 100 states generated by action &lt;code&gt;A&lt;/code&gt;, most likely the number of truly interesting states is smaller (say, 20), all the other states being variants of the interesting cases.&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p align="justify"&gt;So, instead of using the exact number of states generated by each action, we may use an action &lt;em&gt;weight&lt;/em&gt; – representing an estimate of the number of relevant states that each action produces.&lt;/p&gt;  &lt;p align="justify"&gt;With this weight taken into account, using frequencies is easy: each time an action gets selected, its frequency number gets incremented by &lt;code&gt;1/weight&lt;/code&gt; in the stead of &lt;code&gt;1&lt;/code&gt;. Obviously, the frequency number cannot be an integer anymore.&lt;/p&gt;  &lt;h4&gt;Some recollection: using pairs&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S5XrbBUPBnI/AAAAAAAAAt0/aE0ArinLN8g/s1600-h/1236210989_00-va-schaffhaeuser_and_friends_unequal_equality%5B1%5D%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="1236210989_00-va-schaffhaeuser_and_friends_unequal_equality[1]" border="0" alt="1236210989_00-va-schaffhaeuser_and_friends_unequal_equality[1]" align="left" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S5XrbgphDHI/AAAAAAAAAt4/LijLXr2J1q8/1236210989_00-va-schaffhaeuser_and_friends_unequal_equality%5B1%5D_thumb%5B3%5D.jpg?imgmax=800" width="260" height="260" /&gt;&lt;/a&gt;The method of using action frequencies is simple and practical yet it ignores the previous history of actions completely. We don’t want to record the whole previous history (otherwise we end up with the full path problem from above), but we might need to recall the last state and/or action&amp;#160; and include it into the computation of frequencies.&lt;/p&gt;  &lt;p align="justify"&gt;In other words we might want to use frequencies of &lt;em&gt;pairs&lt;/em&gt;. Pairs of what? The next sections will tell.&lt;/p&gt;  &lt;h4&gt;Frequencies of state-action pairs&lt;/h4&gt;  &lt;p align="justify"&gt;We can keep frequencies of state-action pairs in the stead of action frequencies. However, because the number of states that a certain action can act upon may be large, we can do the following:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="justify"&gt;compute &lt;code&gt;H(S)&lt;/code&gt; where &lt;code&gt;S&lt;/code&gt; is the state and &lt;code&gt;H(S)&lt;/code&gt; is a numeric hash value for state &lt;code&gt;S&lt;/code&gt;.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;replace state &lt;code&gt;S&lt;/code&gt; by the value &lt;code&gt;H(S) % K&lt;/code&gt; (remainder of the integer division &lt;code&gt;H(S)/K&lt;/code&gt;) where &lt;code&gt;K&lt;/code&gt; is the maximum number of distinct states that we want to keep in consideration.&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;With this method, space consumption is something like &lt;code&gt;O(K)&lt;/code&gt; which is still &lt;code&gt;O(1)&lt;/code&gt; for a constant &lt;code&gt;K&lt;/code&gt;.&lt;/p&gt;  &lt;h4&gt;Frequencies of action-action pairs&lt;/h4&gt;  &lt;p align="justify"&gt;If using the threshold &lt;code&gt;K&lt;/code&gt; seems arbitrary, then keeping frequencies of action-action pairs is another option. This means that the strategy keeps the frequencies of &lt;code&gt;(A1, A2)&lt;/code&gt; pairs where &lt;code&gt;A1&lt;/code&gt; and &lt;code&gt;A2&lt;/code&gt; are actions that may occur in natural succession during continuous testing.&lt;/p&gt;  &lt;p align="justify"&gt;With this method, space consumption is something like &lt;code&gt;O(N&lt;sup&gt;2&lt;/sup&gt;)&lt;/code&gt; which is still &lt;code&gt;O(1)&lt;/code&gt; since &lt;font face="Courier New"&gt;N&lt;/font&gt; (the number of actions) is constant.&lt;/p&gt;  &lt;h4&gt;Added benefit: knowing how you’re doing and when to stop&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S5Xr1Pw5_uI/AAAAAAAAAuA/tWqg_QwFCqs/s1600-h/istockphoto_11275783-exclamation-sign-man-the-silent-screamer%5B1%5D%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="istockphoto_11275783-exclamation-sign-man-the-silent-screamer[1]" border="0" alt="istockphoto_11275783-exclamation-sign-man-the-silent-screamer[1]" align="right" src="http://lh4.ggpht.com/_e3SRrbdPqkw/S5Xr1XcxeaI/AAAAAAAAAuI/xhz8WbLghUg/istockphoto_11275783-exclamation-sign-man-the-silent-screamer%5B1%5D_thumb%5B3%5D.jpg?imgmax=800" width="224" height="260" /&gt;&lt;/a&gt;&amp;#160; Using frequency-based test strategies with NModel has the added benefit that we know all the time how many times each action has been called. One can use this information to develop various test metrics and policies to stop testing or evaluate the quality of testing:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the average frequency of action calls gives a clue on how well the implementation has been tested. For example, if we have a test run with an average of 10 calls per action and another test run with an average of 10000 calls per action, we can assume that the latter run has been 1000 times more thorough than the former.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;individual call frequencies may tell when to stop. For instance, one may choose to stop when each action has been called at least 10000 times, or when the average frequency is 5000 with a lower limit of 1000 calls per action.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;one can get a clue in real time about the dynamics of continuous testing by following the evolution of action frequencies over time. For example, if a certain action lags behind its peers then it is obvious that a certain part of the state space gets under-tested. In such case, refining or replacing the test strategy is quite necessary.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;Continuous testing with the &lt;code&gt;ct.exe&lt;/code&gt; tool of NModel is a viable method to achieve high quality testing with low costs. NModel offers to the test developer the possibility to develop new test strategies within this framework.&lt;/p&gt;  &lt;p align="justify"&gt;Selecting the next state based on frequencies is a simple yet effective method to ensure a wide variety of action calls with the added benefit that the accumulated numbers may form the basis for various quantitative and qualitative metrics.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-1985069413466960255?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/1985069413466960255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/03/frequency-based-test-strategies-with.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/1985069413466960255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/1985069413466960255'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/03/frequency-based-test-strategies-with.html' title='Frequency-Based Test Strategies with NModel'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_e3SRrbdPqkw/S5VOMZMiUMI/AAAAAAAAAsc/wMjM0RGZctQ/s72-c/book1_thumb5.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-6466101157412864400</id><published>2010-02-15T06:00:00.000+02:00</published><updated>2010-06-08T14:09:44.697+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='industry'/><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><category scheme='http://www.blogger.com/atom/ns#' term='modeling'/><title type='text'>Model-Based Software Testing and Analysis with C#</title><content type='html'>&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S3fikeyy-TI/AAAAAAAAArA/Qt7zA8N1ong/s1600-h/MBSTA%20with%20C%23%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="MBSTA with C#" border="0" alt="MBSTA with C#" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S3fik5QcskI/AAAAAAAAArE/ieDpMcuE7SU/MBSTA%20with%20C%23_thumb%5B2%5D.png?imgmax=800" width="278" height="331" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="justify"&gt;If software testing is checking conformance to specifications or looking for discrepancies between expected behavior and actual behavior, then model-based testing is a promising way to do it. In my opinion, models may be &lt;em&gt;the&lt;/em&gt; way to transform software testing from an art into a science, a strong reason to like them.&lt;/p&gt;  &lt;p align="justify"&gt;In the case of .NET, the &lt;a href="http://nmodel.codeplex.com/" target="_blank"&gt;NModel&lt;/a&gt; set of tools produced by Microsoft Research and freely distributed through &lt;a href="http://www.codeplex.com/" target="_blank"&gt;CodePlex&lt;/a&gt; can be of great help when it comes to modeling. Based on the theory of abstract state machines, NModel has the advantage of using a programming language to express the behavior of the system under test. That is, no UML diagrams or fancy graphical editors. On the other hand, the programmatic approach makes NModel less attractive for non-programmers despite the fact that it does include a visualization tool as part of its suite.&lt;/p&gt;  &lt;p align="justify"&gt;The standard book on NModel is &lt;a href="http://www.amazon.com/Model-Based-Software-Testing-Analysis-C/dp/0521687616/ref=sr_1_2?ie=UTF8&amp;amp;s=books&amp;amp;qid=1266136682&amp;amp;sr=8-2" target="_blank"&gt;Model-based software testing and analysis with C#&lt;/a&gt; by Jacky et al. (the “NModel book”). In this article I try to make a brief overview of the book while emphasizing perceived deficiencies of NModel as a tool for modeling real-life systems.&lt;/p&gt;  &lt;h4&gt;A little bit of history&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S3filRMQU-I/AAAAAAAAArI/JUegGNIpUGI/s1600-h/AsmL%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="AsmL" border="0" alt="AsmL" align="right" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S3filx70KFI/AAAAAAAAArM/YGBhEYtn65k/AsmL_thumb%5B2%5D.png?imgmax=800" width="176" height="103" /&gt;&lt;/a&gt; Yuri Gurevich is a theoretical computer scientist who’s developed the theory of evolving algebras. At Microsoft Research he’s lead a team that developed a specification language named &lt;a href="http://www.codeplex.com/AsmL" target="_blank"&gt;AsmL&lt;/a&gt;, based on abstract state machines (AsmL comes from &lt;strong&gt;A&lt;/strong&gt;bstract &lt;strong&gt;S&lt;/strong&gt;tate &lt;strong&gt;M&lt;/strong&gt;achine &lt;strong&gt;L&lt;/strong&gt;anguage). Abstract state machines are state machines working with arbitrary data. As a result of this, ASMs are capable of expressing a much broader range of computations than FSMs (finite state machines) because the latter ones suffer from “state explosion” (unmanageable growth in number of states).&lt;/p&gt;  &lt;p align="justify"&gt;AsmL provides executable specifications and is embeddable into Word documents via an extension developed by the same team at Microsoft Research. I used AsmL and it is a great language: simple and elegant, it offers great constructs to express abstract concepts while maintaining a programmatic look and feel. I might say it’s the specification heaven for the computer programmer.&lt;/p&gt;  &lt;p align="justify"&gt;Despite its elegance, AsmL has a major drawback: it is neither a programming nor a modeling language. It’s never meant to be, it was supposed just to accompany specifications written in natural language and not to provide ways to construct real systems or the models thereof.&lt;/p&gt;  &lt;p align="justify"&gt;NModel fills the gap. Consisting in a set of tools and nothing else, leveraging the .NET to the fullest extent, anyone who can program .NET can program viable models in C# or any other .NET language (thus, the title of the “NModel book” is somewhat misleading; one can construct models in Visual Basic.NET or C++/CLI as easy as in C#). But NModel is not essentially different from AsmL; it’s founded upon the same sound theory of abstract state machines.&lt;/p&gt;  &lt;h4&gt;NModel: a brief description&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S3fimFR_QkI/AAAAAAAAArQ/d7_GKqvnQ7k/s1600-h/NModel%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="NModel" border="0" alt="NModel" align="left" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S3fimiZwJaI/AAAAAAAAArU/MXHeGIdMGHo/NModel_thumb%5B2%5D.png?imgmax=800" width="225" height="118" /&gt;&lt;/a&gt; NModel consists in a library and a set of tools. The library contains elements to specify the model. Such an element is the &lt;code&gt;ActionAttribute&lt;/code&gt; attribute telling that a certain method represents a state transition. The tools have various purposes: graphic state explorer, test generator, test runner.&lt;/p&gt;  &lt;p align="justify"&gt;With NModel, the designer does not represent states explicitly. He represents data and changes upon the data and NModel computes the states automatically. This represents a great advantage over graphical modeling tools that start with states and end with data. With NModel, the designer models functionality directly, he doesn’t start from functionality to build diagrams only to arrive back at functionality. In order to facilitate state analysis, NModel ofers a graphical exploration tool, though.&lt;/p&gt;  &lt;p align="justify"&gt;The model, in NModel acceptance, is nothing else than a .NET custom library. The modeled elements are classes. The state transitions are methods and the state data consists in class fields. This permits to explore the model apart from NModel and, in fact, NModel itself encourages that. For example, NModel exhibits only one algorithm for state traversal but anyone can implement other algorithms with ease since NModel offers all that’s necessary to explore the state space in any desired manner.&lt;/p&gt;  &lt;p align="justify"&gt;Beside automatic state construction, NModel offers tools for model-based testing. Firstly, the designer writes stubs that act upon the system under test as dictated by the current state. Secondly, he uses the test generator that traverses the state space and, while traversing, acts upon the system under test via the above-mentioned stubs.&lt;/p&gt;  &lt;p align="justify"&gt;This is much more productive than writing test scenarios by hand because the tester can leverage the exploratory algorithms of NModel to generate a larger amount of scenarios in a shorter period of time while obtaining a better coverage of possible states and transitions.&lt;/p&gt;  &lt;h4&gt;The “NModel book”: a short overview&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S3finD7B-aI/AAAAAAAAArY/EkA821Xm_wI/s1600-h/MBSTA%20with%20C%23%5B9%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="MBSTA with C#" border="0" alt="MBSTA with C#" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S3finzciFWI/AAAAAAAAArc/KpqA8T7vwm0/MBSTA%20with%20C%23_thumb%5B5%5D.png?imgmax=800" width="187" height="260" /&gt;&lt;/a&gt; NModel comes accompanied by thorough documentation of the library but it lacks a tutorial explaining how to use everything. The “NModel book” fills this role.&lt;/p&gt;  &lt;p&gt;The book is divided into five main parts:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Overview &lt;/li&gt;    &lt;li&gt;Systems with Finite Models &lt;/li&gt;    &lt;li&gt;Systems with Complex State &lt;/li&gt;    &lt;li&gt;Advanced Topics &lt;/li&gt;    &lt;li&gt;Appendices &lt;/li&gt; &lt;/ol&gt;  &lt;h5&gt;Overview&lt;/h5&gt;  &lt;p align="justify"&gt;This section of the NModel book introduces the reader into the topic of modeling. It explains the role of modeling in analysis and testing, it gives examples on how modeling does a better job at detecting some errors than traditional methods and it shows how modeling is useful in some cases harder to tackle by other means (such as design defects).&lt;/p&gt;  &lt;h5&gt;Systems with Finite Models&lt;/h5&gt;  &lt;p align="justify"&gt;This section covers the issue of state machines with a small number of states, the ones that can be explored exhaustively. Topics like analysis, modeling, exploration, selection and testing are included.&lt;/p&gt;  &lt;h5&gt;Systems with Complex States&lt;/h5&gt;  &lt;p align="justify"&gt;This section begins to reveal the power of abstract state machines and their advantage over finite state machines: the states of ASMs may contain complex data. The section covers modeling, analysis and testing systems with complex states.&lt;/p&gt;  &lt;h5&gt;Advanced Topics&lt;/h5&gt;  &lt;p align="justify"&gt;As the name suggests, this section covers advanced topics: model composition, modeling objects (useful in conjunction with the OOP paradigm) as well as handling non-determinism.&lt;/p&gt;  &lt;h5&gt;Appendices&lt;/h5&gt;  &lt;p&gt;There are two kinds of appendices:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;a library reference –AND - &lt;/li&gt;    &lt;li&gt;a description of the tools included with NModel:      &lt;ul&gt;       &lt;li&gt;&lt;code&gt;mpv&lt;/code&gt;, the Model Program Viewer &lt;/li&gt;        &lt;li&gt;&lt;code&gt;otg&lt;/code&gt;, the Offline Test Generator &lt;/li&gt;        &lt;li&gt;&lt;code&gt;ct&lt;/code&gt;, the Conformance Tester &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;NModel: friendly criticism&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S3fioLu0bfI/AAAAAAAAArg/aRA0maZDMQw/s1600-h/criticism1%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="criticism1[1]" border="0" alt="criticism1[1]" align="left" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S3fiojrIPrI/AAAAAAAAArk/W4nlBCDlHRI/criticism1%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="259" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="justify"&gt;The &lt;strong&gt;first criticism&lt;/strong&gt; of NModel is acknowledged by the autors themselves: the tool does not have other traversal algorithms other than the &lt;a href="http://en.wikipedia.org/wiki/Travelling_salesman_problem" target="_blank"&gt;postman tour&lt;/a&gt; algorithm. However, a programmer can create new traversal algorithms with what the NModel library offers.&lt;/p&gt;  &lt;p align="justify"&gt;The &lt;strong&gt;second criticism&lt;/strong&gt; of NModel consists in the lack of expressing parallelism. NModel offers the composition mechanism (which is, in fact, a Cartesian product over the state spaces adorned with some rudimentary “synchronism”) but the mechanism is so awkward that the authors themselves use it solely for state selection and not much else.&lt;/p&gt;  &lt;p align="justify"&gt;The &lt;strong&gt;third criticism&lt;/strong&gt; of NModel consists in the lack of expressing structural composition: to be able to construct the whole from its parts. For example, provided we have a sub-model &lt;code&gt;A&lt;/code&gt; and a sub-model &lt;code&gt;B&lt;/code&gt;, there’s no way to produce a model &lt;code&gt;C&lt;/code&gt; composed of A and B working together. Needless to say, &lt;code&gt;C&lt;/code&gt; should be at a &lt;em&gt;higher&lt;/em&gt; level of abstraction than the sheer composition &lt;code&gt;A x B&lt;/code&gt;.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="justify"&gt;&lt;strong&gt;OBS:&lt;/strong&gt; NModel &lt;em&gt;does&lt;/em&gt; have a mechanism for state abstraction, i.e. for grouping a (potentially infinite) number of states into a single one. But for an abstraction based of structural composition as explained above, there is no support. That is, if one wants the model &lt;code&gt;C&lt;/code&gt; from above, he must write it from scratch by hand.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p align="justify"&gt;The &lt;strong&gt;fourth criticism&lt;/strong&gt; of NModel consists in the lack of expressing structural decomposition: to be able to break the whole into its parts. For example, provided we have a model &lt;code&gt;A&lt;/code&gt;, there’s no way to break it into sub-models &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; that, when “put together”, do the same thing as &lt;code&gt;A&lt;/code&gt; does. Needless to say, &lt;code&gt;B&lt;/code&gt; and &lt;code&gt;C&lt;/code&gt; should be at a &lt;em&gt;lower&lt;/em&gt; level of abstraction than a sheer division of &lt;code&gt;A&lt;/code&gt;’s states into two separate groups.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="justify"&gt;&lt;strong&gt;OBS:&lt;/strong&gt; NModel &lt;em&gt;does&lt;/em&gt; have a mechanism for state transition refinement via features and composition. Yet, such refinement applies to isolated states and transitions. It doesn’t work per entire groups of states, let alone per entire models. Most importantly, such refinement is not automatic with the exception of exploiting action matching via identical action names (the basic “synchronism” mechanism mentioned above). While yielding some relief in terms of decomposition, state transition refinement does not preclude the need for more elaborate ways to express structural decomposition as it happens in traditional top-down design methodologies.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p align="justify"&gt;The &lt;strong&gt;fifth criticism&lt;/strong&gt; of NModel consists in the poor support it offers for the well-known categories of testing. The software testing industry has long established several distinct kinds of testing: parameter, limits, boundary, functional, stress, robustness, etc. While the test designer can implement them via test strategies, there is not much more support beyond that.&lt;/p&gt;  &lt;p align="justify"&gt;The &lt;strong&gt;sixth criticism&lt;/strong&gt; of NModel consists in the poor support for repro scenarios. Testing with NModel follows two paradigms: predefined testing, quite reduced in scope and applicable to models with small number of states, and on-the-fly testing, much more powerful and customizable via test strategies. By far, the best option is on-the-fly testing in terms of both coverage and chances to find defects. Yet, when it comes to reproducing faulty scenarios, the support offered by NModel is sparse and cumbersome to use.&lt;/p&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;Model-based testing is a promising method to bring rigor and precision into the realm of test design. Despite requiring a higher level of expertise and more effort upfront, using models pays off due to a higher productivity in terms of test case generation and feature coverage.&lt;/p&gt;  &lt;p align="justify"&gt;NModel is a free suite of tools provided by Microsoft Research that can be used for model-based analysis and testing in the .NET ecosystem. While the NModel library is well documented by a help system provided with the tools, it is the “NModel book” the piece of work which contains a gentle yet thorough introduction into the world of modeling in general and NModel usage in particular.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-6466101157412864400?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/6466101157412864400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/02/model-based-software-testing-and.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/6466101157412864400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/6466101157412864400'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/02/model-based-software-testing-and.html' title='Model-Based Software Testing and Analysis with C#'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_e3SRrbdPqkw/S3fik5QcskI/AAAAAAAAArE/ieDpMcuE7SU/s72-c/MBSTA%20with%20C%23_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-6205934980239175504</id><published>2010-02-08T06:00:00.000+02:00</published><updated>2010-02-15T13:07:41.898+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='industry'/><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><category scheme='http://www.blogger.com/atom/ns#' term='artificial intelligence'/><category scheme='http://www.blogger.com/atom/ns#' term='modeling'/><title type='text'>How Much Intelligence in Software Testing?</title><content type='html'>&lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S27qq6xOxWI/AAAAAAAAAqE/DqKno3x05vM/s1600-h/monkey_thinker%5B1%5D%5B22%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="monkey_thinker[1]" border="0" alt="monkey_thinker[1]" align="right" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S27qrb2KQ4I/AAAAAAAAAqI/YOYUfxmlhBs/monkey_thinker%5B1%5D_thumb%5B20%5D.jpg?imgmax=800" width="278" height="331" /&gt;&lt;/a&gt;The issue of required level of technical expertise in software testing is a sensible one, especially when we compare software testers with their friends (and foes) from software development.&lt;/p&gt;  &lt;p align="justify"&gt;I dare to say that the universally accepted “wisdom” tells that testers are less qualified professionals than developers, that one becomes a tester if he’s not good enough to be a developer, that it’s expected that good testers eventually move to development and that professional testing is a disposable asset because, after all, one has the option to hire school students to do the job.&lt;/p&gt;  &lt;p align="justify"&gt;In this article I explore briefly the issue of tester intelligence then I move on to possible ways to optimize the usage of human intelligence in software testing.&lt;/p&gt;  &lt;h4&gt;Cogito, ergo sum&lt;/h4&gt;  &lt;p align="justify"&gt;“I think, therefore I am” said Descartes many years ago and this statement, so much true for any human endeavor, is even more valid for that complex and&amp;#160; brain intensive activity named software construction. Indeed, building software is hard, complex and – unfortunately - very much error prone.&lt;/p&gt;  &lt;p align="justify"&gt;What about software testing?&lt;/p&gt;  &lt;p align="justify"&gt;When it comes to sheer verification of conformance to specs, software testing clearly requires a lower level of expertise than development: we don’t care how much intelligence has been put into a piece of software as long as it conforms to the specs.&lt;/p&gt;  &lt;p align="justify"&gt;However, when it comes to finding &lt;em&gt;on purpose&lt;/em&gt; malfunctions in software, things do change tremendously. The tester is not anymore the patient, hard working bookkeeper of features from above. He’s more like a hacker, trying to exploit any little clue extracted from the system under test.&lt;/p&gt;  &lt;p align="justify"&gt;A hacker is anything but dumb and so is the creative professional tester. Creative software testing is a highly intelligent activity requiring cognitive processes as complex as the ones used for development (but different, of course). Needless to say, such good testers are hard to find.&lt;/p&gt;  &lt;p align="justify"&gt;Alas, like any intelligent human activity, creative software is expensive. Are there ways to optimize it?&lt;/p&gt;  &lt;p align="justify"&gt;Yes, there are.&lt;/p&gt;  &lt;h4&gt;When the artificial flavor is good&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S27qr11yJAI/AAAAAAAAAqM/OYYiGLEKBlA/s1600-h/yogs_03%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="yogs_03[1]" border="0" alt="yogs_03[1]" align="left" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S27qsNxrUJI/AAAAAAAAAqQ/9_BnQBDezdk/yogs_03%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="183" height="260" /&gt;&lt;/a&gt; When the software tester is looking for bugs, he’s faced with a non-decidable search problem whose space is infinite:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;it is a &lt;em&gt;search&lt;/em&gt; problem because the tester has to &lt;em&gt;search&lt;/em&gt; the space of all possible test scenarios and select only the ones leading to bugs.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;it is a &lt;em&gt;non-decidable&lt;/em&gt; problem because the &lt;em&gt;decision&lt;/em&gt; whether a certain behavior is indeed defective resides outside the testing process since it usually requires input from external sources (the developer, the rest of the team).&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;it is an &lt;em&gt;infinite&lt;/em&gt;-space search problem because the total number of possible scenarios is extremely large, practically infinite.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p align="justify"&gt;Does that sound familiar? If it doesn’t, it should: chess players, stock traders, investment businessmen, military or economic strategists, business executives, medical diagnosticians and many others have been playing with such things for years – and they are &lt;em&gt;all&lt;/em&gt; endowed with pretty darn good levels of intelligence.&lt;/p&gt;  &lt;p align="justify"&gt;Not only that: such problems have been tackled by computer science, too. It’s named Artificial Intelligence (A.I), it deals with problems non-tractable by ordinary methods and it’s yielded notable successes in domains like medical diagnosis, oil drilling, automated vision, game playing and others.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Does Artificial Intelligence have any place in software testing? Some attempts have been devised so far yet there is definitely room for better.&lt;/p&gt;  &lt;p&gt;Let’s take a closer look.&lt;/p&gt;  &lt;h4&gt;A proven path: theorem proving&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S27qshF-3-I/AAAAAAAAAqU/BmG22GrEtGw/s1600-h/Pythagorean_Theorem%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Pythagorean_Theorem[1]" border="0" alt="Pythagorean_Theorem[1]" align="right" src="http://lh4.ggpht.com/_e3SRrbdPqkw/S27qtDqh5iI/AAAAAAAAAqY/FHIiJyY5104/Pythagorean_Theorem%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="228" /&gt;&lt;/a&gt; &lt;em&gt;Theorem proving&lt;/em&gt; is a field of Artificial Intelligence that deals with the automated means to prove that a certain statement is true or false. Rooted in mathematical logic, theorem proving employs sophisticated methods of symbolic processing.&lt;/p&gt;  &lt;p align="justify"&gt;The principle of using theorem proving in software testing is very simple:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;testing conformance to specifications is equivalent with: given a software program &lt;code&gt;P&lt;/code&gt; and a set of specifications &lt;code&gt;S&lt;/code&gt;, is the statement ”&lt;code&gt;P and S&lt;/code&gt;“ true? In other words, does &lt;code&gt;S&lt;/code&gt; hold for any run of &lt;code&gt;P&lt;/code&gt;?&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;bug-oriented testing is equivalent with: given a software program &lt;code&gt;P&lt;/code&gt; and a set of specifications &lt;code&gt;S&lt;/code&gt;, is the statement ”&lt;code&gt;P and not S&lt;/code&gt;“ true? In other words, are there runs of &lt;code&gt;P&lt;/code&gt; that break the specs &lt;code&gt;S&lt;/code&gt;?&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;A theorem prover cannot work with a computer program in its direct, binary form, neither can it understand specs in natural language. So, a test system based on theorem proving must perform some transformations upon both the system under test as well as upon the specs to bring them in line with what the theorem prover can work upon.&lt;/p&gt;  &lt;p align="justify"&gt;These transformations are problematic and they wonderfully reveal the limits of the method:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;not every system’s internals are expressible as a formula that can be processed automatically. Hence, some approximations must take place, approximations that introduce a difference between the system under test and its formal expression.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;not every specification in natural language can be translated into a format that can be processed automatically. Again, some approximations must take place.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;To summarize the method in terms of pros and cons, one can say:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;&lt;strong&gt;Pros:&lt;/strong&gt; it is a precise and rigorous method, based upon on the time-tested, solid foundation of mathematical logic.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;&lt;strong&gt;Cons:&lt;/strong&gt; it requires approximations and it relies on access to the system’s internals. This means it cannot do black-box testing.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;A career in modeling&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S27qtXcqOEI/AAAAAAAAAqc/uCmjup2RtAY/s1600-h/Camilla_Barungi%5B1%5D%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Camilla_Barungi[1]" border="0" alt="Camilla_Barungi[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S27qtwythgI/AAAAAAAAAqg/x-OoHjXoGuE/Camilla_Barungi%5B1%5D_thumb%5B3%5D.jpg?imgmax=800" width="145" height="260" /&gt;&lt;/a&gt;Capturing the essentials of a system’s behavior, apart from specifications, can be achieved via &lt;em&gt;models&lt;/em&gt;. Curiously, despite modeling being essential to other branches of engineering, the software industry has recognized its importance only recently.&lt;/p&gt;  &lt;p align="justify"&gt;A software model is an artifact that represents, in simplified form, the behavior of the software system being modeled. Think of a model as the maquette of the software system being built.&lt;/p&gt;  &lt;p align="justify"&gt;Software models can be executable or non-executable. Executable models may be state-based modeling, i.e. they try to mimic the most important states of the system as well as the transitions from one state to another. When each state specifies the invariants that the system must satisfy, then the model becomes a verification tool, too.&lt;/p&gt;  &lt;p align="justify"&gt;Models are viable for software testing by the means of Artificial Intelligence because:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the elements of a model (states, transitions) can be processed by automatic means out of the box – AND -&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;       &lt;div align="justify"&gt;the behavior of a model is much simpler than the actual behavior, hence it is easier to process automatically.&lt;/div&gt;     &lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;As simple as they are, models are still too complex to be explored exhaustively. Their state space is big enough to require Artificial Intelligence techniques, especially from the realm of search algorithms.&lt;/p&gt;  &lt;p align="justify"&gt;Because they resemble more what the user sees (in contrast with the theorem proving approach, where the system under test becomes a mathematical formula) they are closer to the real-life work of the tester. However, because they rely on search algorithms empirical in nature (i.e. not as theoretically sound as mathematical logic) model-based testing does not enjoy the same theoretical precision that theorem proving has.&lt;/p&gt;  &lt;p align="justify"&gt;To summarize the method in terms of pros and cons, one can say that:&lt;/p&gt;  &lt;div align="justify"&gt;   &lt;ul&gt;     &lt;li&gt;       &lt;div align="justify"&gt;&lt;strong&gt;Pros:&lt;/strong&gt; it represents the behavior of a system and not the internals, therefore it supports black-box testing better.&lt;/div&gt;     &lt;/li&gt;      &lt;li&gt;       &lt;div align="justify"&gt;&lt;strong&gt;Cons:&lt;/strong&gt; it adds extra work to build the model, it is not theoretically sound as theorem proving, modeling requires ignoring details of the system that may prove important later on.&lt;/div&gt;     &lt;/li&gt;   &lt;/ul&gt; &lt;/div&gt;  &lt;h4&gt;Darwin was right&lt;/h4&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S27quQso2CI/AAAAAAAAAqk/Jsna-eYWGGI/s1600-h/simp_MonkeySuit%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="THE SIMPSONS: Flanders calls Homer an ape and makes a case for evolution revolution in THE SIMPSONS episode &amp;quot;The Monkey Suit&amp;quot; airing Sunday, May 14 (8:00-8:30 PM ET/PT) on FOX.  THE SIMPSONS™ &amp;amp; ©2006TCFFC ALL RIGHTS RESERVED.  ©2006FOX BROADCASTING  CR:FOX" border="0" alt="THE SIMPSONS: Flanders calls Homer an ape and makes a case for evolution revolution in THE SIMPSONS episode &amp;quot;The Monkey Suit&amp;quot; airing Sunday, May 14 (8:00-8:30 PM ET/PT) on FOX.  THE SIMPSONS™ &amp;amp; ©2006TCFFC ALL RIGHTS RESERVED.  ©2006FOX BROADCASTING  CR:FOX" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S27qu9E7aKI/AAAAAAAAAqo/ikVDOQ9QXCU/simp_MonkeySuit%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="127" /&gt;&lt;/a&gt; The previous methods of testing rely on a view upon the system under test that originates from:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;the translation of the system under test into a formalism that can be maneuvered by the theorem prover – OR - &lt;/li&gt;    &lt;li&gt;the manually built representation of the system’s behavior as a model. &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;Either way, the view of the system under test is &lt;em&gt;static&lt;/em&gt;, it does not evolve over time. Once the view gets constructed, the test engine uses it unchanged as long as testing goes. If one wants a better, more detailed view of the system under test, he must reconstruct it from scratch.&lt;/p&gt;  &lt;p align="justify"&gt;Such approach, obviously, involves a lot of work just to recode the information that already exists in the system. Wouldn’t be nice to have a testing system that doesn’t require that much information upfront but it &lt;em&gt;learns&lt;/em&gt; the system while testing it?&lt;/p&gt;  &lt;p align="justify"&gt;Such a system would depend pretty much on how the learned information gets represented. One way to represent that information consists in the test scenarios themselves, since any test scenario &lt;em&gt;does&lt;/em&gt; represent some information about the system under test. This means that having more scenarios is having more information and having a lot of scenarios is having a lot of information.&lt;/p&gt;  &lt;p align="justify"&gt;Such system would not store all the scenarios but only the ones containing maximum of test-related information, i.e. the ones revealing most defects or the ones exercising most system states. To avoid writing all the scenarios by hand the system has to start with a finite set of hand-crafted scenarios and it has to generate new scenarios automatically, based on the existing ones.&lt;/p&gt;  &lt;p align="justify"&gt;One method of generating new scenarios is by “mixing” existing ones to produce “offspring” while retaining the best “children” and discarding the sub-optimal ones. Since the “mixing” is akin to how the genes of a child’s parents mix to produce the genome of the child, these methods got called &lt;em&gt;genetic algorithms&lt;/em&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;These algorithms make up an evolutionary model of software testing because they work upon a population of test scenarios that, with each new generation, becomes better fit to the “environment” represented by the system under test.&lt;/p&gt;  &lt;p align="justify"&gt;The success or failure of genetic algorithms rely on two elements:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the individual actions which, when applied on succession, form the scenario. These actions are atomic, mostly stateless and mostly independent computational units that try to mimic an atomic piece of functionality of the system under test. Unfortunately, not all the systems support such atomic, sequential and independent decomposition.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the mixing procedure must be fast in order to ensure a high rate of generational renewal of the population. If the above-mentioned actions are truly stateless and independent, the mixing procedure is simple. Yet, a higher rate of inter-dependent actions requires more intelligent mixing procedures which may prove too slow.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;To summarize the method in terms of pros and cons, one can say that:&lt;/p&gt;  &lt;div align="justify"&gt;   &lt;ul&gt;     &lt;li&gt;       &lt;div align="justify"&gt;&lt;strong&gt;Pros:&lt;/strong&gt; it requires little effort upfront and the more it runs the more intelligent, better informed results it produces.&lt;/div&gt;     &lt;/li&gt;      &lt;li&gt;       &lt;div align="justify"&gt;&lt;strong&gt;Cons:&lt;/strong&gt; performance degrades for systems whose functionality does not support decomposition into atomic, stateless and independent actions.&lt;/div&gt;     &lt;/li&gt;   &lt;/ul&gt; &lt;/div&gt;  &lt;h4&gt;Unexplored paths&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh5.ggpht.com/_e3SRrbdPqkw/S2-ersNTfVI/AAAAAAAAAq0/UOJGjo-Pf3E/s1600-h/watermarksm%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="watermarksm[1]" border="0" alt="watermarksm[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S2-esFSPNgI/AAAAAAAAAq4/f0NccuiHSUA/watermarksm%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="200" /&gt;&lt;/a&gt; The previous sections show three fields of Artificial Intelligence that have been used in software testing. Some other fields of AI are good candidates, though. According to my knowledge to date, they haven’t been considered as such.&lt;/p&gt;  &lt;p align="justify"&gt;This section tries to present them along with reasons on why considering them good candidates for software testing makes sense.&lt;/p&gt;  &lt;h5&gt;Rule-based expert systems&lt;/h5&gt;  &lt;p align="justify"&gt;Rule-based expert systems is one field of Artificial Intelligence that has enjoyed considerable commercial success. Expert systems have been used in areas like medicine and mining and, albeit very expensive, they’ve saved large amounts of money to the ones who used them.&lt;/p&gt;  &lt;p align="justify"&gt;A rule-based expert system has two parts:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;a set of “rules” processed by an inference engine that represents the “thinking” of the system.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;a set of “facts” that represents the “memory” of the system.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;When presented with a problem, the expert system applies the rules upon the facts in order to draw a conclusion related to the problem. A solution may consist in a yes/no answer, a sequence of steps leading to a result or an explanation for a certain conclusion.&lt;/p&gt;  &lt;p align="justify"&gt;We may consider that a hypothetical expert systems for software testing should have the following elements:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;a set of “rules” indicating standard procedures to test a testable element.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;a set of “facts” containing knowledge about testable elements: UI controls, APIs, protocols, data structures, hardware ports, etc.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;When presented with a problem – i.e. a description of the system in terms of both structure and functionality – such an expert system would yield test procedures while explaining the reasons for choosing them. Expected outcomes would be: producing a test plan, yielding several standard test scenarios or proposing quality metrics.&lt;/p&gt;  &lt;h5&gt;Neural networks&lt;/h5&gt;  &lt;p align="justify"&gt;Neural networks are a field of Artificial Intelligence that has been used with success in form recognition. They proved capable of recognizing patterns like forms, images, handwriting or even voices. Their principle consists in a decision scheme based on the parallel work of tiny decisional elements named neurons which are inter-linked in various ways. More complex patterns require more complex neural networks.&lt;/p&gt;  &lt;p align="justify"&gt;Neural networks have been designed with static information in mind. This means that they can recognize patterns like images or handwriting but they are not fit to classify motion (unless, of course, motion is decomposed in individual frames, although I am not sure whether such an approach has been tried as of today). When thinking of testing, this means that reasoning upon the dynamics of a software system is unlikely to succeed with neural networks.&lt;/p&gt;  &lt;p align="justify"&gt;Yet, neural networks could be used to reason upon &lt;em&gt;static&lt;/em&gt; aspects of software, such as GUI layout. For example, writing a program that tells whether the GUI controls of a form are harmoniously arranged is nearly impossible to do in conventional ways, yet it becomes tangible with neural networks.&lt;/p&gt;  &lt;h5&gt;Case-based reasoning&lt;/h5&gt;  &lt;p align="justify"&gt;Case-based reasoning is a new field in Artificial Intelligence that deals with problems that resist an analytical description hence they aren’t tractable by analytic processes, no matter how advanced. Case-based reasoning is the automatic counterpart of the “&lt;em&gt;that’s the way we do it&lt;/em&gt;” from real life that we hear so often from people with great empirical experience who know they are right but cannot explain why.&lt;/p&gt;  &lt;p align="justify"&gt;A case-based reasoning system consists in a large database of problems, their characteristics and their resolutions. These are the cases. When a new problem arrives, the system tries to match the new situation to one of the existing cases and to propose a solution based on existing precedents. The solution bears no logical explanation since there is no apparent, logical correlation between a problem, its characteristics and its resolution. Yet, it works because a liaison &lt;em&gt;does&lt;/em&gt; exist but it is intractable by computational means.&lt;/p&gt;  &lt;p align="justify"&gt;Case-based reasoning may work for software testing considering that software developers, being all humans, most likely make similar mistakes when faced with a similar design. Hence, a case-based testing system doesn’t need to deeply analyze the system’s structure or behavior: provided with a description of the design, the case-based testing system might look up into the database of preceding cases to pinpoint the most probable vulnerabilities.&lt;/p&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;Software testing, like any other creative endeavor, requires a significant amount of intelligence. Various fields of Artificial Intelligence have been used to replace or complement the intelligence of software testers which, like any human intelligence, is slow, expensive and error prone.&lt;/p&gt;  &lt;p align="justify"&gt;This article presented an overview of several usages of Artificial Intelligence in software testing while proposing other fields of AI as good candidates for the same purpose, along with reasons for such proposals.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-6205934980239175504?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/6205934980239175504/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/02/how-much-intelligence-in-software.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/6205934980239175504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/6205934980239175504'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/02/how-much-intelligence-in-software.html' title='How Much Intelligence in Software Testing?'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_e3SRrbdPqkw/S27qrb2KQ4I/AAAAAAAAAqI/YOYUfxmlhBs/s72-c/monkey_thinker%5B1%5D_thumb%5B20%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-1071015995003152148</id><published>2010-02-01T06:00:00.000+02:00</published><updated>2010-02-15T13:21:50.117+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><title type='text'>The Power to Shell</title><content type='html'>&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S2S0-NTnC5I/AAAAAAAAAoc/IxFHE9xtbLE/s1600-h/shell%5B1%5D%5B7%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="shell[1]" border="0" alt="shell[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S2S0-tokwvI/AAAAAAAAAog/QDwp5SSonlQ/shell%5B1%5D_thumb%5B5%5D.jpg?imgmax=800" width="278" height="331" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align="justify"&gt;James Bach has written &lt;a href="http://www.satisfice.com/blog/archives/401"&gt;a blog post&lt;/a&gt; recently advocating for thorough software logging in order to help exploratory testing. In the same vein, Michael Bolton says in &lt;a href="http://www.developsense.com/2010/01/exploratory-testing-is-accountable.html"&gt;his blog&lt;/a&gt; that exploratory testing &lt;em&gt;is&lt;/em&gt; accountable, if done properly.&lt;/p&gt;  &lt;p align="justify"&gt;With no doubt, proper logging helps. But what if we have to test completed, non-modifiable systems or if the development team can not or would not inject such kind of tracing in the code? A solution against such inflexibility is to resort to record-and-play tools that, if used judiciously, may make up an adequate framework for good, reproducible exploratory testing.&lt;/p&gt;  &lt;p align="justify"&gt;However, what if the system under test has no GUI elements (as is the case of autonomous libraries, services or drivers) and by consequence it does not support record-and-play tools? Can we still have exploratory testing for internal components?&lt;/p&gt;  &lt;p align="justify"&gt;My past experience says that exploratory testing &lt;em&gt;is&lt;/em&gt; possible for internal components (even services or drivers) provided we have the right tools to do it. Those tools don’t have to be fancy or expensive, as shown below.&lt;/p&gt;  &lt;p align="justify"&gt;In this article I present my background on the problem and I suggest a way to do simple and elegant exploratory testing on non-GUI .NET components.&lt;/p&gt;  &lt;h4&gt;A little bit of history&lt;/h4&gt;  &lt;p align="justify"&gt;When I was doing testing on CLFS (&lt;a href="http://en.wikipedia.org/wiki/Common_Log_File_System"&gt;Common Log File System&lt;/a&gt;) at Microsoft, I was writing my tests in C/C++ as most testers in my group did. Quite frustrated by the fact that I had to write a complete C/C++ program every single time, even when all I wanted to do was to try some ad-hoc scenario, I asked myself: “isn’t there a better way?”.&lt;/p&gt;  &lt;p align="justify"&gt;It’s quite normal to ask such a question. Put plain and simple, you cannot do exploratory testing in C++, with its write-compile-run cycle. By the time you have the chance to “explore”, your mind is already emptied by making the code to pass compilation (if you are able to write error-free C++ code in one shot, this article isn’t for you). The result: in C++, spontaneity in testing is dead and dead is exploratory testing, too.&lt;/p&gt;  &lt;p align="justify"&gt;That was my situation: I wanted a tool that would allow me to exercise the system under test freely as the ideas were popping up in my head. But C/C++ was not such tool. The solution? Scripting.&lt;/p&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S2ZyWjl1SxI/AAAAAAAAAok/LF-KW8J-fl8/s1600-h/vbspro%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="vbspro[1]" border="0" alt="vbspro[1]" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S2ZyXBLSmuI/AAAAAAAAAoo/lDdgql7LOIQ/vbspro%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="214" height="260" /&gt;&lt;/a&gt;So, I wrote a little COM Automation library as a wrapper over the CLFS APIs and, lo and behold, I instantly had the component’s functionality at my fingertips with all the freedom to try quirky scenarios right on the spot.&lt;/p&gt;  &lt;p align="justify"&gt;Obviously, not every kind of functionality was accessible from scripting. For instance, I couldn’t do multi-threaded testing upon the component (which was necessary for certain scenarios). But nearly 90% of the component’s functionality was perfectly accessible through scripting.&lt;/p&gt;  &lt;p align="justify"&gt;Moreover, as a bonus, my tests were truly open (being written in VBScript instead of being C++ executables) so when my developer tried to reproduce a bug by running one of my tests he was able to &lt;em&gt;see&lt;/em&gt; what my test was doing and possibly add minor test cases before declaring the bug fixed.&lt;/p&gt;  &lt;p align="justify"&gt;I presented my little library and my script-based approach to my colleagues (testers of system components like me) and I encouraged them to “downgrade” their tools to a simpler programming language that would cover most of their testing needs. Some of them were intrigued, others were outright amused: “so, going &lt;em&gt;back&lt;/em&gt; to Basic?”. “For 90% of the time, yes”, I said.&lt;/p&gt;  &lt;p align="justify"&gt;Let’s admit it: trying to make a C++ programmer write &lt;em&gt;anything&lt;/em&gt; in Basic is blasphemous, almost like a personal insult. Yet, there are deep reasons to adopt such an approach in the case of test development.&lt;/p&gt;  &lt;h4&gt;Automated translators, information theory and software testing&lt;/h4&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S2ZyXSw2ZsI/AAAAAAAAAos/knmqb2eTNJY/s1600-h/compiler_large%5B1%5D%5B4%5D.gif"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="compiler_large[1]" border="0" alt="compiler_large[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S2ZyX-mVYJI/AAAAAAAAAow/BQPgfxzz-_0/compiler_large%5B1%5D_thumb%5B2%5D.gif?imgmax=800" width="181" height="260" /&gt;&lt;/a&gt; Let us think a little bit of automated translators that accept sequential inputs and produce an output which is (information-wise) equivalent to the input (such as compilers). In all these cases, the input language is &lt;em&gt;much&lt;/em&gt; more simple than the translator itself - even for very simple languages. See the &lt;a href="http://en.wikipedia.org/wiki/Brainfuck"&gt;Brainfuck&lt;/a&gt; language and imagine writing a translator for it.&lt;/p&gt;  &lt;p align="justify"&gt;The cause of this discrepancy resides in the fact that, in the case of sequential input, complexity manifests in &lt;em&gt;length&lt;/em&gt; whereas in the translator’s case complexity manifests in &lt;em&gt;states&lt;/em&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;It’s basically the same information: but one is stateless and infinite whereas the other is state-full and finite (in terms of size). The potentially infinite complexity manifests in:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;a potentially infinite length, in the case of sequential input.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;a potentially infinite state space, in the case of the translator’s execution.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;Due to the equivalence of these two forms of the same information, we don’t need a rich set of input words to challenge the inner execution of a translator. It is the &lt;em&gt;quality&lt;/em&gt; and the &lt;em&gt;length&lt;/em&gt; of the input sequences that count and not the &lt;em&gt;number of keywords&lt;/em&gt; that the translator has to accept.&lt;/p&gt;  &lt;p align="justify"&gt;Let us move now from automated translators to other kinds of software systems. We can conceptualize most software systems as being large, unconventional translators: they accept commands (the “sequential inputs”) and translate those commands into actions, data transfers and so on (the &amp;quot;output”). By the same line of reasoning as above, the input of a system is much simpler (in terms of individual commands) than the system itself. Just think of Microsoft Word, whose inputs consists in keyboard strokes, mouse clicks and not much more – therefore are much simpler than the data structures and the code within Word.&lt;/p&gt;  &lt;p align="justify"&gt;Applying this view to software testing, it turns out that the commands used in testing can be (and should be) &lt;em&gt;much&lt;/em&gt; simpler than the kind of processing happening in the system under test: it is not the fanciness of the commands or the price of the tools the we use in testing that matter. It is the &lt;em&gt;quality&lt;/em&gt; and &lt;em&gt;length&lt;/em&gt; of inputs sequences (i.e. test scenarios) that make all the difference.&lt;/p&gt;  &lt;p align="justify"&gt;Coming back to my CLFS testing, this means that you don’t need C++ to do high quality system testing upon components written in C++. In fact, a simpler programming language (like VBScript) that lets you quickly try things is preferable in most cases, being more productive and more fun.&lt;/p&gt;  &lt;h4&gt;The advent of .NET&lt;/h4&gt;  &lt;p align="justify"&gt;Assuming I’ve made a strong case for test languages as simple as possible for testing, even when testing very complex systems, let us take a look at how the situation has changed with the advent of .NET.&lt;/p&gt;  &lt;p align="justify"&gt;In the pre-.NET era there was COM Automation as the natural gateway from simple to complex (that’s why I ended up writing my CLFS tests in VBScript). Once .NET has arrived both COM and Automation start to fade away (without disappearing completely) and as a sure sign of that Microsoft hasn’t produced a truly .NET-friendly variant of VBScript so far (registering .NET classes as COM interfaces and accessing them from VBScript doesn’t count, sorry). The path is closed, no questions asked.&lt;/p&gt;  &lt;p align="justify"&gt;Is there a viable alternative? Do we have in .NET something flexible, powerful yet easy to use as VBScript?&lt;/p&gt;  &lt;p align="justify"&gt;We have. It’s called PowerShell.&lt;/p&gt;  &lt;h4&gt;The power to shell: PowerShell as &lt;em&gt;the&lt;/em&gt; test language for .NET&lt;/h4&gt;  &lt;p align="justify"&gt;&amp;#160; The administrators of the Windows operating system have long envied their colleagues from the Unix/Linux world for the powerful shell environments those platforms enjoy. Being able to write functions in scripts, having pipelines and a myriad of tools to do any thing imaginable were features putting cmd.exe and its reduced set of commands truly to shame.&lt;/p&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S2ZyYUuPsZI/AAAAAAAAAo0/JV1QOLONB8Y/s1600-h/PowerShell%20Progress_63173619-d8f5-4b95-b8ae-25d4f7321b01%5B1%5D%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 15px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="PowerShell%20Progress_63173619-d8f5-4b95-b8ae-25d4f7321b01[1]" border="0" alt="PowerShell%20Progress_63173619-d8f5-4b95-b8ae-25d4f7321b01[1]" align="right" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S2ZyZFpgbWI/AAAAAAAAAo4/zHHDnzV_1WE/PowerShell%20Progress_63173619-d8f5-4b95-b8ae-25d4f7321b01%5B1%5D_thumb%5B2%5D.png?imgmax=800" width="260" height="224" /&gt;&lt;/a&gt; But Windows eventually did retaliate. Strongly.&lt;/p&gt;  &lt;p align="justify"&gt;PowerShell has many characteristics in common with the Unix shells: functions, pipelines and the like. But besides those, it has two &lt;em&gt;huge&lt;/em&gt; advantages:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the commands are not standalone programs but embedded little modules named cmdlets, highly uniform in terms of parameters and very predictable in terms of behavior.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the commands do not work with textual information but with &lt;em&gt;structured&lt;/em&gt; information - that is, they work directly with .NET objects (even when piping).&lt;/div&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p align="justify"&gt;It is the second characteristic that can be fully exploited by .NET testing because one can instantiate from PowerShell, with &lt;em&gt;no&lt;/em&gt; restriction whatsoever, &lt;em&gt;any&lt;/em&gt; .NET class and can call &lt;em&gt;any&lt;/em&gt; method while gathering &lt;em&gt;any&lt;/em&gt; result. Hey, but this not any kind of scripting, this is truly test scripting for free!&lt;/p&gt;  &lt;p align="justify"&gt;So, what I propose in this article is to use, as extensively as possible, Windows PowerShell as the standard test language for .NET components.&lt;/p&gt;  &lt;h4&gt;PowerBlend: the tester and the admin are one&lt;/h4&gt;  &lt;p align="justify"&gt;Using PowerShell as a standard testing language for .NET brings another benefit: the tester can leverage the huge potential represented by the administrative power of the cmdlets in order to configure various execution environments for particular test runs.&lt;/p&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S2ZyZmjz9UI/AAAAAAAAAo8/QLSXIScJzSs/s1600-h/WindowsAdmin-Client_clip_image002_0000%5B1%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; margin: 0px 15px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="WindowsAdmin-Client_clip_image002_0000[1]" border="0" alt="WindowsAdmin-Client_clip_image002_0000[1]" align="left" src="http://lh3.ggpht.com/_e3SRrbdPqkw/S2ZyZ4yVzPI/AAAAAAAAApA/Q8Na3mcD2gU/WindowsAdmin-Client_clip_image002_0000%5B1%5D_thumb%5B2%5D.jpg?imgmax=800" width="260" height="220" /&gt;&lt;/a&gt; Imagine you have to test a little module that creates a certain kind of file within a certain directory. Writing tests that verify the file’s content is not enough. What if the user doesn’t have the right to write into that directory? What if the user doesn’t have the right to go &lt;em&gt;at all&lt;/em&gt; into that directory? What if the directory is actually a network path that needs to be created on the fly? What if the user has lower priviledges? What if … ?&lt;/p&gt;  &lt;p align="justify"&gt;Without the administrative power of PowerShell, the test developer is left with two options:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;to hard-code the configuration sequence into the test itself (within the test body or as a Setup/Teardown sequence). This makes difficult to switch to another configuration with ease, if necessary.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;to run the whole test harness under a different configuration. This is very problematic, since it may break the test harness itself!&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;There is another reason to use PowerShell for such configurations: performing admin tasks from C++ or C# (i.e. hard-coding the admin part into the test) is much more difficult than doing them with PowerShell commands. PowerShell was created with system administration in mind right from the beginning. So it is the natural choice when thinking about altering the environment to run tests under unusual conditions. Why wouldn’t it be the natural choice to write the .NET tests themselves?&lt;/p&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;Because complexity is represented differently in the inputs of a software system compared to the system itself, it makes a lot of sense to use a programming language as simple as possible when developing tests - even for the most complex systems. In this respect, scripting languages bring the advantage of simplicity while allowing to do exploratory testing even in the absence of a GUI interface.&lt;/p&gt;  &lt;p align="justify"&gt;With the advent of .NET, the Windows shell becomes a fully fledged, powerful, flexible environment that can access, manipulate, call and pipe .NET objects natively. All these qualities make PowerShell an excellent candidate for testing .NET components with the added benefit that test administration and test execution may be handled by the same language under the same hood.&lt;/p&gt;  &lt;p align="justify"&gt;This article presented some arguments in favor of using PowerShell in .NET testing. Future postswill bring more details on how .NET testing can be achieved in PowerShell.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-1071015995003152148?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/1071015995003152148/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/02/power-to-shell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/1071015995003152148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/1071015995003152148'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/02/power-to-shell.html' title='The Power to Shell'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_e3SRrbdPqkw/S2S0-tokwvI/AAAAAAAAAog/QDwp5SSonlQ/s72-c/shell%5B1%5D_thumb%5B5%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-8195390816232256820</id><published>2010-01-25T06:00:00.001+02:00</published><updated>2010-01-30T12:15:50.549+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><title type='text'>Data Flow Diagrams and Functional Testing</title><content type='html'>&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S1nC8Zmg5HI/AAAAAAAAAnY/ZKpU2Piv8ps/s1600-h/Figure91111.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="Figure91[1]" border="0" alt="Figure91[1]" align="left" src="http://lh6.ggpht.com/_e3SRrbdPqkw/S1nC89ulTUI/AAAAAAAAAnc/evXyjYyOS8U/Figure911_thumb9.jpg?imgmax=800" width="277" height="331" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="justify"&gt;&lt;strong&gt;D&lt;/strong&gt;ata &lt;strong&gt;F&lt;/strong&gt;low &lt;strong&gt;D&lt;/strong&gt;iagrams (&lt;strong&gt;DFD&lt;/strong&gt;s) have been widely used in the software methodologies of Structured Analysis and Design for a long time. While the structured method has largely fell out of use thanks to the advent of OOP techniques, maintaining a DFD model may prove useful in test design.&lt;/p&gt;  &lt;p align="justify"&gt;This article briefly presents DFDs and Structured Analysis, contrasts them with the OOP methods and proposes an approach of test design that uses DFD and Structured Analysis.&lt;/p&gt;  &lt;h4&gt;DFDs: it’s all in the data&lt;/h4&gt;  &lt;p align="justify"&gt;Data Flow Diagrams are composed of two “static” element types: &lt;em&gt;sources of data&lt;/em&gt; and &lt;em&gt;storages of data&lt;/em&gt;. Between them sits the third element type, the “dynamic” one: &lt;em&gt;processors of data&lt;/em&gt;. All these are interlinked by, of course, data (named &lt;em&gt;data flows&lt;/em&gt; in DFD parlance).&lt;/p&gt;  &lt;p align="justify"&gt;The role of these elements is obvious: the sources of data give &lt;em&gt;information&lt;/em&gt; to the system. The storages of data &lt;em&gt;keep&lt;/em&gt; the information for later use or for consumption by other systems. The processors of data work upon data by &lt;em&gt;transforming&lt;/em&gt; it whereas the data flows are, in fact, &lt;em&gt;abstractions&lt;/em&gt; of what we call information.&lt;/p&gt;  &lt;p align="justify"&gt;So far, so good: basically any IT system may be thought of in terms of data source, data storage, data processor and data flow. For instance, Windows Live Writer, which is the blog editor I am using right now, may be conceptualized in these terms:&lt;a href="http://lh4.ggpht.com/_e3SRrbdPqkw/S1nC9W59VQI/AAAAAAAAAng/gCBfptECdcg/s1600-h/Windows%20Live%20Writer%20DFD0%5B15%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 20px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Windows Live Writer DFD0" border="0" alt="Windows Live Writer DFD0" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S1nC-XsOrxI/AAAAAAAAAnk/3iXVR3fs7VQ/Windows%20Live%20Writer%20DFD0_thumb%5B11%5D.png?imgmax=800" width="260" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the data source is me, Marius Filip, who is writing this text.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the data storage is the repository of Blogger.com.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the data processor is Windows Live Writer.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the data flow is the text of this article.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;The data processing of Windows Live Writer consists in taking the text of my article, putting it into a format compatible with the internet protocols and the APIs exposed by Blogger.com and sending that content, in that format, to Blogger.com over the wire (see the image to the right). &lt;/p&gt;  &lt;h4&gt;DFDs: an explosion of bubbles&lt;/h4&gt;  &lt;p align="justify"&gt;Software systems are much more complex than this simple story yet the DFD environment is powerful enough to express even the most complex systems provided we enhance it with what is aptly called “bubble explosion”.&lt;/p&gt;  &lt;p align="justify"&gt;This “explosion” is nothing else than an orderly way of transforming what’s complex into what’s simple: the data processors (the “bubbles”) get decomposed into sub-data processors. The sub-processes (another name for data processor is &lt;em&gt;process&lt;/em&gt;) get placed into a different sheet exhibiting the same inputs and outputs as the original data processor. It is customary to number the bubbles in such way that their relationships are apparent: bubble &lt;strong&gt;1.1.3&lt;/strong&gt; is a child of bubble &lt;strong&gt;1.1&lt;/strong&gt; which is a child of bubble no. &lt;strong&gt;1&lt;/strong&gt; which belongs to the top.&lt;/p&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh3.ggpht.com/_e3SRrbdPqkw/S1nC-8qS_5I/AAAAAAAAAno/ClaXmqwnmrI/s1600-h/Windows%20Live%20Writer%20DFD1%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 20px 15px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Windows Live Writer DFD1" border="0" alt="Windows Live Writer DFD1" align="left" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S1nC_CZrMjI/AAAAAAAAAns/BECcm5Krkxg/Windows%20Live%20Writer%20DFD1_thumb%5B2%5D.png?imgmax=800" width="256" height="260" /&gt;&lt;/a&gt; Let us consider the example with Windows Live Writer from above. When I write an article to publish on this blog, I don’t produce it in one shot: there’s an editing process ongoing so we may speak of an article being &lt;em&gt;in progress&lt;/em&gt; or being &lt;em&gt;completed&lt;/em&gt;. Only the completed article goes to Blogger.com so we can split “Windows Live Writer” (process no. 1 from image above) into two sub-processes, one named “User Interface” and the other one “Blogger.com Interface” (see the image to the left).&lt;/p&gt;  &lt;p align="justify"&gt;&lt;/p&gt;  &lt;p align="justify"&gt;&lt;/p&gt;  &lt;p align="justify"&gt;We should observe how the numbers evolve: data processor no. 1 (Windows Live Writer) has been split into data processor 1.1 (User Interface) and data processor 1.2 (Blogger.com Interface). This way we know that “User Interface” is a child of “Windows Live Writer” and not the other way around.&lt;/p&gt;  &lt;h4&gt;DFDs: a “chain reaction”&lt;/h4&gt;  &lt;p align="justify"&gt;We can go with the “explosion” further. For example, the “User Interface” process responds to the commands from me while progressively recording internally the text of the article I am writing. It is the layer of UI controls that handle my commands (keystrokes, mouse clicks) whereas we may assume that something else buffers the actual text while I am typing. We call this something else the “Editor” process and we make it a child of process 1.1 (User Interface).&lt;/p&gt;  &lt;p align="justify"&gt;&lt;a href="http://lh6.ggpht.com/_e3SRrbdPqkw/S1nDAcTnh9I/AAAAAAAAAnw/Bd8u5QgfNow/s1600-h/Windows%20Live%20Writer%20DFD1.1%5B4%5D.png"&gt;&lt;img style="border-right-width: 0px; margin: 0px 0px 15px 20px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Windows Live Writer DFD1.1" border="0" alt="Windows Live Writer DFD1.1" align="right" src="http://lh5.ggpht.com/_e3SRrbdPqkw/S1nDA_78fsI/AAAAAAAAAn0/kWElTZVml1I/Windows%20Live%20Writer%20DFD1.1_thumb%5B2%5D.png?imgmax=800" width="260" height="220" /&gt;&lt;/a&gt; This second “explosion” keeps the numbering schema equally enforced: process 1.1.1 (UI Controls) together with process 1.1.2 (Editor) are children of process 1.1 (UI Interface). Important to know: data storage &amp;quot;Blogger.com” as well as data flow “Article Data” are &lt;em&gt;missing&lt;/em&gt; from the third diagram (see the image to the right) because process 1.1 (UI Interface) does not interact directly with “Blogger.com”. This means each sheet displays only the minimum information necessary to give the right amount of detail while simplicity is maintained.&lt;/p&gt;  &lt;p align="justify"&gt;We can go with the “explosion” even further, detailing the processes and sub-processes more and more, thus accomplishing a real “chain reaction” whose end result is the description of the IT system at any degree of detail we want.&lt;/p&gt;  &lt;p align="justify"&gt;The “reaction” ends when the bottom processes are so simple and straightforward that they can be easily translated into a procedural programming language like C or Pascal. However, this doesn’t occur soon: even a relatively simple program like Windows Live Writer may generate hundreds of pages of documentation and thousands of non-divisible processes. This may seem a lot, yet it’s better than jumping directly to coding.&lt;/p&gt;  &lt;h4&gt;DFDs in the shadow of OOP&lt;/h4&gt;  &lt;p align="justify"&gt;DFDs offer a simple and rigorous way of handling complex systems and enjoyed considerable success. However, the structured method has a major disadvantage: each process is linked with the surrounding processes in such degree that changing the system is very difficult. In fact, according to this method, the processes have no existence of their own: a certain process appears only in the context of a certain system and has no meaning outside of it.&lt;/p&gt;  &lt;p align="justify"&gt;The object-oriented paradigm of computer programming (OOP) fares better in this respect: a running system is a dynamic collection of “objects” which in turn are instances of prototypes named “classes”. These prototypes define how the instances interact with their surroundings. Once you code a class, you can use it in any system that needs its services – provided the class is well designed. Such degree of reuse is hard to do with the code resulted from the structured method.&lt;/p&gt;  &lt;p align="justify"&gt;How can one determine which are the classes necessary for a computer program? It depends on the method, but one of them is to start from the user behavior (captured in “use cases” or “user stories”) and to try to associate classes with nouns and behaviors (aka “signals” or “methods”) with verbs.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="justify"&gt;For example, if the “user story” reads “The user opens a document by selecting an existing file on the disk” then we can propose two classes, one named “Disk” with the method “Select” receiving a string (the “file name”) and another class named “Document” with the method “Open”. Obviously, the method “Select” of class “Disk” should return an instance of the class “Document”.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p align="justify"&gt;This means that OOP favors &lt;em&gt;behavior&lt;/em&gt; over data. This doesn’t mean that OOP systems do not handle data. It means that the starting point is the behavior and not the data whereas the structured method starts from data to arrive at behavior. This difference may form the basis for a kind of functional testing which is data-oriented and may make good use of the age-old DFDs.&lt;/p&gt;  &lt;p align="justify"&gt;Before proceeding with this approach we should clarify what’s the equivalent of a DFD process in the OOP world.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;To be or not to be a process&lt;/h4&gt;  &lt;p align="justify"&gt;OOP systems are composed of dynamically created entities (“objects”) which are based on behavioral and structural prototypes (“classes”). This makes classes instantiable entities, something that DFD processes are not. So, it seems that DFDs are not appropriate for modeling OOP systems.&lt;/p&gt;  &lt;p align="justify"&gt;This is not true.&lt;/p&gt;  &lt;p align="justify"&gt;Classes differ in their status and importance. They aren’t members of a perfect democracy where everyone is equal to everyone. For various reasons classes get grouped in larger entities: namespaces, modules, packages, libraries, DLLs, assemblies, components, etc. No matter how these are called, they represent divisions of a software system that, like classes, have clear boundaries in between.&lt;/p&gt;  &lt;p align="justify"&gt;However, unlike classes, these divisions are &lt;em&gt;not&lt;/em&gt; instantiable so they make good candidates for DFD processes.&lt;/p&gt;  &lt;h4&gt;Data-oriented testing: why?&lt;/h4&gt;  &lt;p align="justify"&gt;Because OOP is the favorite programming paradigm nowadays. This means that the current programming paradigm favors behavior and internal structure over data transmission. This means that we can expect that data flows contain some specific bugs that are not readily apparent just by following class behaviors.&lt;/p&gt;  &lt;p align="justify"&gt;The distinction is not trivial: when we test &lt;em&gt;behavior&lt;/em&gt;, we apply our test assumptions upon the &lt;em&gt;functionality&lt;/em&gt; while using data merely as a support to carry out our testing.&lt;/p&gt;  &lt;p align="justify"&gt;On the contrary, when we test &lt;em&gt;data flows&lt;/em&gt;, we apply our test assumptions upon the &lt;em&gt;data&lt;/em&gt; while using functionality merely as a support to trigger data transfer.&lt;/p&gt;  &lt;p align="justify"&gt;Because OOP systems favor behavior over data, it’s likely that data-oriented testing can find certain systemic errors better than functionality-oriented testing.&lt;/p&gt;  &lt;h4&gt;Data-oriented testing: when?&lt;/h4&gt;  &lt;p align="justify"&gt;Since just components can be DFD processes, data-oriented testing cannot commence before components take shape – at least on paper, during the architecture and design phases. For instance, it is meaningless to do data-oriented unit testing: at this level of granularity it is the behavior that counts while data interchange is basically sub-summed to it.&lt;/p&gt;  &lt;p align="justify"&gt;However, once the components are fairly well defined, data-oriented testing may begin. It is not necessary to have the actual components in place: one can use models or mock-ups to carry data-oriented testing out.&lt;/p&gt;  &lt;h4&gt;Data-oriented testing: how?&lt;/h4&gt;  &lt;p align="justify"&gt;The basis for data-oriented testing consists in the assumptions we make about the data flows that go into, come out from or flow within the system under test. These assumptions apply to:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;the inputs of a process.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the outputs of a process.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the relationship between the inputs and the outputs.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;the relationship between the behavior and the outputs.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;The inputs&lt;/h5&gt;  &lt;p&gt;The inputs of a process are not under the control of the process. Hence, we can only test the behavior of the process against various kinds of inputs. This is sheer functional testing, but with an emphasis on incoming data.&lt;/p&gt;  &lt;h5&gt;&lt;/h5&gt;  &lt;h5&gt;The outputs&lt;/h5&gt;  &lt;p align="justify"&gt;The outputs of a process are under the control of the process and are the byproducts of the process’ execution upon the incoming data. Tested in isolation, output may be checked along these coordinates: amount, rate, integrity, internal consistency. In order to achieve all the variants we have to vary both the inputs as well as the functionality. Yet, it is important to keep in mind that it is &lt;em&gt;data&lt;/em&gt; that we test and we must strive to obtain as much variation in terms of output data as possible.&lt;/p&gt;  &lt;h5&gt;The input-output relationship&lt;/h5&gt;  &lt;p align="justify"&gt;The inner execution control of a process establishes various relationships between the inputs and the outputs. For example, if the component converts one binary format to another, it is the correctness of conversion that must be tested. Checking the quality of inputs and outputs in separation is not enough.&lt;/p&gt;  &lt;p align="justify"&gt;A DFD process is not a procedure, a method or a class. It is a whole component with may have multiple inputs and outputs. Assuming the number of inputs is M and the number of outputs is N, there are up to 2&lt;sup&gt;M+N&lt;/sup&gt; input-output relationships to check. Usually not all combinations make sense but the ones that do must be thoroughly tested in terms of relationship assumptions.&lt;/p&gt;  &lt;h5&gt;The behavior-output relationship&lt;/h5&gt;  &lt;p align="justify"&gt;The input-output relationship established by the inner execution of a process is enforced as long as the execution itself goes normally. However, the component’s execution may terminate unexpectedly for reasons lying outside the component. In such case, the normal input-output relationships do not function. Data-oriented testing must check the quality of outputs even when such situations occur.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="justify"&gt;&lt;strong&gt;Situation 1&lt;/strong&gt;: in the case of a crash, have the output files been irremediably corrupted or some data may still be recovered? If something may be recovered, is the recovered data in good standing relative to the inputs?&lt;/p&gt;    &lt;p align="justify"&gt;&lt;strong&gt;Situation 2:&lt;/strong&gt; in the case of a power outage during a commit, what’s the extent of database corruption: the target cell, the target row, the target table or the whole database?&lt;/p&gt;    &lt;p align="justify"&gt;These are kinds of questions that the testing of behavior-output relationships must answer to.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h4&gt;Data-oriented testing: a tiny tutorial&lt;/h4&gt;  &lt;p align="justify"&gt;Performing data-oriented testing is easy once the DFD approach is understood.&lt;/p&gt;  &lt;h5&gt;Step I: construct a DFD model of the system under test&lt;/h5&gt;  &lt;p align="justify"&gt;The first step is to construct a DFD model. The ideal is to carry out this task while the early phases of product development are ongoing, but constructing the DFD model for an existing architecture works just as well. The DFD model must be as detailed as necessary to capture every non-instantiable component of the system, but not more detailed.&lt;/p&gt;  &lt;h5&gt;Step II: perform data-oriented testing upon the bottom processes&lt;/h5&gt;  &lt;p&gt;The data-oriented testing should contain all the four types of testing explained in the section “&lt;strong&gt;Why?” &lt;/strong&gt;from above.&lt;/p&gt;  &lt;h5&gt;Stept III: once all the children of a process are data-tested, test the data of the parent process, too&lt;/h5&gt;  &lt;p&gt;Data-oriented testing goes bottom-up. It is not enough to test only the bottom of the process hierarchy, for the following reasons:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;The sub-processes of a process may explicitly interact with one another by exchanging data. Although testing each sub-process in isolation gives some coverage of those interactions, the real life interactions among the sub-processes may reveal cases not caught during individual testing.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;The sub-processes of a process may implicitly interact with one another outside the explicit data-flow framework (using the same critical section, for instance). In order to catch the bugs in this area it is necessary to test the sub-processes as integral parts of the same parent process.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;Even if the sub-processes of a process are independent from one another, they may unexpectedly interact due to inner bugs. Such bugs may escape uncaught if data-oriented testing doesn’t go bottom-up, in an integrative manner.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Conclusions&lt;/h4&gt;  &lt;p align="justify"&gt;Data Flow Diagrams make up one of the pillars of Structured Analysis and Design. With the advent of OOP, DFDs fell much out of use since the new paradigm starts software analysis, architecture and design from behavior towards data and not the other way around.&lt;/p&gt;  &lt;p align="justify"&gt;The emphasis on functionality brought in by OOP gives to the professional tester the opportunity to use the DFDs to design a kind of tests that put more emphasis on data and data flows with the hope that certain systemic errors can be caught easier when the system under test is looked upon from a different angle.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-8195390816232256820?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/8195390816232256820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/data-flow-diagrams-and-functional.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/8195390816232256820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/8195390816232256820'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/data-flow-diagrams-and-functional.html' title='Data Flow Diagrams and Functional Testing'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_e3SRrbdPqkw/S1nC89ulTUI/AAAAAAAAAnc/evXyjYyOS8U/s72-c/Figure911_thumb9.jpg?imgmax=800' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-5197761825225804488</id><published>2010-01-18T06:00:00.002+02:00</published><updated>2010-01-19T11:01:46.622+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='industry'/><title type='text'>Software Cinderella</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://7uncle.files.wordpress.com/2009/01/cinderella1.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; width: 360px; float: left; height: 440px; cursor: pointer" border="0" alt="" src="http://7uncle.files.wordpress.com/2009/01/cinderella1.jpg" /&gt;&lt;/a&gt;Software testing is, in some respects, the &lt;strong&gt;Cinderella&lt;/strong&gt; of software industry.   &lt;p align="justify"&gt;&lt;strong&gt;Everybody&lt;/strong&gt; invests in quality assurance yet only the largest organizations can afford a 1:1 developer/tester ratio. &lt;strong&gt;Everybody&lt;/strong&gt; talks about quality yet we still don’t have a strong theoretical model for what software quality really is. &lt;strong&gt;Everybody&lt;/strong&gt; develops and/or uses more and more advanced programming tools boosting productivity yet the tools for testing are either too narrow-scoped or too expensive. &lt;strong&gt;Everybody&lt;/strong&gt; thinks that detecting and fixing bugs early in the process makes economic sense yet the pressure of early deadlines becomes stronger day by day.&lt;/p&gt;  &lt;p align="justify"&gt;And, the last but not the least, &lt;strong&gt;every&lt;/strong&gt; IT college usually has subjects on various kinds of programming (procedural, OOP, logic, functional) yet only few of them offer courses on quality assurance.&lt;/p&gt;  &lt;p align="justify"&gt;The &lt;strong&gt;Cinderella&lt;/strong&gt; status of software testing has strong, deep roots. This article tries to reveal them.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;Problem no. 1: software skills are expensive&lt;/h4&gt;  &lt;p align="justify"&gt;Software is one of the few fields of engineering that use highly-skilled, hard-to-find and expensive workers with at least college-level training. This does not happen with other branches of engineering that underwent a much longer evolution: construction, mechanical engineering and the like.&lt;/p&gt;  &lt;p align="justify"&gt;For instance, it is highly unlikely that the worker of a factory that produces metal sheets, nails and barbed wire has a college degree. Even the highly skilled workers who assemble luxury cars most likely do not have that kind of education.&lt;/p&gt;  &lt;p align="justify"&gt;By contrast, even the smallest computer program requires programming skills which in turn require some math skills which in turn require some college-level education. The computer programmer, albeit being a white-collar individual, performs in fact a kind of work more akin with the work of a blue-collar in a factory than with the work of an engineer in the same factory. &lt;strong&gt;OBS: &lt;/strong&gt;it is the software manager who’s the peer of an engineer in a factory.&lt;/p&gt;  &lt;p align="justify"&gt;This kind of expensive workers makes software development very costly. If it takes so much skill and money to build something, it’s no wonder that hardly anyone is enthusiastic to invest in breaking it (which, put in simple terms, testing is).&lt;/p&gt;  &lt;p align="justify"&gt;So, testing is the &lt;strong&gt;Cinderella&lt;/strong&gt; of software.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;Problem no. 2: software lacks standards&lt;/h4&gt;  &lt;p align="justify"&gt;Software is one of the few fields of engineering that suffer from a deep, malignant lack of standards. Other branches of engineering have standards normalizing a much broader range of elements maneuvered during their production processes.&lt;/p&gt;  &lt;p align="justify"&gt;“&lt;em&gt;But we do have standards&lt;/em&gt;!” one might say. “&lt;em&gt;We have standards for&lt;/em&gt; &lt;strong&gt;C&lt;/strong&gt;&lt;em&gt;, &lt;/em&gt;&lt;strong&gt;C++&lt;/strong&gt;&lt;em&gt;, &lt;/em&gt;&lt;strong&gt;C#&lt;/strong&gt;&lt;em&gt;,&lt;/em&gt; &lt;strong&gt;Lisp&lt;/strong&gt; &lt;em&gt;… Even&lt;/em&gt; &lt;strong&gt;Prolog&lt;/strong&gt; &lt;em&gt;has its own standard&lt;/em&gt;!&lt;em&gt; And do not forget the standards of interfaces and protocols like&lt;/em&gt; &lt;strong&gt;CORBA&lt;/strong&gt;!!”.&lt;/p&gt;  &lt;p align="justify"&gt;It is very true that we do have standards for programming languages, protocols and interfaces. Yet, these are the &lt;em&gt;materials&lt;/em&gt; that we use to build software and not &lt;em&gt;components&lt;/em&gt; that we can simply assemble or slightly modify to build more complex things – as other engineering fields routinely do.&lt;/p&gt;  &lt;p align="justify"&gt;Let us go back a little to the metal factory producing barbed wire mentioned above. When producing the barbed wire, the workers need wire of a certain material and a certain thickness. The worker cuts the wire, tosses it, attaches the pieces together and voilà, we have barbed wire.&lt;/p&gt;  &lt;p align="justify"&gt;For barbed wire of a certain strength the worker uses wire of a certain kind of steel. For a certain kind of size the worker uses of a certain kind of thickness. For a rust-free barbed wire the worker uses a stainless material. Either way, the producer of barbed wire chooses the original wire based on some catalogues which specify the kind of steel, the thickness and the composition of each kind of wire he uses in production.&lt;/p&gt;  &lt;p align="justify"&gt;Let us assume now that the metal industry lacked a standard for wire thickness. The producer of barbed wire would have to produce his own simple, non-barbed wire of desired thickness for each kind of barbed wire the customer wants. That is, he would be the producer of his own &lt;em&gt;component&lt;/em&gt; (i.e. simple wire) as well. Imagine how much would barbed wire cost!&lt;/p&gt;  &lt;p align="justify"&gt;Unfortunately, this is exactly the situation with software development. Excepting some standardized programming languages and API libraries, we do not have much in terms of &lt;em&gt;standardized componentization&lt;/em&gt;. We have to build pretty much everything from scratch.&lt;/p&gt;  &lt;p align="justify"&gt;The lack of standards hinders software testing a lot. Every time you have to reinvent the wheel you have to test that wheel. Alas, we, software engineers, reinvent a lot of wheels because none of the available ones fits perfectly our immediate needs. So much wheel reinventing leaves little room for wheel testing.&lt;/p&gt;  &lt;p align="justify"&gt;So, one more time, testing is the &lt;strong&gt;Cinderella&lt;/strong&gt; of software.&lt;/p&gt;  &lt;h4&gt;Problem no. 3: software lacks interchangeable componentization&lt;/h4&gt;  &lt;p align="justify"&gt;Software is again at fault when it comes to interchangeable componentization. Other fields of engineering have a huge array of interchangeable components that one can choose from when assembling more complex constructions. Is a kind of transistor too expensive to buy from the &lt;strong&gt;Netherlands&lt;/strong&gt;? No problem, you get it from &lt;strong&gt;Taiwan&lt;/strong&gt;. Or from &lt;strong&gt;Singapore&lt;/strong&gt;. Or from &lt;strong&gt;China&lt;/strong&gt;. Provided they obey some well-known parameters, they can work just as well.&lt;/p&gt;  &lt;p align="justify"&gt;There is no such degree of interchangeability in software components. You cannot interchange an edit control from &lt;strong&gt;MFC&lt;/strong&gt; with one from &lt;strong&gt;Windows Forms&lt;/strong&gt; or with one from &lt;strong&gt;Gtk&lt;/strong&gt; or with one from &lt;strong&gt;Qt&lt;/strong&gt;. Although we &lt;em&gt;do&lt;/em&gt; have componentization, the components can be assembled and can work only in certain fixed environments - although they essentially do the same thing.&lt;/p&gt;  &lt;p align="justify"&gt;Not only that. Each component comes with different &lt;em&gt;rules&lt;/em&gt; for componentization – even for the same functionality. Although an edit control offers pretty much the same basic functionality across all the platforms and environments, when it comes to how to program it we observe that its properties &lt;em&gt;differ&lt;/em&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;For instance, in the case of steel wire, the thickness is always thickness and it’s always measured in integer millimeters. In the case of components, the thickness property can be &lt;strong&gt;Thickness&lt;/strong&gt;, &lt;strong&gt;theThickness&lt;/strong&gt;, &lt;strong&gt;GetThickness&lt;/strong&gt;, &lt;strong&gt;Width&lt;/strong&gt;, &lt;strong&gt;Size&lt;/strong&gt;, &lt;strong&gt;Dimension&lt;/strong&gt; or &lt;strong&gt;CoconutCrunch&lt;/strong&gt; and may return an &lt;code&gt;int&lt;/code&gt;, a &lt;code&gt;float&lt;/code&gt;, a &lt;code&gt;double&lt;/code&gt; or a &lt;code&gt;Numeric&lt;/code&gt; while the returned value may mean &lt;strong&gt;millimeters&lt;/strong&gt;, fractions of &lt;strong&gt;meters&lt;/strong&gt;, &lt;strong&gt;miles&lt;/strong&gt; or &lt;strong&gt;Ångströms&lt;/strong&gt;. There is no support that permits uniform handling of componentization. &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p align="justify"&gt;That’s why we have specialists in “IT technologies” and not plain and simple “IT specialists”. Is &lt;strong&gt;Windows Forms&lt;/strong&gt; that different from &lt;strong&gt;Qt&lt;/strong&gt; when it comes to the user experience? Or, is the difference between them greater than, say, the difference between a &lt;strong&gt;Ford&lt;/strong&gt; and a &lt;strong&gt;Chrysler&lt;/strong&gt; car? I don’t think so. Yet, although &lt;strong&gt;Windows Forms&lt;/strong&gt; isn’t radically different from &lt;strong&gt;Qt&lt;/strong&gt;, only few people can master both well – let alone combining them into the same application.&lt;/p&gt;  &lt;p align="justify"&gt;The result? A lot of energy and investment goes into training employees to learn a particular “IT technology” - that is, a particular way of componentization – and by consequence little traction is left for considering testing as an engineering process in its own right.&lt;/p&gt;  &lt;p&gt;So, one more tine, testing is the &lt;strong&gt;Cinderella&lt;/strong&gt; of software.&lt;/p&gt;  &lt;h4&gt;&lt;/h4&gt;  &lt;h4&gt;Problem no. 4: software lacks testability&lt;/h4&gt;  &lt;p align="justify"&gt;Software is equally poor in terms of testability compared to other branches of engineering. Nearly every engineering device has ways to tell how well it runs at any point in time. That is, it has specialized interfaces that a technician can easily check in order to verify whether the system runs well and if not what’s the most probable cause.&lt;/p&gt;  &lt;p align="justify"&gt;Well, software is different. Much different. If you want to see what’s wrong with a piece of software then you have to be equally qualified as or even &lt;em&gt;more&lt;/em&gt; qualified than the developer himself. The reason? Support for testability in none. The inventors of programming languages designed those languages as if everything would work from the first shot. It’s amazing that even debuggers exist!&lt;/p&gt;  &lt;p align="justify"&gt;Imagine what would be if, when you go with your car for routine checkup, the technicians had to bring an engineer from the producing factory to disassemble the whole engine just to detect that the fuse ran out.&lt;/p&gt;  &lt;p align="justify"&gt;That’s pretty much the state of the art in software diagnosis today: if one wants to figure out what’s going on inside of a piece of software he must surgically intervene via the debugger right into the bowels of the faulty component. The procedure equally applies if the defect is due to some stupid typo or to some profound, architectural error.&lt;/p&gt;  &lt;p align="justify"&gt;If each software system is so arcane by design, there’s no surprise that testing is so much helpless, costly and it takes so long.&lt;/p&gt;  &lt;p align="justify"&gt;So, one more time, testing is the &lt;strong&gt;Cinderella&lt;/strong&gt; of software.&lt;/p&gt;  &lt;h4&gt;Problem no. 5: testing lacks a language of its own&lt;/h4&gt;  &lt;p align="justify"&gt;Every speaker has his own tongue but the software tester, much like the Apostles of Christ at Pentecost, must speak other tongues, namely the ones of the developers. By tongues I mean, of course, programming languages.&lt;/p&gt;  &lt;p align="justify"&gt;Imagine what would be if a mechanical test engineer employed in testing some metal sheets the very same tools that produced those sheets. How many defects in the sheets would that test engineer find?&lt;/p&gt;  &lt;p align="justify"&gt;Let’s see what happens in the software realm. Does the developer use &lt;strong&gt;C++&lt;/strong&gt;? So must the tester do. Is the developer a friend of &lt;strong&gt;C#&lt;/strong&gt;? The very same language is the first choice for the &lt;strong&gt;.NET&lt;/strong&gt; tester. What about the tester of &lt;strong&gt;Prolog&lt;/strong&gt;, &lt;strong&gt;Lisp&lt;/strong&gt; or &lt;strong&gt;Python&lt;/strong&gt; systems? I doubt that he’d use &lt;strong&gt;C++&lt;/strong&gt;, &lt;strong&gt;Smalltalk&lt;/strong&gt; or &lt;strong&gt;Simula&lt;/strong&gt; to do his job.&lt;/p&gt;  &lt;p align="justify"&gt;Not only the tester has to use the language which the developer uses, he doesn’t even have much other choice. The current programming languages have truly great features to construct things. Does this mean they are appropriate to &lt;em&gt;test&lt;/em&gt; things? Are concepts like &lt;strong&gt;LINQ&lt;/strong&gt;, &lt;strong&gt;anonymous delegates&lt;/strong&gt; or &lt;strong&gt;dynamically typed variables&lt;/strong&gt; that important for the tester of systems written in &lt;strong&gt;C#&lt;/strong&gt;?&lt;/p&gt;  &lt;p align="justify"&gt;What about the real needs of the tester in terms of automating his work? It seems that, besides some narrow-scoped languages lacking general acceptance (each testing tool with its own language), there’s nothing in terms of programming languages designed &lt;em&gt;specifically&lt;/em&gt; for testing.&lt;/p&gt;  &lt;p align="justify"&gt;Without tools like an appropriate programming language for testing, the tester must rely on a fragmented world of tools, methodologies and languages that hinder the ability of the software testing industry to produce long lasting, durable, ever-growing and transmissible know-how for the sake of its own engineers.&lt;/p&gt;  &lt;p align="justify"&gt;So, one more time, testing is the &lt;strong&gt;Cinderella&lt;/strong&gt; of software.&lt;/p&gt;  &lt;h4&gt;Problem no. 6: software itself is Cinderella&lt;/h4&gt;  &lt;p align="justify"&gt;By looking at the problems above one can easily see that what’s wrong with software testing is not necessarily wrong with testing itself but rather with the industry as a whole. To put it bluntly, software itself is, in some way, the &lt;strong&gt;Cinderella&lt;/strong&gt; of engineering.&lt;/p&gt;  &lt;p align="justify"&gt;How can one call such as vibrant, dynamic and money-watered industry a &lt;strong&gt;Cinderella&lt;/strong&gt;? How about Bill Gates and other big figures who amassed fortunes that in other domains took generations to accumulate?&lt;/p&gt;  &lt;p align="justify"&gt;Maybe the biggest foe of software is its very success. As the industry was developing at such speed, the rigor and the decantation which are at the core of every analytic endeavor fell, in the case of software, on the second level. Too eager to serve the world we, software engineers, were perhaps overlooking the state of our own back yard.&lt;/p&gt;  &lt;p align="justify"&gt;I have no doubt that our industry will eventually mature and that software will become, some day, more like the steel or automotive industries: boasting some big players in the field with a myriad of services, big and small, around. I am also sure that, by that time, software testing would have gained its deserved place as a rigorous and well respected discipline.&lt;/p&gt;  &lt;p align="justify"&gt;Till then, software testing remains the &lt;strong&gt;Cinderella&lt;/strong&gt; of software. That is, the &lt;strong&gt;Cinderella&lt;/strong&gt; of &lt;strong&gt;Cinderella&lt;/strong&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-5197761825225804488?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/5197761825225804488/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/software-cinderella.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/5197761825225804488'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/5197761825225804488'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/software-cinderella.html' title='Software Cinderella'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-5499206199456009983</id><published>2010-01-11T06:00:00.000+02:00</published><updated>2010-01-11T07:31:18.727+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='test design'/><title type='text'>Right to the internals</title><content type='html'>&lt;img style="display: inline; margin-left: 10px; margin-right: 10px" align="left" src="http://upload.wikimedia.org/wikipedia/commons/0/03/Crucian_carp-bowels_2.JPG" width="300" height="300" /&gt;   &lt;p align="justify"&gt;I think I’m not wrong when saying that software testing is mainly an &lt;em&gt;external&lt;/em&gt; activity - as opposed to software development which is inherently &lt;em&gt;internal&lt;/em&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;Indeed, the final judges of how good a piece of software is are its beneficiaries, its ultimate users who don’t care that much about &lt;em&gt;how&lt;/em&gt; the software does what it does. Therefore we, as software testers, need to be some sort of &lt;em&gt;super&lt;/em&gt;-users, more interested in how the software functions than how it’s built. This contrasts with the main agenda of software developers who cannot avoid knowing the intricacies of what they build.&lt;/p&gt;  &lt;p align="justify"&gt;&lt;/p&gt;  &lt;p align="justify"&gt;Yet, going “inside” is more valuable than one might think because, at least according to &lt;strong&gt;Sir C.A.R. Hoare&lt;/strong&gt;, “&lt;em&gt;the success of tests is that they test the &lt;strong&gt;programmer&lt;/strong&gt;, not the program&lt;/em&gt;” (emphasis mine). OBS: one can find the original article &lt;a href="http://cacm.acm.org/magazines/2009/10/42360-retrospective-an-axiomatic-basis-for-computer-programming/fulltext" target="_blank"&gt;here&lt;/a&gt;. I got the extract from &lt;a href="http://herbsutter.wordpress.com/2009/10/26/hoare-on-testing/" target="_blank"&gt;Herb Sutter’s blog&lt;/a&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;We should not forget that &lt;strong&gt;Sir Hoare&lt;/strong&gt; is one of the fathers of formal methods in software verification yet this didn’t stop him from saying “&lt;em&gt;One thing&lt;/em&gt;&lt;em&gt; I got spectacularly wrong &lt;/em&gt;(i.e. testing)” (my note). As a side observation, I believe that formal methods for software verification should be within every tester’s horizon (more about that in future posts).&lt;/p&gt;  &lt;p align="justify"&gt;In this article I propose a systematic method of “testing the programmer” by going “inside” the code he produces - obviously, the main beneficiary of the method may be the developer himself but we assume that the developer doesn’t have time to test his own code beyond writing very basic unit tests.&lt;/p&gt;  &lt;p align="justify"&gt;The examples here are in &lt;strong&gt;C#&lt;/strong&gt; for &lt;strong&gt;.NET&lt;/strong&gt; and &lt;strong&gt;NUnit&lt;/strong&gt; yet the method works for any language that admits conditional compilation, any environment that allows some sort of code decoration and any test harness which uses code decoration to detect test drivers and permits the test drivers to reside within the system under test.&lt;/p&gt;  &lt;p align="center"&gt;&lt;strong&gt;* * * * *&lt;/strong&gt;&lt;/p&gt;  &lt;p align="justify"&gt;The usual method to write tests for a particular module is to create another module with the same name but the &lt;strong&gt;_t&lt;/strong&gt; suffix and to place the testing code in there. For example, if the &lt;code&gt;Account&lt;/code&gt; class from the &lt;a href="http://nunit.org/index.php?p=quickStart&amp;amp;r=2.5.3" target="_blank"&gt;NUnit Quick Start Tutorial&lt;/a&gt; resides within &lt;strong&gt;account.dll&lt;/strong&gt;, then the &lt;code&gt;AccountTest&lt;/code&gt; fixture goes to &lt;strong&gt;account_t.dll&lt;/strong&gt;.&lt;/p&gt;  &lt;p align="justify"&gt;This makes sense: we keep the code clean and we don’t mix apples and pears. Yet, abiding strictly to this full separation approach has its drawbacks:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;     &lt;div align="justify"&gt;It is not possible to write tests for internal classes or methods except by using reflection – which is not available on all the platforms and is not easy to use anyhow.&lt;/div&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;div align="justify"&gt;The code that tests and the code being tested load as separate units. While this doesn’t matter much in most cases, sometimes the initialization code of the SUT may have important side effects (see static constructors in &lt;strong&gt;C#&lt;/strong&gt;), hence being able to “inject” the tests right into the SUT may really make a difference.&lt;/div&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p align="justify"&gt;The main idea herein is to transform the SUT itself into a test driver by injecting part of the tests right within it.&lt;/p&gt;  &lt;p align="center"&gt;&lt;strong&gt;* * * * *&lt;/strong&gt;&lt;/p&gt;  &lt;p align="justify"&gt;Going back to the &lt;code&gt;Account&lt;/code&gt; class from the &lt;strong&gt;NUnit Quick Start Tutorial&lt;/strong&gt;, we make a fixture out of it and we move the tests inside (see the code in &lt;strong&gt;&lt;font color="#800000"&gt;red&lt;/font&gt;&lt;/strong&gt;):&lt;/p&gt; &lt;code&gt;namespace bank    &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#ff0000"&gt;&lt;strong&gt;using NUnit.Framework;        &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [TestFixture]&lt;/strong&gt;&lt;/font&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public class Account     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;float&lt;/span&gt; balance;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Deposit(&lt;span class="kwrd"&gt;float&lt;/span&gt; amount) { balance+=amount; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Withdraw(&lt;span class="kwrd"&gt;float&lt;/span&gt; amount) { balance-=amount; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TransferFunds(Account destination, &lt;span class="kwrd"&gt;float&lt;/span&gt; amount) { }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;float&lt;/span&gt; Balance { get{ &lt;span class="kwrd"&gt;return&lt;/span&gt; balance; } }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;&lt;font color="#ff0000"&gt;[Test]        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public void TransferFunds()         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/strong&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Account source = &lt;span class="kwrd"&gt;new&lt;/span&gt; Account();         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; source.Deposit(200.00F);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Account destination = &lt;span class="kwrd"&gt;new&lt;/span&gt; Account();         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; destination.Deposit(150.00F);         &lt;br /&gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; source.TransferFunds(destination, 100.00F);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Assert.AreEqual(250.00F, destination.Balance);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Assert.AreEqual(100.00F, source.Balance);         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/font&gt;&lt;/strong&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;} &lt;/code&gt;  &lt;p align="justify"&gt;The problem is that we altered the code so that it now has declarations it doesn't normally need. We get rid of the test declarations by enclosing them between &lt;code&gt;#if TEST … #endif&lt;/code&gt; directives:&lt;/p&gt;  &lt;p align="justify"&gt;&lt;code&gt;namespace bank      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#ff0000"&gt;&lt;strong&gt;#if TEST&lt;/strong&gt;&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;using NUnit.Framework;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#ff0000"&gt;#endif&lt;/font&gt;&lt;/strong&gt;&lt;/code&gt;&lt;code&gt;&lt;strong&gt;        &lt;br /&gt;        &lt;br /&gt;&lt;font color="#ff0000"&gt;&amp;#160;&amp;#160;&amp;#160; #if TEST&lt;/font&gt;         &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [TestFixture]         &lt;br /&gt;&lt;font color="#ff0000"&gt;&amp;#160;&amp;#160;&amp;#160; #endif&lt;/font&gt;&lt;/strong&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public class Account       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;float&lt;/span&gt; balance;       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Deposit(&lt;span class="kwrd"&gt;float&lt;/span&gt; amount) { balance+=amount; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Withdraw(&lt;span class="kwrd"&gt;float&lt;/span&gt; amount) { balance-=amount; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; TransferFunds(Account destination, &lt;span class="kwrd"&gt;float&lt;/span&gt; amount) { }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;float&lt;/span&gt; Balance { get{ &lt;span class="kwrd"&gt;return&lt;/span&gt; balance; } }       &lt;br /&gt;      &lt;br /&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #if TEST&lt;/strong&gt;&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [Test]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public void TransferFunds()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Account source = &lt;span class="kwrd"&gt;new&lt;/span&gt; Account();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; source.Deposit(200.00F);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Account destination = &lt;span class="kwrd"&gt;new&lt;/span&gt; Account();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; destination.Deposit(150.00F);       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; source.TransferFunds(destination, 100.00F);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Assert.AreEqual(250.00F, destination.Balance);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Assert.AreEqual(100.00F, source.Balance);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&lt;font color="#ff0000"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #endif&lt;/strong&gt;&lt;/font&gt;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;}&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Obviously, the same source code of the system under test should produce two binaries instead of one: &lt;strong&gt;account.dll&lt;/strong&gt; compiled &lt;em&gt;without&lt;/em&gt; the &lt;code&gt;TEST&lt;/code&gt; definition and containing the &lt;code&gt;Account&lt;/code&gt; class as a functional class as well as &lt;strong&gt;account_it.dll&lt;/strong&gt; compiled &lt;em&gt;with&lt;/em&gt; the &lt;code&gt;TEST&lt;/code&gt; definition and containing the &lt;code&gt;Account&lt;/code&gt; class as a test fixture (&lt;strong&gt;_it&lt;/strong&gt; stands for “internal tests”). By the same token, any test that tests the &lt;code&gt;Account&lt;/code&gt; class externally should go to &lt;strong&gt;account_et.dll&lt;/strong&gt; (&lt;strong&gt;_et&lt;/strong&gt; meaning “external tests”).&lt;/p&gt;  &lt;p align="center"&gt;&lt;strong&gt;* * * * *&lt;/strong&gt;&lt;/p&gt;  &lt;p align="justify"&gt;The main advantage of the method consists in the complete access that the tests gain to the internals of the system. This is not as trivial as it seems. For instance, in the example above, the &lt;code&gt;TransferFunds&lt;/code&gt; test has direct access to the &lt;strong&gt;balance&lt;/strong&gt; private field. This opens the door to intimately testing the &lt;strong&gt;Balance&lt;/strong&gt; property which is &lt;em&gt;supposed&lt;/em&gt; to return the value of &lt;code&gt;balance&lt;/code&gt; but it &lt;em&gt;may&lt;/em&gt; be buggy.&lt;/p&gt;  &lt;p align="justify"&gt;Such advantage doesn’t come without costs, however. The main hindrance is the needed access to the developer’s code. Depending on organization, such access may be subject to restrictions. In the case of software testing organizations, a software house may not feel at ease to let some external contractor to modify its code.&lt;/p&gt;  &lt;p align="justify"&gt;However, internal testing is a powerful tool in the hands of software developers committed to quality and in the hands of the software testers allowed to bring their contribution to the very core of the system they are required to test.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-5499206199456009983?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/5499206199456009983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/right-to-internals.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/5499206199456009983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/5499206199456009983'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/right-to-internals.html' title='Right to the internals'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5907126310633254820.post-652976521914088869</id><published>2010-01-01T00:01:00.001+02:00</published><updated>2010-01-01T03:05:23.614+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bug hunting'/><category scheme='http://www.blogger.com/atom/ns#' term='planning'/><title type='text'>Harmony between Dr. Jekyll and Mr. Hyde</title><content type='html'>&lt;div style="text-align: center; clear: both" class="separator"&gt;&lt;a style="margin-bottom: 1em; float: left; clear: left; margin-right: 1em" title="Courtesy of PhotoBucket.com" href="http://i6.photobucket.com/albums/y237/PattyRid/Dougray%20Scott/dvdcover-1.jpg" target="_blank" imageanchor="1"&gt;&lt;img border="0" src="http://i6.photobucket.com/albums/y237/PattyRid/Dougray%20Scott/dvdcover-1.jpg" width="224" height="320" /&gt;&lt;/a&gt; &lt;/div&gt;  &lt;div align="justify"&gt;   &lt;p&gt;Shortly after I started my career as a Software Design Engineer in Test at Microsoft (this happened sooo long ago) I took an internal course on software testing. The teacher (whose name I don’t recall) ended his presentation with a vigorous “&lt;em&gt;and now go ahead and find bugs!&lt;/em&gt;”.&lt;/p&gt;    &lt;p&gt;We, the students, were quite thrilled: “&lt;i&gt;so &lt;u&gt;that&lt;/u&gt;’s what testing is all about!&lt;/i&gt;”. I don’t know about the others, but I did take that preachment seriously and as a good boy I measured my performance by the number of bugs I was bringing to the fore within a given timeframe – and so did my managers, by the way.&lt;/p&gt;    &lt;p&gt;Little did I know …&lt;/p&gt;    &lt;p align="center"&gt;&lt;strong&gt;* * * * *&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;While finding bugs is a good target to aim in software testing, it is not the only one and I believe it is not the most important one (I know it’s blasphemous; I plead guilty).&lt;/p&gt;    &lt;p&gt;Let us think about the user a little. What’s most useful to him: a piece of software with a huge pile of fixed bugs behind but with incomplete or barely tested features OR a piece of software with fewer uncovered bugs but with the most common features &lt;i&gt;better&lt;/i&gt; tested?&lt;/p&gt;    &lt;p&gt;While the professional tester is tempted to choose the first variant, I’d rather say that the regular user – who rarely stretches a piece of software to its limits – would find the second option more enticing.&lt;/p&gt;    &lt;p&gt;Users don’t care about software, they care about getting their job done with software. Software is a tool - nothing more, nothing less. &lt;/p&gt;    &lt;p align="center"&gt;&lt;strong&gt;* * * * *&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;There are two hats in a tester’s wardrobe:&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;       &lt;div align="justify"&gt;One is borrowed from &lt;b&gt;Mr. Hyde&lt;/b&gt;: the tester must be the bad guy who cracks the developer’s hard work. He must be smart. He must be imaginative. He must even be on the evil side a little.&lt;/div&gt;     &lt;/li&gt;      &lt;li&gt;       &lt;div align="justify"&gt;The other one fits &lt;b&gt;Dr. Jekyll&lt;/b&gt;: the tester must decently verify all the features placed on his plate by management. He must plan. He must be rigorous. He must be a church-going, neighbor-loving good citizen. &lt;/div&gt;     &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;Being &lt;b&gt;Mr. Hyde&lt;/b&gt; is quite fun. Even addictive. “&lt;i&gt;Finding bugs, boss? Sure, no problem, any time. Just give me some software to break!&lt;/i&gt;”. We find bugs because they’re proof that WE are good. That WE are smart. That WE are able to think of what nobody has thought before. And there are so many bugs out there, folks. Plenty!&lt;/p&gt;    &lt;p&gt;Being &lt;b&gt;Dr. Jekyll&lt;/b&gt; is not as fun as being &lt;b&gt;Mr. Hyde&lt;/b&gt;. There’s no adrenaline rush in bookkeeping progress little by little. We don’t usually exclaim “&lt;i&gt;yesterday I had only 10% of the features covered but today I jumped to a staggering 12% and if I keep apace, tomorrow I’ll be at 14%! I just can’t wait!!!&lt;/i&gt;” &lt;/p&gt;    &lt;p&gt;The sad part is that &lt;b&gt;Mr. Hyde&lt;/b&gt; has the bad habit of taking over the whole person – that of the tester, in our case. If there’s no miraculous potion around, the prospects are not good.&lt;/p&gt;    &lt;p align="center"&gt;&lt;strong&gt;* * * * *&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;It is true that there are so many bugs out there and it is also true that the best way to reveal them is to have a hacker-like mindset – at least until we have intelligent software to find the bugs for us.&lt;/p&gt;    &lt;p&gt;Unfortunately, the bugs are not just “many”. They are &lt;i&gt;too&lt;/i&gt; many - and that is the problem with the hacker mindset because the most precious resource – time – is never enough to find all the bugs. Not even half the bugs. Not even whatever-significant-percent of bugs. Not even the largest share of the most interesting bugs.&lt;/p&gt;    &lt;p&gt;It’s too bad so many bugs remain out there, but software needs to ship. Bosses need it and users need it. Nobody can wait indefinitely until all the interesting bugs are found and yet everyone expects that we, as constituents of software organizations, contribute to the delivery of good software - in time, within budget, bearing the right amount of features and having enough quality for the market.&lt;/p&gt;    &lt;p&gt;It results that the software tester must find the right balance between searching pro-actively for bugs and planning carefully the testing effort in order to meet deadlines – even at the cost of leaving inside presumably many interesting bugs.&lt;/p&gt;    &lt;p&gt;I believe that this ability to reconcile the two extremes is the miraculous potion that keeps &lt;b&gt;Dr. Jekyll&lt;/b&gt; and &lt;b&gt;Mr. Hyde &lt;/b&gt;in harmony. Fortunately to us, that potion never runs out – if we take good care.&lt;/p&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5907126310633254820-652976521914088869?l=mariusfilipontesting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mariusfilipontesting.blogspot.com/feeds/652976521914088869/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/harmony-between-dr-jekyll-and-mr-hyde.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/652976521914088869'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5907126310633254820/posts/default/652976521914088869'/><link rel='alternate' type='text/html' href='http://mariusfilipontesting.blogspot.com/2010/01/harmony-between-dr-jekyll-and-mr-hyde.html' title='Harmony between Dr. Jekyll and Mr. Hyde'/><author><name>Marius Filip</name><uri>http://www.blogger.com/profile/11369035654997497568</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_e3SRrbdPqkw/S92JVCBqdaI/AAAAAAAAA6M/h5RsU0K5mmg/S220/Matrix+128x128.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://i6.photobucket.com/albums/y237/PattyRid/Dougray%20Scott/th_dvdcover-1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
