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

<channel>
	<title>My Other Pants &#187; white</title>
	<atom:link href="http://myotherpants.com/tag/white/feed/" rel="self" type="application/rss+xml" />
	<link>http://myotherpants.com</link>
	<description>I left it in my other pants</description>
	<lastBuildDate>Sun, 28 Feb 2010 21:27:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Automatic, for the People</title>
		<link>http://myotherpants.com/2009/06/automatic-for-the-people/</link>
		<comments>http://myotherpants.com/2009/06/automatic-for-the-people/#comments</comments>
		<pubDate>Sun, 28 Jun 2009 23:34:04 +0000</pubDate>
		<dc:creator>Ball</dc:creator>
				<category><![CDATA[work safe]]></category>
		<category><![CDATA[ironruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[white]]></category>

		<guid isPermaLink="false">http://myotherpants.com/?p=79</guid>
		<description><![CDATA[Confession, this is the album where I stopped listening to REM.  Dunno why, because Monster was one of the best albums I never bought.
Let us review our strategy, especially referencing our usage of White.  I find it interesting that Test Complete makes it so hard to &#8220;do the right thing&#8221; as propounded by [...]]]></description>
			<content:encoded><![CDATA[<p>Confession, this is the album where I stopped listening to REM.  Dunno why, because Monster was one of the best albums I never bought.</p>
<p>Let us review our strategy, especially referencing our usage of <a href="http://white.codeplex.com">White</a>.  I find it interesting that Test Complete makes it so hard to &#8220;do the right thing&#8221; as propounded by both Scripting GUI Tests in Ruby and by White.  And just what is that?</p>
<p>The responsibility of the test script is to</p>
<ul>
<li> perform a series of actions and verifications.</li>
<li> allow someone to read the script and understand what the hell is going on.</li>
</ul>
<p><span id="more-79"></span></p>
<p>The first is a gimme.  The second is interesting.  When I have my developer hat on, I believe code is read more often then it is written. Wearing my manual tester hat, I believe the scripts should be clear and show intent.  Tricky scripts are trouble.  They are also a pain to maintain.  So, if automated testing the meeting of these two worlds, the clarity and intent of the scripts must be sacrosanct.  The libraries the scripts use, on the other hand, just need to be treated like code and kept maintainable.</p>
<p>What do I want my test scripts to look like?  There are two options, DSL, or clearly abstracted test code.</p>
<p>First, lets look at DSLs, Baby!  WAHOOO! Tests that double as manual tests!</p>
<pre name="code" class="ruby">
open sekrit with New Document
insert image "picture.png" into sheet
first image item should match stored image "stored_0001.png"
</pre>
<p>I could do that.  I could use some functional programming language.  I could also use something like <a href="http://cukes.info/">cucumber</a> and code behind my feature files.  But what&#8217;s the point?  All I need is clarity, so the auditors / business people understand.  I LIKE dsls, but this buys us nothing right now.</p>
<p>Option two uses Objects to clarify the application.</p>
<pre name="code" class="ruby">
sek = Sekrit.open( :New_Document )
doc = sek.document

doc.add_image("picure.png")
Assert.equal doc.images[0].as_bitmap, Stored.images["0001.png"]
</pre>
<p>This is at the proper level of abstraction for a slightly motivated business user to understand.  What they don&#8217;t care about at this level is the control hierarchy and control manipulation.  Unless the requirements say, &#8220;via a popup menu&#8221; or some such.</p>
<p>If you&#8217;re going to be technical, this is a <a href="http://en.wikipedia.org/wiki/Facade_pattern">facade</a>.  It&#8217;s a wrapper to the complex underbelly of the white framework.  It allows for a higher level use of the collected objects and re-use as we don&#8217;t have to repeat the code for complex actions and interactions.  It also decouples our tests from changes in our application.  I&#8217;ve had to chase that down in our current automation set, and I hate it.</p>
<p>How do we build up this abstraction?  To be compatible with White&#8217;s recommended practices, I&#8217;m going to call this facade a &#8220;Screen&#8221;.  We&#8217;re going to write a test for an application for which we have no source.  Download <a href="http://white.codeplex.com/">blu</a> and warm up your tweetin&#8217; fingers.  We&#8217;re going to log in!</p>
<pre name="code" class="ruby">
# our screens
class Blu
  def initialize(application, window)
    @app = application
    @win = window
  end
  def login_screen
    return LoginScreen.new(@app, @win)
  end
end
class LoginScreen
  def initialize(application, window)
    @app = application
    @win = window
  end
  def login_user( username, password, remember = false)
    @win.get_textbox("UsernameTextBox").enter username
    @win.get_textbox("PasswordTextBox").enter password
    rem = @win.get_checkbox("Rememberage")
    if rem.checked != remember
      rem.enter " "
    end
    @win.get_button("LoginButton").click
  end
end
</pre>
<p>You noticed that the BluScreen has a LoginScreen?  Our application has regions and concepts to which we wish to refer.  For example, we may want to represent a ribbon control, a toolbar, different types of documents, or even the clipboard.</p>
<p>How do we use these screens?  Let&#8217;s flesh out this little story in <a href="http://dannorth.net/whats-in-a-story">Dan North &#8220;Story&#8221; format</a>.</p>
<pre> As I malicious user, so I can't defame Brian's good twitter name,
   Given blu is open
   And no one is logged in
   When I attempt to log in using a bad password
   Then I should see a warning that my login information was incorrect
</pre>
<pre name="code" class="ruby">
app = Application.attach("blu")
win = app.get_window("blu")

blu = Blu.new(app, win)
login = blu.login_screen
login.login_user( "Myotherpants", "NoWai!" )

# A test would have assertion here...
</pre>
<p>I&#8217;m holding out on you. The truth of the matter is, I started with the test steps first, then made screens that abstracted those steps.  But there&#8217;s magic in the screens, they have magic strings passed around like <code name="code" class="ruby">@win.get_checkbox("Rememberage")</code>.  Where did that come from?  I got it from <a href="http://msdn.microsoft.com/en-us/library/ms727247.aspx">UISpy</a>.  I&#8217;ve read about <a href="http://www.codeproject.com/KB/WPF/WoodstockForWPF.aspx">Woodstock</a>, <a href="http://blois.us/blog/2006/08/long-time-since-my-last-post-but-dont_21.html">Snoop</a>, and a few other tools, but UISpy is the only tool I used for this post.  It is in the Windows SDK.  UISpy shows a tree of controls.  When you click on one, it hilights it with a red box.  It also displays information such as the automation Id, those magic strings we have scattered in our code.  Before my two picture tutorial on UISpy, let me note, those strings are what&#8217;s likely to break your script in the future as your application grows.</p>
<div id="attachment_85" class="wp-caption alignnone" style="width: 385px"><a href="http://myotherpants.com/wp-content/uploads/2009/06/uispy-screen.png"><img src="http://myotherpants.com/wp-content/uploads/2009/06/uispy-screen-300x226.png" alt="UI Spy looking at a textbox" title="uispy-screen" width="300" height="226" class="size-medium wp-image-85" /></a><p class="wp-caption-text">UI Spy looking at a textbox</p></div><br />
<div id="attachment_86" class="wp-caption alignnone" style="width: 241px"><a href="http://myotherpants.com/wp-content/uploads/2009/06/blu-screen.png"><img src="http://myotherpants.com/wp-content/uploads/2009/06/blu-screen-171x300.png" alt="Blu when UISpy is indicating a textfiled" title="blu-screen" width="171" height="300" class="size-medium wp-image-86" /></a><p class="wp-caption-text">Blu when UISpy is indicating a textfiled</p></div>
<p>what else is there? </p>
<p>These aren&#8217;t tests, they are automation.  I&#8217;ll eventually wrap the automation with RSpec and get some real tests.  I&#8217;ll get to Cucumber.  <a href="http://myotherpants.com/2009/09/crouching-donny-iron-cucumber/">I&#8217;ll publish examples</a>.  I promise.</p>
<p>But next, I want to address three types of custom controls:<br />
  User controls, Inhereited and Templated Controls, and Framework Elements.  Another problem is finding un-named controls.  I&#8217;ll see you next week.</p>
<p>One last bit, here&#8217;s what the white ruby library is starting to look like.</p>
<pre name="code" class="ruby">
white_loc = (File.dirname(__FILE__) + "\\White_Bin\\")
$LOAD_PATH.push(white_loc)
require "White.Core.dll"

Application = Core::Application
Button = Core::UIItems::Button
CheckBox = Core::UIItems::CheckBox
TextBox = Core::UIItems::TextBox
Window = Core::UIItems::WindowItems::Window
SearchCriteria = Core::UIItems::Finders::SearchCriteria

class Window
  def get_button(*args)
    self.method(:get).of(Button).call(*args)
  end
  def get_button_labeled(label)
    self.get_button(SearchCriteria.by_text(label))
  end
  def get_checkbox(*args)
    self.method(:get).of(CheckBox).call(*args)
  end
  def get_textbox(*args)
    self.method(:get).of(TextBox).call(*args)
  end
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://myotherpants.com/2009/06/automatic-for-the-people/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Generic White Rubies are Open</title>
		<link>http://myotherpants.com/2009/06/generic-white-rubies-are-open/</link>
		<comments>http://myotherpants.com/2009/06/generic-white-rubies-are-open/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 21:15:23 +0000</pubDate>
		<dc:creator>Ball</dc:creator>
				<category><![CDATA[work safe]]></category>
		<category><![CDATA[ironruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[white]]></category>

		<guid isPermaLink="false">http://myotherpants.com/?p=76</guid>
		<description><![CDATA[I&#8217;ve been continuing my exploration of IronRuby and White for gui testing.  I expected to deal with Automation IDs first, but I&#8217;ll get back to that.  For now I&#8217;m tying IronRuby to White, and handling generics.
My install of white is not in the GAC, so I&#8217;ll be requireing DLLs from a directory.  [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been continuing my exploration of <a href="http://myotherpants.com/2009/06/thoughts-on-gui-testing/">IronRuby and White for gui testing</a>.  I expected to deal with Automation IDs first, but I&#8217;ll get back to that.  For now I&#8217;m tying IronRuby to White, and handling generics.</p>
<p>My install of white is not in the GAC, so I&#8217;ll be requireing DLLs from a directory.  DLLs are looked for in ruby&#8217;s <code>$LOAD_PATH</code>, just like ruby libraries.  It&#8217;s an array.  You&#8217;ll notice that White suggests also including an NUnit dll, but I&#8217;ve not needed that with RSpec.  And, I want to shorten the namespace stuff.  So let&#8217;s start with white.rb and we&#8217;ll add to it later.</p>
<pre name="code" class="ruby">
white_loc = "C:\\Projects\\Libs\\White_Bin_0.18"
$LOAD_PATH.push(white_loc)
require "White.Core.dll"
Application = Core::Application
</pre>
<p><span id="more-76"></span></p>
<p>So, next we just start using the application.  I want to launch my application, conviniently called &#8220;sekrit.&#8221;  I need to find the window titled &#8220;Sekrit (version 0.5)&#8221;.  Then I need to call the C# method <code>win.Get&lt;Button&gt;("Open")</code> but that uses generics that ruby doesn&#8217;t have.  Using what I learned from a <a href="http://stackoverflow.com">Stack Overflow</a> post <a href="http://stackoverflow.com/questions/895585/how-to-invoke-an-overloaded-generic-methods-in-ironruby">how to invoke an overloaded generic method in ironruby</a>, we can work around that in IronRuby 0.5.</p>
<pre name="code" class="ruby">
require 'white'
app = Application.launch("c:\\projects\\sekrit\\build\\sekrit.exe")
win = app.get_window("Sekrit (version 0.5)")
win.focus
win.method(:get).of(Core::UIItems::Button).call("Open")
</pre>
<p>Oh, lawdy!  Did you see that last line?  It ain&#8217;t pretty.  This is something we&#8217;ll be doing a lot of, so let&#8217;s wrap that up.  I need to add, essentially, a non-generic extention method to wrap the generic call.  But, do it with Ruby to extend a .NET class.  Back to white.rb for some open class magic.</p>
<pre name="code" class="ruby">
class Core::UIItems::WindowItems::Window
  def get_button(*args)
    self.method(:get).of(Core::UIItems::Button).call(*args)
  end
end
</pre>
<p>Now that cleans up our earlier program.</p>
<pre name="code" class="ruby">
require 'white'
app = Application.launch("c:\\projects\\sekrit\\build\\sekrit.exe")
win = app.get_window("Sekrit (version 0.5)")
win.focus
win.get_button("Open")
</pre>
<p>Okay, one more problem.  I talked about RSpec, but that&#8217;s because I hacked my install.  There&#8217;s a known bug in IronRuby 0.5&#8217;s implementation of <code>File.expand_path(file_name)</code> that uses the .NET System::IO::Path methods that throws execptions when you try to expand a path with &#8220;:8&#8243; on the end to help track line numbers.  I don&#8217;t know yet if it&#8217;s been fixed.  If not, that may be another post.</p>
<p>So, what&#8217;s left?  RSpec doesn&#8217;t run out of the box.  I need to wrap some stuff up so I can say <code> app.open_file("some_file.ext") </code> and other higher level &#8220;user action&#8221; concepts (those shouldn&#8217;t be in white.rb, but sekrit.rb).  I need to handle finding controls quickly and easily.  I&#8217;ll take a look at that this weekend and see what I can find.  Especially, since I&#8217;ll be hanging with a WPF MVP both this evening at IndyALT.NET and on Saturday.</p>
]]></content:encoded>
			<wfw:commentRss>http://myotherpants.com/2009/06/generic-white-rubies-are-open/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thoughts on GUI Testing</title>
		<link>http://myotherpants.com/2009/06/thoughts-on-gui-testing/</link>
		<comments>http://myotherpants.com/2009/06/thoughts-on-gui-testing/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 11:03:42 +0000</pubDate>
		<dc:creator>Ball</dc:creator>
				<category><![CDATA[work safe]]></category>
		<category><![CDATA[ironruby]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[white]]></category>

		<guid isPermaLink="false">http://myotherpants.com/?p=70</guid>
		<description><![CDATA[I&#8217;m currently involved with a WPF project as a tester.  My charge is to automate the System-Level testing of this project for my client.  Our belife is that automated testing allows us to find &#8220;popup bugs&#8221; before they become a problem.  This has worked well, in combination with the team doing a degree of dog-fooding. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently involved with a WPF project as a tester.  My charge is to automate the System-Level testing of this project for my client.  Our belife is that automated testing allows us to find &#8220;popup bugs&#8221; before they become a problem.  This has worked well, in combination with the team doing a degree of dog-fooding.  They catch the esoteric things, I find the simple things no one looks for.  Also, I&#8217;m currently working with a lot of them as we build manual test scripts for our verification phase.  This is a lot more focused act that, once automated as we move forward with version two, will allow us to have a better understanding of the &#8220;shipability&#8221; of our software.  We&#8217;re regulated and we want to automate most of the acceptance testing, at least in theory.</p>
<p><span id="more-70"></span></p>
<p>I&#8217;ve been using TestComplete for this.  T.C. is good stuff, but there are some things about it I don&#8217;t like.  It&#8217;s meant for recording and playback of tests.  But, to automate in a regulated situation, I don&#8217;t want to see javascript (T.C.&#8217;s CSharp script is a horrible trap, don&#8217;t go there) like the following</p>
<pre name="code" class="javascript">var p1;
var w1;
p1 = Sys.Process('MyProcess');
w1 = p1.Window('HWind: MainWindow').MainWindow.Base.WPFObject('Grid', '', 1).ScrollView;
w1.x = 0;
w1.y = 0;
w1.WPFObject('RowItem', '', 2).StackPannel.WPFObject('Button', 'Cancel', 1).Click(3,15);</pre>
<p>What the hell is my intent here?  Also, I&#8217;m crawling the visual tree, which may be brittle.  The renaming of internal variables, like &#8220;StackPannel&#8221; to something more revealing like &#8220;VisibleFlarns,&#8221; I&#8217;d have to go edit this test.  And a buch of other tests that traverse that point in the tree.  We kind of saw this coming and have rewritten our tests to a degree.</p>
<pre name="code" class="javascript">var process = Sys.Process('MyProcess');
VisibleFlarn(process, 2).WPFObject('Button', 'Cancel', 1).Click();</pre>
<p>This is slightly more clear.  The main benefit is that we&#8217;re hiding the traversal of the tree to the visible flarns.  That means we only have one place to hunt down our changes to the tree.  But it doesn&#8217;t take full advantage of our environment, JavaScript.  Foreign objects, like the process, windows, and buttons can&#8217;t be extended with helper methods.  So, I&#8217;ve started the next round of testing with a bunch of decorators and strict reuse.</p>
<pre name="code" class="javascript">var process = new MyProcess();
process.GetVisibleFlarn(2).Cancel();</pre>
<p>That&#8217;s starting to get to good.  The last piece is that regulatory oversight loves positive passing of tests, not just error logs.  T.C. doesn&#8217;t have that.  T.C. doesn&#8217;t even really have asserts.  You can only error, or log.  In fact, I&#8217;ve yet to find a test framework that does that out of the box.   Even those that assert, don&#8217;t log positive asserts.  Why is this important?  I want to be able to say Req-123 was tested 7 times, and passed each one.  That&#8217;s what the oversight wants.  They fear, &#8220;Well, it&#8217;s didn&#8217;t show up in the error logs, so I&#8217;m assuming it worked.&#8221;  So, I wrote some asserts that take explicit requirements and &#8220;Why&#8221; I&#8217;m asking about that.</p>
<p>Now, on to prong two, of my assault.</p>
<p>I recently picked up &#8220;<a href="http://pragprog.com/titles/idgtr/scripted-gui-http://pragprog.com/titles/idgtr/scripted-gui-http://pragprog.com/titles/idgtr/scripted-gui-testing-with-ruby">Scripted GUI Testing with Ruby</a>&#8221; by Ian Dees as I visited my local book store. I like the book. It covers using Win32API to grab window handles and throw around events. Oh, it&#8217;s also got some crap about Jruby and an apple-talk bridge if you want to go that route. Basically, it covers testing on all the platforms that aren&#8217;t X11 or .NET. That doesn&#8217;t detract from the book&#8217;s handling of GUI testing strategy, but I want to fill in that gap.</p>
<p>The CLR has a pretty good testing story, for WPF at least, in the <a title="White" href="http://white.codeplex.com">White </a>testing framework from ThoughtWorks.  It uses Automation Ids to identitfy and find all of your controls.  So, the pieces I&#8217;m looking at are, &#8220;What are Automation Ids,&#8221; and &#8220;What are their best practices?&#8221;  Couple that with a running example of using IronRuby to get my hands on the application and bang it around.  The big deal is our current project doesn&#8217;t use Automation Ids (accessibiltiy isn&#8217;t a huge driving need), so I need to show some benefit and low risk.</p>
<p>What am I going to have to do, for this experiement?  I&#8217;m, currently, only interested in rSpec and don&#8217;t need cucumber.  I&#8217;ll start by using White directly, but I&#8217;m guessing I&#8217;ll be wrapping it some.  I&#8217;m also interested in alternatives to AutomationIds.  But I&#8217;ll need to wrap the standard asserts with something that positively checks asserts against requirement numbers.</p>
<p>Will the regulators go for this?  I don&#8217;t know.  When working in a regulated environment, you can be innovative with how you handle testing as long as the auditors are comfortable with your ability to be repeatable and cover what they find important.</p>
<p>Should be fun.</p>
]]></content:encoded>
			<wfw:commentRss>http://myotherpants.com/2009/06/thoughts-on-gui-testing/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
