<?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>Stories from a Software Tester</title>
	<atom:link href="http://testerstories.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://testerstories.com</link>
	<description>Twice upon a time, in another space, no distance in any direction from here ...</description>
	<lastBuildDate>Wed, 22 May 2013 13:27:40 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Starting Out With Lucid, Part 1</title>
		<link>http://testerstories.com/?p=1011</link>
		<comments>http://testerstories.com/?p=1011#comments</comments>
		<pubDate>Wed, 22 May 2013 13:27:40 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[Lucid]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=1011</guid>
		<description><![CDATA[In a previous post I introduced the basics of Lucid. This post, and a few follow-ups, will be all about putting Lucid through its paces. If you have a Ruby system all set up, you just need to install the &#8230; <a href="http://testerstories.com/?p=1011">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In a previous post I <a href="http://testerstories.com/?p=1008">introduced the basics of Lucid</a>. This post, and a few follow-ups, will be all about putting Lucid through its paces. If you have a Ruby system all set up, you just need to install the lucid gem. You can read the <a href="http://testerstories.com/?page_id=260">Setting Up Lucid</a> instructions for more details.</p>
<p><span id="more-1011"></span></p>
<p>As I noted a bit in the first post, you&#8217;ll see that Lucid borrows a lot from Cucumber. Why? Because what Cucumber does works. By way of related example, when Bioware decided to come out with the MMO <em>Star Wars: The Old Republic</em> they made much of it look and operate like the hugely popular <em>World of Warcraft</em>. There were good reasons for that, not least of which was to make the transition easier for players. I&#8217;m taking the same approach with Lucid.</p>
<h2>Getting Started with Lucid</h2>
<p>To get started, create some project directory that you can play around in. Now at the command line, in that directory, type:</p>
<pre>
$ lucid
</pre>
<p>Here I&#8217;ll use the $ as a sort of generic command prompt.</p>
<p>When you do this, Lucid will essentially tell you that it cannot find a &#8216;specs&#8217; directory. Here&#8217;s an area right at the start where Lucid differs from Cucumber. Instead of a &#8216;features&#8217; directory, there is a &#8216;specs&#8217; directory that is expected by default. This isn&#8217;t to say you can&#8217;t use a &#8216;features&#8217; directory. It&#8217;s simply to say that in Lucid&#8217;s opinionated view, what you are writing are specifications &#8212; not features. Those specifications will talk about features, yes. But they are not, themselves, features. They are specifications.</p>
<h2>A Spec Repository</h2>
<p>Lucid requires a spec repository; it defaults to looking in a directory called &#8216;specs&#8217; for this.</p>
<p>So create the necessary directory:</p>
<pre>
$ mkdir specs
</pre>
<p>If you run the &#8216;lucid&#8217; command again, you will be told that Lucid recognizes there is a specs directory but it will do so largely by telling you that it was attempting to find some scenarios and steps to execute. There are none at the current time, of course, so Lucid will simply report that and stop.</p>
<p>Incidentally, if you do want to use a features directory, simply create one. Then tell Lucid to look in that directory:</p>
<pre>
$ mkdir features
$ lucid features
</pre>
<p>Here you have specified a spec repository to look in, called &#8216;features&#8217;, and so Lucid will use that rather than the default.</p>
<h2>A Specification File</h2>
<p>To get the ball rolling a little further, let&#8217;s create a specification file. Within your specs directory, create a plain-text file called <strong>triangle.spec</strong>. Going with the change of &#8216;features&#8217; to &#8216;specs&#8217;, here the file extension is &#8216;spec&#8217;, not &#8216;feature&#8217;. Again, this is an area where Lucid differs a bit from Cucumber. These are specification files &#8212; specifically test specifications &#8212; and are named accordingly.</p>
<p>When you have this file in place, put the following header statement at the top of it:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Ability: Triangle Calculation
</pre>
<p>Now run the lucid command again. You&#8217;ll know that Lucid is finding your spec file because it repeats the header.</p>
<p>Lucid simply reads in text files. You can type the above in via Notepad, vi, TextMate, pico, EditPad Pro and so forth. You can even enter it in something like Microsoft Word as long as you save as a text file. As I mentioned in the introductory post to Lucid, I&#8217;m using the Gherkin API, just as tools like Behat, Cucumber, and SpecFlow are. Gherkin provides a structuring element for the TDL you use to write Lucid specifications. Gherkin is also a library that you can use to parse those specifications.</p>
<p>Note that the header clause &#8220;Ability&#8221; can also be &#8220;Feature&#8221;. A spec file is just a file that Gherkin will be able to parse and Gherkin allows you to use Ability as synonymous with Feature. You can also use the term &#8220;Business Need&#8221; as well.</p>
<p>So, with that, Lucid specs are grouped into features or abilities or business needs. These names are used because you want these spec files to describe the features that will be provided, the abilities that users will have, or the business needs that are being satisfied.</p>
<p>Note that if you do want to name your files with a &#8220;.feature&#8221; extension, rather than &#8220;.spec&#8221;, you can certainly do that. You just have to tell Lucid that&#8217;s what you want to use as the spec type.</p>
<pre>
$ lucid --spec-type feature
</pre>
<p>Let&#8217;s digress for a second here. If you have decided to use a features directory and you want to use a .feature file rather than a .spec file, you now have two things you have to specify on the command line:</p>
<pre>
$ lucid --spec-type feature features
</pre>
<p>Pretty soon that can get annoying. You can use a configuration file to specify these elements. You can create a file called <strong>lucid.yml</strong> in your project directory and then put the following in that file:</p>
<p></p><pre class="crayon-plain-tag">default: --spec-type feature features</pre><p></p>
<p>Were you to do that, you could then just run the lucid command without any arguments:</p>
<pre>
$ lucid
</pre>
<p>Lucid will see that there is a lucid.yml file and use that. Since you have a default configuration, or operational profile, specified that will be used by &#8230; well, by default. And, yes, lucid.yml is basically just like cucumber.yml.</p>
<p>The goal was to make Lucid work out of the box without complex configuration. Lucid doesn&#8217;t require you to provide a configuration file or pass a lot of complex command-line options to work. However, there are times when you will want to tweak how Lucid behaves so the above was just making sure that was known. This is somewhat similar, if not identical to, the idea of &#8220;convention over configuration&#8221; that is favored by frameworks like Rails.</p>
<p>Note that at this point, and for the rest of this post, I&#8217;m going to assume you&#8217;re not using a features directory or a lucid.yml file. I&#8217;m going to assume you have the following structure based on what we&#8217;ve done so far:</p>
<pre>
.
|---specs
      triangle.spec
</pre>
<p>Now let&#8217;s add some narrative or a description to this ability.</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Ability: Triangle Calculation
  
  As a math teacher
  I need a triangle calculator
  so that I can have students in my classroom learn about triangles
  
  The possible triangle types are:
  
  - Scalene:     all side lengths are different
  - Isosceles:   two side lengths are equal
  - Equilateral: all side lengths are equal
  
  Invalid side lengths will not form a valid triangle.
  
  A "right" triangle has one angle which is 90 degrees.
  This means the side lengths form a Pythagorean triple and
  thus satisfy the Pythagorean theorem.
</pre>
<p>You&#8217;ll probably recognize the first part of this &#8212; the &#8220;As a &#8230; I need &#8230; so that &#8230;&#8221; &#8212; as a standard feature injection template for indicating why something has value. The rest is just text that a hypothetical business user may have put in to make sure everything is clear.</p>
<p>All of this information is just for the consumption of the reader of this test spec. What you can see is that if you run the lucid command again, all of this information is parroted back as part of the execution of the spec. At this point, however, that&#8217;s all Lucid can do: simply parrot back the spec file it found. Nothing is actually being executed. This is because you do not yet have an <em>executable</em> spec. A spec becomes executable when it has steps within scenarios.</p>
<p>Incidentally, there are a few other ways you can execute Lucid to have it tell you what it&#8217;s doing as it is executing. Try the following commands:</p>
<pre>
$ lucid --verbose
$ lucid --debug
</pre>
<p>This in turn brings up another point, which is that Lucid has a fairly rich set of command line options that you can use to control execution. To see these, do this:</p>
<pre>
$ lucid --help
</pre>
<h2>An Executable Specification File</h2>
<p>To start making this specification executable let&#8217;s first add a scenario. Change the triangle.spec file so that it looks like this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Ability: Triangle Calculation

  ...
  
  Scenario: Scalene
</pre>
<p>Here I have added a scenario and given it a title. Run lucid again at the command line.</p>
<p>Here you can see that now that you have a scenario, Lucid found it and executed it, saying it passed. This might seem a little odd. What passed, exactly? Lucid defaults to everything passing and thus showing green if you can see color output. The reason for this is because the onus is on the person writing the test specifications to specifically indicate what failure looks like. Lucid has no way to know that.</p>
<p>You can see, by the output you receive, that passing means little since no actual steps were executed. Now let&#8217;s add a step. We know this is a triangle calculator and we&#8217;re going to need the lengths of the sides of a triangle. That&#8217;s pretty the context for any actions we take to see if we get back the appropriate triangle. Change your spec file so that it looks like this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Ability: Triangle Calculation

  ...
  
  Scenario: Scalene
    Given the length values 10, 8, 3
</pre>
<p>Note here that I&#8217;m showing a lot of indentation to make things look nicer visually. In reality, none of the indentation is needed.</p>
<p>Here I have added a specific step, using the Given-When-Then format. Run lucid again at the command line and this time you will get quite a bit more output. What the output will be telling you is that Lucid is now trying to execute your spec because it has found a step. Notice that the output says there was a step found, but that it was &#8220;undefined.&#8221; This means that Lucid has found the step but has no knowledge of what it means; Lucid doesn&#8217;t know how to execute the statement.</p>
<p>You can also see that Lucid is helping you write the matchers that you will need in order to start making those steps executable.</p>
<p>As a side note, at this point you will see a message where Lucid is saying that no test definitions were found. When Lucid mentions &#8220;test definitions&#8221; what it&#8217;s saying is: I need something that tells me how translate the plain English steps in the spec into logic that I can execute. When Lucid mentions &#8220;matchers&#8221; it means <em>that</em> is the mechanism that will be used to provide the link.</p>
<p>You can see that Lucid is providing a lot of information with your last output. Two command line options will allow you reduce the amount of information if you want. Try the following:</p>
<pre>
$ lucid --no-source
$ lucid --no-matchers
</pre>
<p>Since people often want to run both of those options simultaneously for quick output, you can also do that using the following single option:</p>
<pre>
$ lucid --quiet
</pre>
<h2>Matchers and Test Definitions</h2>
<p>We need a place to put those matchers. So now create a file in the specs directory called <strong>triangle_steps.rb</strong>.</p>
<p>Incidentally, it&#8217;s not necessary that the test definitions file in any way match the name of the spec file. So the fact that my spec file is called triangle.spec does not mean that the steps file must be called triangle_steps.rb. You can follow that convention if you wish, but Lucid certainly doesn&#8217;t enforce it. Similarly you did not have to include the word &#8220;_steps&#8221; in the name of the file.</p>
<p>Once you create that file you can simply copy and paste the matchers that Lucid provides to you. You could also retype them in yourself if you want. The reason you might do that is if you want to change the matchers around a bit. Going with the simple copy-paste route for now, your triangle_steps.rb file will look like this:</p>
<p></p><pre class="crayon-plain-tag">Given (/^the length values (\d+), (\d+), (\d+)$/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>Run lucid again at the command line.</p>
<p>The scenario now shows that the undefined step has become &#8220;pending.&#8221; That means Lucid has found how to sync up the natural language with a matcher in a test definition. The pending keyword in the test definition matcher stops the step from executing any further.</p>
<h2>Flexible Matchers</h2>
<p>So let&#8217;s close out this post talking about some variations that you can do with the step statement and the matchers.</p>
<p><strong>Variation 1</strong></p>
<p>You can do a literal match on a string.</p>
<p></p><pre class="crayon-plain-tag">Given &quot;the length values 10, 8, 3&quot; do
  pending
end</pre><p></p>
<p>This is a very literal string. What this means is that only a TDL statement with those exact numbers will be matched up.</p>
<p><strong>Variation 2</strong></p>
<p>If you are using a string, you can parameterize the string. You can use a $ sign to indicate placeholders.</p>
<p></p><pre class="crayon-plain-tag">Given &quot;the length values $side1, $side2, $side3&quot; do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p><strong>Variation 3</strong></p>
<p>You can use a literal regular expression. This is basically like variation 1, except the phrase is in a regular expression delimiter, not a string.</p>
<p></p><pre class="crayon-plain-tag">Given (/^the length values 10, 8, 3$/) do
  pending
end</pre><p></p>
<p><strong>Variation 4</strong></p>
<p>You can use capture groups as part of a regular expression.</p>
<p></p><pre class="crayon-plain-tag">Given (/^the length values (10), (8), (3)$/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>In this case, the groups are essentially useless because the value is still hard coded.</p>
<p><strong>Variation 5</strong></p>
<p>You can use capture groups that are generic.</p>
<p></p><pre class="crayon-plain-tag">Given (/^the length values (\d+), (\d+), (\d+)$/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>You&#8217;ll note that this is essentially what Lucid provided for you as a suggestion. Here I&#8217;m using a shorthand character class. That would be as opposed to using something like the &#8220;([0-9]*)&#8221; character class. Note also that I&#8217;m using the + modifier to mean &#8220;at least one.&#8221; This would be as opposed to using the * modifier to mean &#8220;zero or more&#8221;.</p>
<p><strong>Variation 6</strong></p>
<p>This isn&#8217;t so much a variation as it is showing how multiple matchers can conflict in the sense that Lucid will find it ambiguous as to which matcher it should use. To see this in action, have variation 4 and 5 in your triangle_steps.rb file at the same time. If you have both in place and run the lucid you will be that there is an ambiguous match.</p>
<p>Run the following:</p>
<pre>
$ lucid --guess
</pre>
<p>You&#8217;ll see that Lucid still did not feel safe making a determination. The reason this is happening is because Lucid is designed to not necessarily make very smart guesses since, in reality, you don&#8217;t want your tool guessing what to do. In this case, what&#8217;s happening is the following matchers are being considered:</p>
<pre>
/^the length values (10), (8), (3)$/
/^the length values (\d+), (\d+), (\d+)$/
</pre>
<p>To Lucid those are both a string that has the same literal text with three parameters. Lucid will not check that the first has literal parameters and the second has generic. To see how using &#8211;guess might work, change your triangle_steps.rb file so it has the following matchers:</p>
<p></p><pre class="crayon-plain-tag">Given (/^the length values 10, 8, 3$/) do
  pending
end

Given (/^the length values (\d+), (\d+), (\d+)$/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>If you run the lucid command (without &#8211;guess) you&#8217;ll see you get the ambiguous warning. Now run lucid again with &#8211;guess. In this case, Lucid will make a guess. Why? Well, consider what Lucid is comparing in this case:</p>
<pre>
/^the length values 10, 8, 3$/
/^the length values (\d+), (\d+), (\d+)$/
</pre>
<p>In this case Lucid guesses and choose to go with the first matcher and the reason for that is because here it has two choices: a very specific, literal phrase or a phrase that is parameterized. So Lucid will prefer specificity if and when it can determine it. The more specific and literal the phrase, the more comfortable Lucid feels. However, once capture groups get introduced, Lucid gets a little less comfortable.</p>
<p><strong>Variation 7</strong></p>
<p>Here&#8217;s a slight change to variation 5, where I&#8217;m using the ? modifier:</p>
<p></p><pre class="crayon-plain-tag">Given (/^the length values? (\d+), (\d+), (\d+)$/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>This is a simple change but it means the word &#8220;value&#8221; or &#8220;values&#8221; will be recognized.</p>
<p><strong>Variation 8</strong></p>
<p>This is pretty much the same as variation 7 but now I&#8217;m allowing for multiple phrasings with an alternate</p>
<p></p><pre class="crayon-plain-tag">Given (/^the (?:length|side) values? (\d+), (\d+), (\d+)$/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>You&#8217;ll also note that I&#8217;m using a non-capturing group element, specified by the ?: characters. This is because I don&#8217;t want to capture whether someone used the term &#8216;length&#8217; or &#8216;side&#8217;, which is what would happen since they are in parentheses.</p>
<p><strong>Variation 9</strong></p>
<p>This is building off of variation 8 in that here I&#8217;m allowing for an optional phrasing:</p>
<p></p><pre class="crayon-plain-tag">Given (/^the (?:length|side) values?(?: of )?(\d+), (\d+), (\d+)$/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>Here the ? character, by itself, indicates that what comes before is optional and thus not be included. So with this in place, Lucid would recognize if someone said &#8220;the side values <strong>of</strong> 10, 8, 3&#8243;. As with the length and side alternate capture group, I have also made sure to make this optional phrase non-capturing. Do note, however, that allowing for optional phrasing like this gets tricky because you then have to account for spaces and keep in mind that those spaces must be optional as well.</p>
<p><strong>Variation 10</strong></p>
<p>This is the same as variation 9 but I removed the end of line anchor, indicated by the $ character.</p>
<p></p><pre class="crayon-plain-tag">Given (/^the (?:length|side) values?(?: of )?(\d+), (\d+), (\d+)/) do |arg1, arg2, arg3|
  pending
end</pre><p></p>
<p>With this, I could match anything at the end of the string. Specifically, I could allow for longer phrases at the end that will simply be ignored. So someone could say &#8220;the length values of 10, 8, 3 for my triangle&#8221; and the &#8220;for my triangle&#8221; would simply be ignored.</p>
<p>In this post we got started using Lucid and you&#8217;ll have seen that while it distinguishes itself from it&#8217;s close cousin Cucumber in some ways but, in many other ways, is very similar if not identical. As I indicated above, this is largely by design. Cucumber does a lot of cool things and there is zero point in entirely reinventing the wheel. But I think there is also benefit in being able to strike out with your own solution, varying certain aspects to fit situations.</p>
<p>In the next post I&#8217;ll continue on building the triangle example started here.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=1011</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introducing Lucid</title>
		<link>http://testerstories.com/?p=1008</link>
		<comments>http://testerstories.com/?p=1008#comments</comments>
		<pubDate>Mon, 20 May 2013 14:51:23 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[Lucid]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=1008</guid>
		<description><![CDATA[I have been working on a tool called Lucid which is, in many ways, almost a direct port of the popular tool Cucumber. I do believe tools with humanizing and fluent interfaces are key to the future of testing. Here &#8230; <a href="http://testerstories.com/?p=1008">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I have been working on a tool called <a href="https://github.com/jnyman/lucid">Lucid</a> which is, in many ways, almost a direct port of the popular tool <a href="https://github.com/cucumber/cucumber">Cucumber</a>. I do believe tools with humanizing and fluent interfaces are key to the future of testing. Here I&#8217;ll explain a little of the basis behind Lucid.</p>
<p><span id="more-1008"></span></p>
<p>One obvious question might be: if there are already tools out there &#8212; like Cucumber, SpecFlow, Behat, Lettuce &#8212; why choose to come up with another one? Beyond that, why create one that is so closely aligned with an existing solution?</p>
<p>Part of the answer is that I ultimately want to provide a more configurable framework than I currently see with some of the existing solutions. I also want to incorporate more functionality into the tool than is currently directly available with other tools. But, beyond even those concerns, I also want to have a tool that matches how I think about testing. The name &#8220;lucid&#8221; refers to the approach of &#8220;lucid testing.&#8221; That, to me, simply sounds better than a (let&#8217;s admit it) ridiculous sounding name like &#8220;Cucumber.&#8221; I also want to match up concepts a bit better during tool operation. For example, Cucumber refers to &#8220;snippet&#8221; whereas I prefer &#8220;matcher&#8221;.</p>
<h2>The Lucid Ecosystem</h2>
<p>But what actually <em>is</em> Lucid?</p>
<p>Lucid can be thought of as a business requirements specification framework. In this way it&#8217;s used for capturing business requirements and providing a way to create a ubiquitous language.</p>
<p>Lucid can also be thought of as a test specification framework. In this way it is used for capturing tests in the form of a Test Description Language (TDL) that matches the ubiquitous language.</p>
<p>Lucid can be thought of as a TDL execution library. In this way it is used to provide a structure that allows for tests to be validated against an application.</p>
<p>Or Lucid can be thought of as all of these things together. Lucid is an approach. Lucid is also a tool. Lucid is also an interface. These, at least, are my immediate goals for it.</p>
<p>Let&#8217;s take the first one in that list: the idea that Lucid is a specification framework. In this context the goal for the Lucid framework is to be output-focused, condition-based, and example-driven. A lot of what that actually <em>mean</em> will come out in further posts. Suffice it to say that I believe tools like this should attempt to impart good test design practices and encode those as part of its operation.</p>
<p>Lucid is also predicated on a few core ideas:</p>
<ul>
<li>Requirements can be written as tests.</li>
<li>Testing is a design activity.</li>
</ul>
<p>In order to adhere to these ideas, as well as to satisfy the above-mentioned goal, Lucid uses a lightweight structure to do the following:</p>
<ul>
<li>Write examples of the behavior that users want.</li>
<li>Allow those examples to be readable in business domain terms.</li>
<li>Allow those examples to be drivers to development.</li>
<li>Allow those examples to be executable as tests whether manually or via automation.</li>
</ul>
<p>We all know that the idea of &#8220;testing takes too long&#8221; is really a way of saying that &#8220;fixing the problems in the application takes too long.&#8221; The idea of &#8220;testing as a design activity&#8221; is to put tests where they stand the best chance of finding an issue at the most responsible time. The most responsible time, of course, is when we are discussing what to build in the first place.</p>
<p>In this way we take the view of lean software development and lean testing. This means we take an options-based approach. It&#8217;s not all or nothing; it&#8217;s not either-or. We do the most responsible things we can do, at the earliest times we can do them, consistent with our skills and experience, consistent with the values we have as a team regarding how our work deliverables are effective/efficient, and consistent with the idea of getting the most important issues raised in the most timely manner.</p>
<p>This kind of approach will show you a lot about how creative, flexible, adaptive and innovative your team can be, while still being responsible to the needs of the business.</p>
<p>What we&#8217;re really talking about here is building up a shared understanding of quality and that&#8217;s what I believe that tools like Cucumber, SpecFlow, and Lucid can help with. But where and how do we encode that understanding? That goes back to what I said before: requirements as tests. Specifically, you write actionable requirements in the language of a test. These tests are focused on business intent and task implementation, as opposed to UI level implementation concerns.</p>
<p>I believe all of this is done by adhering to a Test Description Language (TDL).</p>
<p>As a general note, you <em>always</em> have some form of TDL. You are always describing your tests. You can&#8217;t help but do so. The question is what principles, values, and idioms guide your expression and what structuring elements you use as part of your TDL to help provide reminders of that expression. Once you consider that, you then get into more high-level concepts that also speak to how you write tests. Lucid, like other such tools, allows you to use a structured format to write those tests, currently based on the Gherkin language. Note, however, that Gherkin just provides a structuring element &#8212; based on Given/When/Then. Gherkin does not help you create a ubiquitous language and it most certainly does not provide a TDL.</p>
<p>We all know that a tool is just a tool. It&#8217;s not going to make you better at crafting tests. However, a tool <em>can</em> guide expression. When people find they keep &#8220;fighting&#8221; a tool due to it not matching their model of how they want to express, that tells you something about the tool. It doesn&#8217;t tell you that it&#8217;s a bad tool. It tells you that it may not be the best tool given the needs of how you want to express things.</p>
<p>This is important because tools like Lucid are ultimately designed to allow developers, business analysts, and testers to talk about the business domain in the language of tests.</p>
<p>Clearly this is just the start of a project for me. I have no idea exactly where it will go in the future. What I do know is that I want to promote what I believe the future of testing is. I want to do so with my own tool solutions, using the best of what has come before me, but using that to build further based on my own experiences. I&#8217;ll have more posts going forward about how to use Lucid and, in particular, some of the rationale that I think must be in place for using tools like these.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=1008</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tester as Learner</title>
		<link>http://testerstories.com/?p=983</link>
		<comments>http://testerstories.com/?p=983#comments</comments>
		<pubDate>Tue, 19 Mar 2013 10:54:48 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[Thinking]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=983</guid>
		<description><![CDATA[I&#8217;ve always been interested in the different ways that testers think and how those modes of thinking directly apply to the work testers do. What it comes down to for me is how people learn. This ultimately impacts how they &#8230; <a href="http://testerstories.com/?p=983">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve always been interested in the different ways that testers think and how those modes of thinking directly apply to the work testers do. What it comes down to for me is how people learn. This ultimately impacts how they evolve their career. And, in a somewhat loaded statement, how a tester has evolved their career tells me how useful they are going to be.</p>
<p><span id="more-983"></span></p>
<p>Take, for example, the idea of testing being the &#8220;Great Hunt.&#8221; James Whittaker had an interesting take on this:</p>
<blockquote><p>&#8220;I see this period of focusing exclusively on the hunt as a rite of passage, an important trial by fire that helps immerse a new tester in testing culture, technique, and mindset. However, if I had to do it for too long as the main focus of my day, I&#8217;d go bonkers. This monotony is the reason that many testers leave the discipline for what they see as the more creative pastures of design and development.&#8221;</p></blockquote>
<p>I would maintain that testers who still find a &#8220;thrill&#8221; in bug finding after many years of doing it are probably showing you all they are ever going to be. The thrill is not in the hunt for an effective and efficient tester. The thrill is in planning the trap. Therefore there is almost no hunt. You just spring the trap!</p>
<p>But that means you need many traps. In strategic locations. Designed to catch certain types of issues. The strategic elements are what testers move to as they go from test analyst to test engineer and, eventually, beyond. So in looking at numerous individuals over the course of time – including myself, I might add! – I&#8217;ve tried to distill some conclusions based on the learning modes that we, as human beings, tend to exhibit.</p>
<h2>The Learning Modes</h2>
<p>These modes can be broken down along a few axes.</p>
<ul>
<li>What type of information does the tester preferentially perceive: <strong>sensory</strong> or <strong>intuitive</strong>?</li>
<li>Through which modality is sensory information most effectively perceived: <strong>visual</strong> or <strong>verbal</strong>?</li>
<li>With which organization of information is the tester most comfortable: <strong>inductive</strong> or <strong>deductive</strong>?</li>
<li>How does the tester prefer to process information: <strong>actively</strong> or <strong>reflectively</strong>?</li>
<li>How does the tester progress toward understanding: <strong>sequentially</strong> or <strong>globally</strong>?</li>
</ul>
<p>The rest of this post will be me trying to make sense of what I just said regarding these modalities, for lack of a better term.</p>
<h2>The Learning Modes Applied to a Tester</h2>
<h3>Sensory/Intuitive</h3>
<p>The difference in modality here is in <strong>how information is perceived</strong>.</p>
<p>This is probably one of the most important things to look for and understand. In a nutshell:</p>
<ul>
<li>The sensory-based person (who likes details and well-defined solutions to problems, while preferring information gained from their senses) will tend to focus on their actual observations of the software they are testing.</li>
<li>The intuitor (with preference for internally generated information) might then focus instead on their internal model of the software they are testing.</li>
</ul>
<p>The two testers will probably also vary in their approach to performing their testing. Let&#8217;s consider the sensor first.</p>
<ul>
<li>The sensor will generally apply &#8220;rules and tools&#8221; &#8212; solutions that have worked in the past for specific bugs that they can apply in their current testing to determine whether a particular bug exists.</li>
<li>Their testing will take the form of a series of experiments on the application.</li>
<li>These experiments will tend to be of the form &#8220;Does this specific bug exist?&#8221;</li>
<li>A strongly sensing tester may also be more likely to begin testing the product before they create any models of the software (mentally or otherwise).</li>
<li>They are more likely to consult the specification and other reference material, and to experiment with the conformance of the documentation and the product.</li>
<li>The learning done by a strong sensor is apt to be more based on experiencing the product.</li>
</ul>
<p>Given the sensor&#8217;s preference for well-defined standard solutions, they are probably going to be more inclined to develop a standard pattern for using an approach like exploratory testing. This pattern can develop into a mental script, shifting the tester&#8217;s focus from exploratory testing to scripted testing.</p>
<ul>
<li>The intuitor is more likely to approach the problem by applying different theories of error to the software.</li>
<li>They will take a risk-based approach to their testing, thinking of ways in which the software can fail and then thinking of tests which will show whether the software actually does fail in that manner.</li>
<li>This is different from the sensor&#8217;s testing for specific bugs in that the intuitor is not focusing on bugs they have seen in the past.</li>
<li>Instead, they are using their experience and understanding of the application they are testing to think about all the different failure modes of the application.</li>
<li>They usually like it when their mental model of the software is proven to be incorrect, often viewing the act of bringing their model back in line with reality as a fun challenge to be tackled.</li>
</ul>
<p>It&#8217;s a subtle difference between the two &#8212; a difference primarily of level of thought. The sensor is taking specific examples of bugs and checking for them. The intuitor is looking for more general possibilities of failure (each of which may have multiple bugs associated with it) and then deriving tests that could trigger a particular failure mode. The intuitor is also more likely to begin testing by building a model of the software. While the sensor is perhaps doing research designed to predict the behavior of the system, the intuitor might instead be doing research to define and then refine their models, with the intention of then evaluating the model against the product.</p>
<p>My belief is that the most effective and efficient testers have found a way to harness both modalities.</p>
<p>I have observed a few generalities regarding those modes. Given that these are general statements, I have them as tendencies rather than as hard facts that you can categorize someone into.</p>
<ul>
<li>Sensory testers are observant up to a point; they certainly favor facts and observable phenomena. But that also means they are apt to prefer problems with well-defined standard solutions and dislike surprises and complications that make them deviate from these solutions. They tend to be good, but limited, experimentalists.</li>
<li>The intuitive testers can be really bored with details, but can handle abstraction. They only like the details when they feel they can fit them into an understood abstract concept. Intuitors can be careless when performing repetitive tasks, preferring instead to focus on more innovative (and thus new) things.</li>
<li>Sensory testers tend to want their thinking done for them (as via a script or a tool) whereas intuitors prefer to do the thinking with only guides provided for them.</li>
</ul>
<h3>Visual/Verbal</h3>
<p>The difference in modality here is in <strong>how information is received</strong>.</p>
<p>The major difference between testers with a strong preference for visual learning and those with a preference for verbal learning might reflect the internal mental model that the testers use.</p>
<p>Let&#8217;s first consider visual learners.</p>
<ul>
<li>Visual learners will tend to work off an internal model that is picture-based.</li>
<li>This model could be a set of UML diagrams, flowcharts, or even mental screenshots.</li>
<li>They will also tend to work off visual portrayals of the steps in the tests they are executing.</li>
<li>These portrayals may run like a movie in the visual learner&#8217;s head and that&#8217;s how they may even convey them: sequences of action.</li>
<li>Alternatively, visual learners may make diagrams and pictures for their notes as they explore</li>
</ul>
<p>As for the verbal learners&#8230;</p>
<ul>
<li>Verbal learners will instead use a textual model for their testing.</li>
<li>These models might take the form of a textual description of the system (perhaps a textual use case format) or they may take the form of a remembered conversation.</li>
<li>The model will be based around words &#8212; the tester will use words to describe the system to themselves and words to describe each step in the process.</li>
<li>In addition to their internal models, these testers may also differ in the types of specification documents they try to get from their analysts and developers.</li>
</ul>
<p>Not surprisingly, visual testers probably will be more comfortable working with visual models of the system, whether those be state charts, UML diagrams, flowcharts, or whatever other representations the people designing and building the software use to help clarify things for themselves. Verbal testers, on the other hand, are likely to be happier taking the textual specification for the system and wading through it, learning as they go.</p>
<p>In my own experience, it doesn&#8217;t really matter which aspect your team focuses on the most, as long as they can craft effective tests from the materials available to them.</p>
<h3>Inductive/Deductive</h3>
<p>The difference in modality here is in <strong>how information is organized</strong>.</p>
<p>In general, an inductive learner prefers to work from specifics and derive the generalities, while a deductive learner starts with the generalities and applies them to the specific situations they encounter. A few immediate generalities spring from this:</p>
<ul>
<li>An inductive tester will tend to adopt an approach to testing where they gather as many specifics (such as techniques, potential defects, changes made to the application, and application history) as possible and generalize them to the application.</li>
<li>A deductive tester will tend to approach testing by keeping a collection of general principles and heuristics and find ways to specifically apply these generalities.</li>
</ul>
<p>I&#8217;ve tend to run across the inductive type tester more, so here&#8217;s what I&#8217;ve observed in that regard:</p>
<ul>
<li>The inductive tester will likely take advantage of historical data &#8212; looking at the available defect reports, the technical support database, published information about the software being tested and about similar programs, and any other historical documents that they can get a hold of.</li>
<li>From these documents, the inductor will derive a set of specific guidelines that they then can use to guide their testing. For example, the application being tested may have a history of defects in one particular area.</li>
<li>An inductor would take the specific fact of the large number of defect reports and generalize it to show that there could still be a large number of defects remaining in that application area, and thus focus more attention on that area than on another area which has had no defects reported historically.</li>
<li>While an inductive learner is using heuristics for this approach, it is less apt to be a deliberate usage than the deductive learner will have.</li>
</ul>
<p>As far as the deductive, when I have met such testers, they tend to follow some of the basic principles of inductive learning but there&#8217;s also this:</p>
<ul>
<li>The deductive learner starts with a collection of general heuristics and guidelines and then consciously applies them to the application.</li>
<li>Many of the traditional techniques of software testing are deductive and so the tester learns the basic skill (such as equivalence partitioning) and then determines how to apply it in the specific situation of their testing.</li>
</ul>
<p>There will be differences in how deductive and inductive testers use bug taxonomies, lists of potential risk factors, and the distinctions between scenarios, conditions, cases, and so on. What I&#8217;ve found is that, in general, the deductive tester will tend to gain familiarity with the categories and then be able to come up with new examples within those categories. The inductive tester, on the other hand, can be expected to gain an understanding of the various elements and then be able to see new ways of categorizing them.</p>
<p>You definitely need both styles of thinking. What I&#8217;ve found is that it&#8217;s pretty hard for any tester to not fall into one of these learning modes, simply by the fact that they are human beings. What I&#8217;ve found more often than not, however, is that testers are not able to articulate the mode of thought they most fall into or rely on.</p>
<h3>Active/Reflective</h3>
<p>The difference in modality here is in <strong>how information is processed</strong>.</p>
<p>Some people need to use any information they get right away for it to stick in their memories, while others need to think about the information and figure out how it fits into their mental framework before they can use it. From what I&#8217;ve seen, active and reflective testers differ most in how they execute tests.</p>
<ul>
<li>An active tester will usually do very hands-on testing.</li>
<li>They often will perform many test cases rapidly and will view each test case as an experiment, asking, &#8220;What happens if I do this?&#8221; each time.</li>
<li>An active tester will also tend to be more visibly a part of a testing group, often bouncing ideas and results off other members of the group to solicit their feedback.</li>
</ul>
<ul>
<li>A reflective tester is apt to do far fewer tests.</li>
<li>A thought process will precede each test case where the tester is thinking through the test.</li>
<li>Reflective testers make up for their lack of speed in test execution by executing the &#8220;good&#8221; tests that are most likely to find bugs.</li>
<li>Most reflective testers will probably tend to prefer to work alone or with at most one other person, and so may seem anti-social or outside the group.</li>
</ul>
<p>The isolation and thinking should give the reflective tester the time to develop more complex tests and scenarios to apply to the application, and thus they should be encouraged to take the time they need. The active tester is more often going to be bouncing the ideas for those more complex tests and scenarios to the rest of the team.</p>
<p>As with all of these modes of learning, you need a healthy mix of both here. It&#8217;s not so much that you need each tester to be a good mix of both, but rather you need both types of testers on your team and the recognition for how such personalities tend to work.</p>
<h3>Sequential/Global</h3>
<p>The difference in modality here is in <strong>how information is understood</strong>.</p>
<p>This dimension deals with how learners &#8220;get&#8221; the information they are learning. Sequential learners learn material in a logically ordered progression, learning little bits as they go, and incrementally building on the knowledge they have already learned. Global learners, however, tend to learn in chunks. They will spend some time being lost, then suddenly everything will come together and they will understand the concept.</p>
<ul>
<li>The sequential tester will often seem to get off to a faster start.</li>
<li>They will build test plans (or approaches) as they go along, step by step.</li>
<li>Not having a piece of information will not normally prove to be a problem for a sequential tester, as they will just work with the information that they do have.</li>
<li>They also will be able to explain their tests clearly to people after they have performed them.</li>
</ul>
<p>In general, a sequential tester&#8217;s test cases will grow in complexity over time as they build a deeper understanding of the system. One issue, however, is that a sequential tester is less likely to ask for information that they should have, but don&#8217;t. They will allow assumptions to creep into the tests. Their tests may also be a bit simpler, thus lacking a certain amount of breadth and depth to the testing.</p>
<ul>
<li>A global tester will get off to a slow start.</li>
<li>They may have problems understanding the point of the application (or their area within it) and need to be shown how to use the application in order to have any idea how to test it.</li>
<li>Once they get the piece of information that brings it all together for them, however, they quickly become able to create detailed, complex tests that often draw on connections that other people on the testing team have not seen.</li>
</ul>
<p>A global tester&#8217;s test cases may be more high-level in nature. Since they see the big picture first and foremost, that&#8217;s what they tend to write. They will assume the details can be covered elsewhere (if they are even needed at all). Global testers may sometimes not be able to explain all their steps very well, at least without prodding. The tests of a global tester will tend to be more complex, focusing on end-to-end scenarios.</p>
<p>In terms of test planning and creation, sequential testers will tend to be effective at convergent thinking and analysis. Global testers will tend to be effective at divergent analysis and synthesis. Global testers have much less enjoyment (or tolerance) for working with systems that are only partially or superficially understood. This means they will tend to avoid having assumptions or false information creep into their tests, but it also means it will take them longer to create those tests in environments where knowledge is sparse or unevenly distributed.</p>
<h2>So what? What does this tell us?</h2>
<p>Well, what I hope is clear in all this is that it&#8217;s really a mix of the modes that you want when you are looking to become the most effective and efficient tester you can be. But a mix is just that: a mix. It doesn&#8217;t mean that everyone should strive for some perfect balance, if such a thing even exists.</p>
<p>For me, this kind of breakdown really helped me understand what kind of learner I am. I had some blind spots but I had some good habits as well. Likewise, often, so did my teammates. Knowing both what needed to be improved and what could probably be mentored to others was a very liberating experience for me and one that made me feel I was more in control of my career. Being more in control allowed me to focus the direction my career would take. I certainly hope that&#8217;s made me a useful tester.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=983</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Seeking Conditions in TDL</title>
		<link>http://testerstories.com/?p=968</link>
		<comments>http://testerstories.com/?p=968#comments</comments>
		<pubDate>Tue, 12 Mar 2013 11:39:18 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[TDL]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=968</guid>
		<description><![CDATA[Regarding my post on Seeking Requirements in TDL, a comment was made regarding the question of whether or not I was focusing on the conditions as part of the scenario and whether or not this tied into how I view &#8230; <a href="http://testerstories.com/?p=968">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Regarding my post on <a href="http://testerstories.com/?p=960">Seeking Requirements in TDL</a>, a comment was made regarding the question of whether or not I was focusing on the conditions as part of the scenario and whether or not this tied into how I view requirements being made manifest in a test spec. The answer to both questions is &#8220;yes&#8221; but since that response may require a bit of elaboration, this post is my attempt at that.</p>
<p><span id="more-968"></span></p>
<p>A test condition is a particular behavior with respect to certain circumstances. Consider a simple statement you might see in a programming language:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
if (age < 21)
</pre>
<p>That's a condition. It's saying that what happens, or how something behaves, is conditional upon something. There are actually two types of condition we are considering here. The <strong>data condition</strong> is age. The <strong>test condition</strong> is whether the data condition (age) is less than a value (21).</p>
<p>So now let's consider my original examples (with elements bolded):</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: <strong>No Discount</strong> For <strong>Active Customer</strong>
  GIVEN an Active customer
  WHEN  the customer makes a purchase <strong>less than $10.00</strong>
  THEN  <strong>no discount</strong> is applied
  WHEN  the customer makes a purchase of <strong>exactly $10.00</strong>
  THEN  <strong>no discount</strong> is applied

Scenario: <strong>Discount</strong> for <strong>Active Customer</strong>
  GIVEN an Active customer
  WHEN  the customer makes a purchase of <strong>$10.50</strong>
  THEN  a <strong>discount of 1%</strong> is applied
</pre>
<p>Here the bolded elements are, to me, indicating data and test conditions. Writing this out, I might have this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
if (purchase <= 10.00)
  discount = 0
else
  discount = 1
</pre>
<p>So here my data conditions are purchase and discount. The test conditions are whether purchase is less than or equal to (<=) the value of 10.00 or whether purchase is greater than the value of 10.00. The second test condition is implied with the 'else' clause above but if you want to see it called out:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
if (purchase <= 10.00)
  discount = 0
else if (purchase > 10.00)
  discount = 1
</pre>
<p>The data condition of discount will either take the value 0% or 1% based on the above test conditions. So the bolded phrases from my scenarios are meant to indicate these type of test or data conditions. And, in fact, in doing this you can probably already see a change it would be nice to make.</p>
<p>Do you see what it might be?</p>
<p>I would say it is this: the $10.50 is not necessarily clear in terms of why it is $10.50. You might assume that it fits in with the previous scenario where we had "less than $10.00" and "exactly $10.00" wherein here we now have "greater than $10.00." And in fact that would be true. But still ... it was an assumption.</p>
<p>So really, the second scenario could -- and perhaps should -- be:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply <strong>Discount</strong> for <strong>Active Customer</strong>
  GIVEN an Active customer
  WHEN  the customer makes a purchase of <strong>greater than $10.00</strong>
  THEN  a <strong>discount of 1%</strong> is applied
</pre>
<p>Does this put us into a potential testing issue? Specifically, if the value to be used is simply specified as "greater than $1000", then what value will the tester (whether manual or automated) use? Clearly it is up to the tester. That can be a good thing as different values being used in tests is a way to inject variation. If you wanted to call out specific values, then you could perhaps use a data table. I already had indicated this a bit in <a href="http://testerstories.com/?p=943">A TDL Communicates Intent and Describes Behavior</a>.</p>
<p>What I hope I got across was the idea of making sure the conditions are clear. Each scenario is a essence a high level condition that states some of the key elements of my conditions. Again, consider the above as if written out in some form of code:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
if (<strong>customer</strong> == "Active")
  if (<strong>purchase</strong> <= 10.00)
    <strong>discount</strong> = 0
  else if (purchase > 10.00)
    discount = 1
</pre>
<p>Here I've bolded the first instance of each condition term. Of those terms, the only one I'm missing from my scenario title is "purchase". If I really wanted to have my scenario state each condition, I could have done it like this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply <strong>Discount</strong> for Active <strong>Customer</strong> <strong>Purchases</strong>
</pre>
<p>However, I think the scenario title was fine even without the inclusion of the word purchases. I also think it's a good habit to avoid trying to include every possible condition term in your scenario title. After all, if your app is even slightly complex, you are probably going to have a hard time fitting everything within a single concise declarative statement.</p>
<p>Speaking of more complicated conditions, let's consider one that's only slightly more complicated. Let's say there's a general business rule that says "a 2% discount is applied when a purchase is greater than $10.00 but less than $25.00 and is a long-standing title."</p>
<p>These are cases where, given the nature of the related conditions, you may want to spell out more data. It's all about what makes it clear. Let's consider the above business rule and write it as a scenario:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discount for Mid-Range, Long-Standing Games
  GIVEN an Active customer
  AND   a $12.00 long-standing game
  WHEN  the customer purchases the game
  THEN  a discount of %2 is applied
</pre>
<p>So I called something a "mid-range, long-standing game." Just by looking at the scenario (and the steps), what does that mean? Forget the business rule you saw earlier. Just consider the scenario as written. What do I mean by "mid-range, long-standing game." You have absolutely no idea, right? Just by looking at the scenario (and the steps), why did I choose a value of $12.00? You really don't have a clue, do you?</p>
<p>This sort of circles back to making it clear what you are testing for. So how do you deal with that? Because this does get to the heart of how you know you are testing the requirement, right? Well, here's one idea:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases

  A "mid-range" game is one that costs between $10.00 and $25.00.
  A "long-standing" game is one that is over five years old and has had no sales in the past one year.
  
  Scenario: Apply Discount for Mid-Range, Long-Standing Games
    GIVEN an Active customer
    AND   a $12.00 long-standing game
    WHEN  the customer purchases the game
    THEN  a discount of %2 is applied
</pre>
<p>Or would it be better to word the context part of the scenario this way:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
GIVEN an Active customer
AND   a long-standing game that costs between $10.00 and $25.00
</pre>
<p>Well, "a game that costs between $10.00 and $25.00" is a mid-range game, as we've already stated. The fact that it happens to be a long-standing game is a different aspect. So I could just say:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
GIVEN an Active customer
AND   a mid-range, long-standing game
</pre>
<p>Here "mid-range game" is a valid data condition that refers to a domain phrase. In fact, the phrase has the data condition (purchase price) and the test condition (between $10.00 and $25.00) wrapped up in one phrase. When you add "long-standing" to it you have two more data conditions (age of game; sales) and two test conditions (greater than or equal to five years old; sales equal to zero for past year). Okay, but let's take a look at what we end up with assuming we make all these changes:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases

  A "mid-range" game is one that costs between $10.00 and $25.00.
  A "long-standing" game is one that is over five years old and has had no sales in the past one year.
  
  Scenario: Apply Discount for Mid-Range, Long-Standing Games
    GIVEN an Active customer
    AND   a mid-range, long-standing game
    WHEN  the customer purchases the game
    THEN  a discount of %2 is applied
</pre>
<p>Again, someone could say but you don't know if a tester is going to choose a game at $10.00 or at $25.00 or at some value in between. Technically that's fine since the behavior forms an equivalence class or any values in that range. Outside of that range, of course, is a different question -- and it's also a different scenario. Something less than $10.00 or greater than $25.00 is not a mid-range game and thus should not be dealt with in a scenario with mid-range game in the title.</p>
<p>Before looking at another possible issue, I'll note you could actually just state this as a single clause:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discount for Mid-Range, Long-Standing Games
  * a discount of 2% is applied when an Active customer purchases a mid-range, long-standing game
</pre>
<p>But, in either example, is my context (the AND clause in the first example or the last part of the asterisk example) duplicating too much of what I said in the scenario title? And, if so, is that bad? Well, you have a few options. One is simply do what I did above and not worry about it. The other is you could specify the data conditions and values as part of the steps, relying on the context of the scenario (along with the narrative at the top of the file) to make it clear what the data condition applies to.</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases

  A "mid-range" game is one that costs between $10.00 and $25.00.
  A "long-standing" game is one that is over five years old and has had no sales in the past one year.
  
  Scenario: Apply Discount for Mid-Range, Long-Standing Games
    GIVEN an Active customer
    AND   a game that is greater than five years old
    AND   a game that has not had sales in the past year
    AND   a game that is between $10.00 and $25.00
    WHEN  the customer purchases the game
    THEN  a discount of %2 is applied
</pre>
<p>Is that good? Well, it can be fine but it makes the context wordy. You normally solve that by using domain phrases. So here we have a situation where we did define the domain phrase, but didn't use it. Which seems like a waste.</p>
<p>Another option is you could have specific data that you know you can rely on as part of your "gold data" that is used for testing. In that case, you might call out the specific data item:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases

  A "mid-range" game is one that costs between $10.00 and $25.00.
  A "long-standing" game is one that is over five years old and has had no sales in the past one year.
  
  Scenario: Apply Discount for Mid-Range, Long-Standing Games
    GIVEN an Active customer
    WHEN  the customer purchases the game "Midsummer Evening of Walking Living Dead"
    THEN  a discount of %2 is applied
</pre>
<p>From a step reusability standpoint, I like this one:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discount for Mid-Range, Long-Standing Games
  * a discount of 2% is applied when an Active customer purchases a mid-range, long-standing game
</pre>
<p>Why? Because it states the business rule largely as a business user would. My matcher for these kinds of phrases could be something along these lines:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
(/^a discount of (/d+)% is applied when an (.*) customer purchases a (.*) game$/)
</pre>
<p>But with my scenario title and my step statement, am I repeating a little, yes? Is that bad, I don't know. I try to avoid doing so but to a certain extent when you define your conditions with domain phrases there probably is going to be a little of that. Notice what my scenario title is not. It was not this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply a 2% Discount for Mid-Range, Long-Standing Games for Active Customers
</pre>
<p><em>That</em> would be too much duplication for me. Beyond just the duplication concerns, this example includes a value (2%) in the title, which I think should be considered a no-no. Why did I not originally include the Active customer clause in the scenario title, though? That seems relevant, no? It does, but the operative conditions I'm testing for are "discount on item." The key action is "apply a discount." I don't apply a discount to a customer. I apply it to a product. This allows me to have different steps for different customers:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discount for Mid-Range, Long-Standing Games
  * a discount of 2% is applied when an Active customer purchases a mid-range, long-standing game
  * a discount of 5% is applied when a Gamer customer purchases a mid-range, long-standing game
</pre>
<p>As far as the repetition goes, can I avoid that? Since the title already says "mid-range, long-standing games" can I just do this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discount for Mid-Range, Long-Standing Games
  * a discount of 2% is applied for an Active customer purchase
  * a discount of 5% is applied for a Gamer customer purchase
</pre>
<p>I could do that but, from an automated execution standpoint, that can become problematic. I say that because from an automated test perspective, the above phrases would not fully establish the context.</p>
<p>Before considering that issue, if in fact it even is an issue, also notice how I have two different data conditions being tested for. Should those instead be different scenarios? Based on what I just said above regarding the operative condition ("discount on item"), I would answer no. But if the answer was 'yes', then I would have to call out the customer as well in each scenario title:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Scenario: Apply Discount for Mid-Range, Long-Standing Games for Active Customers
  Scenario: Apply Discount for Mid-Range, Long-Standing Games for Gamer Customers
</pre>
<p>Now let's go back to that other issue, in terms of how much detail is duplicated between the scenario title and the scenario steps. I ended up with two variations:</p>
<p><strong>Variation 1</strong></p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discount for Mid-Range, Long-Standing Games
  * a discount of 2% is applied when an Active customer purchases a mid-range, long-standing game
  * a discount of 5% is applied when a Gamer customer purchases a mid-range, long-standing game
</pre>
<p><strong>Variation 2</strong></p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discount for Mid-Range, Long-Standing Games
  * a discount of 2% is applied for an Active customer purchase
  * a discount of 5% is applied for a Gamer customer purchase
</pre>
<p>I think the level of detail in Variation 1 is what I want in the steps, assuming that I am using domain phrases and not specific values. Assuming I'm worried about the duplication of content (i.e., the "mid-rang, long-standing game" text), I could shorten the scenario title. Since I seem to be focusing on variation 1, here is what that might look like:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Apply Discounts for Active Customer
  * a discount of 2% is applied when an Active customer purchases a mid-range, long-standing game
  * a discount of 5% is applied when a Gamer customer purchases a mid-range, long-standing game
</pre>
<p>With this, though, I'm potentially broadening out what the scenario can cover. After all, now the scenario title would be applicable to any discount that can be applied to an Active customer. Also notice that now my second condition -- "5% is applied when a Gamer customer" -- no longer applies to this scenario and would have to be removed. I suppose I could just make the scenario "Apply Discounts for Customers" but, now, of course it's becoming the equivalent of an 'epic' scenario in that it would have to cover all aspects of how discounts are applied to any customer.</p>
<p>Notice how it's easy to keep bouncing around between one solution and another? When I encounter these situations it's usually telling me that I might want to consider using specific data values or specific data in my scenario steps. It's a time for me to question how I am breaking out my scenarios. It's also interesting to consider whether domain phrases ("mid-range, long-standing game") should be used solely in the scenario title and not in the scenario steps. But that gets interesting when one part of the phrase is easier to specify. Consider a whole feature example again:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases

  A "mid-range" game is one that costs between $10.00 and $25.00.
  A "long-standing" game is one that is over five years old and has had no sales in the past one year.
  
  Scenario: Apply Discount for Mid-Range, Long-Standing Games
    GIVEN an Active customer
    AND   a $12.00 long-standing game
    WHEN  the customer purchases the game
    THEN  a discount of %2 is applied
</pre>
<p>Here in my GIVEN, stating a specific data value for the domain phrase "mid-range game" is easy: I just specify a value between $10.00 and $25.00. But how do I state a specific value for the domain phrase a "long-standing game"? The only way I can do so is via recourse to the name of a specific game or by making the phrase even more unwieldy: "a game that is over five years old and has had no sales in the past one year." Further, the amount you are going to want to permute the data values will indicate how you want to call out details in your scenario title and your scenario steps.</p>
<p>What I hope this shows is that what I consider to be an effective TDL is one that uses scenario titles to convey the most relevant, or operative, elements of test conditions. That is usually how you will stick to conveying intent in your scenario title. Ideally these test conditions are stated as domain phrases where and when applicable. The scenario titles generally do not include the <em>values</em> of data conditions but they are likely to include the name of data conditions (i.e., "purchase" or "discount").</p>
<p>What you might notice, however, is that this is a hard area to provide prescriptive rules for. What is and is not "too much detail" for your scenarios will depend on your application, the complexity of the scenarios you are attempting to write up, and the skills of each individual person in determining how and when to write "just enough" information in the scenario title to convey intent about the type of condition being exercised by the scenario.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=968</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Seeking Requirements in TDL</title>
		<link>http://testerstories.com/?p=960</link>
		<comments>http://testerstories.com/?p=960#comments</comments>
		<pubDate>Mon, 11 Mar 2013 12:21:21 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[TDL]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=960</guid>
		<description><![CDATA[Regarding my previous post on this subject, a tester I work with asked me a great question regarding the readability of the TDL and the ability to discern the actual requirements from it. This post is essentially what my answer &#8230; <a href="http://testerstories.com/?p=960">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Regarding <a href="http://testerstories.com/?p=943">my previous post on this subject</a>, a tester I work with asked me a great question regarding the readability of the TDL and the ability to discern the actual requirements from it. This post is essentially what my answer was. Whether my answer is good or not is up to the individual reader.</p>
<p><span id="more-960"></span></p>
<p>The tester had looked at these examples from my previous post:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of exactly $10.00
  THEN  no discount is applied

Scenario: Discount for Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase of $10.50
  THEN  a discount of 1% is applied
</pre>
<p>Upon doing so she felt she had a &#8220;fundamental misunderstanding of, at the very least, what the scenario title is supposed to convey.&#8221; Specifically, from her viewpoint the scenario title <em>was</em> the requirement. When she said that to me, I realized something immediately. If, with the above examples, you treated the scenario titles as requirements, you have a contradiction. Here&#8217;s what you have if you just look at the scenario titles:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
Scenario: Discount for Active Customer
</pre>
<p>The tester said she would have written the scenario titles as this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No discount for active customers when purchase is less than or equal to $10.00
Scenario: Discount for active customers when purchase is greater than $10.00
</pre>
<p>Keeping in mind that the scenario title is generally a &#8220;non-executable&#8221; portion of a test spec, what this can do is lead to repetition. Consider those new titles along with the steps:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No discount for active customers when purchase is less than or equal to $10.00
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of exactly $10.00
  THEN  no discount is applied

Scenario: Discount for active customers when purchase is greater than $10.00
  GIVEN an Active customer
  WHEN  the customer makes a purchase of $10.50
  THEN  a discount of 1% is applied
</pre>
<p>The issue for me there is the duplication. I restate the conditions in two places: in the scenario title and in the steps themselves. At the very least, this allows the possibility that I might update one without updating the other. But assuming I have discipline enough to not do that, doesn&#8217;t the above make sense? Aren&#8217;t those scenario titles supposed to be requirements, after all?</p>
<p>Well, as I see it, the distinction here is that scenarios in a feature file are not statements of requirement, per se. They are conditions upon or of the requirements. The feature file had a title and the scenarios were ways of testing that feature. Looking at what I had originally, we have this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases
  Scenario: No Discount For Active Customer
  Scenario: Discount for Active Customer
</pre>
<p>All this being said, it didn&#8217;t take me too long to realize that this can seem a bit confusing, particularly if testers are coming from a world where their test case summary, for example, is meant to a statement that reflects upon, or even restates, some requirement. Further, the tester said this about my original example: &#8220;My concern is that in the situations [you provide] one must read through the steps to know the requirement.&#8221; The argument thus being that the requirement was easier to read with the longer form scenario title. And that can be a valid argument, right?</p>
<p>So let&#8217;s talk about this for a moment. The key question really is: &#8220;<em>Where</em> are the requirements in a TDL format?&#8221;</p>
<p>From my perspective, the conceptual issue here is the idea of a test <strong>spec</strong>, emphasis on that last word. A test specification is really a requirements+test specification. All of this is predicated upon the idea that testing is a design activity and that, at a certain level of approximation, requirements and tests merge into the same type of communication mechanism. (The old <a href="http://www.gmelnik.com/papers/IEEE_Software_Moebius_GMelnik_RMartin.pdf">Möebius</a> idea.)</p>
<p>But that can get tricky, right? After all, consider back in the day when lively &#8220;debates&#8221; &#8212; if such they can be called &#8212; swirled around the distinction between a &#8220;requirement&#8221; and a &#8220;requirement statement.&#8221; When BDD first started coming on the scene, lots of conversations focused on the idea of distinguishing between &#8220;business need&#8221; and &#8220;business understanding.&#8221; That was tied up with the notion of distinguishing between a &#8220;business rule&#8221; and a &#8220;requirement.&#8221; And then, of course, you got into what is &#8220;acceptance criteria&#8221; versus what is an &#8220;acceptance test.&#8221; I probably even jumped into this fray myself with <a href="http://testerstories.com/?p=496">Testing&#8217;s Brave New World</a>.</p>
<p>Whether these debates were needed at all is not not the point. Rather it&#8217;s just to show that conflating terms can lead to some cognitive friction, particularly when people have years of experience with certain terms.</p>
<p>The reason I like the phrase &#8220;test specification&#8221; (or &#8220;test spec&#8221; to make it sound more lively) is because I like to call attention to the fact that we have a &#8220;specification&#8221; (so part start hearing &#8216;requirements&#8217;) that is encoded as a &#8220;test&#8221;. In my mind, the notion of a requirement sort of changes in that the &#8220;requirements&#8221; are the combined set of the scenario titles plus the steps. Yet it&#8217;s sort of a new way of looking at it: by the conditions. Or, put another way, each scenario is one view into the overall &#8220;set of requirements.&#8221;</p>
<p>This is why the Given, When, and Then statements themselves should even be relatively short and as declarative as possible. I say that because it should not take a long time to parse them to understand the specific scenario. So let&#8217;s go back to my example:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of exactly $10.00
  THEN  no discount is applied
</pre>
<p>That tells me that there is a condition wherein there is no discount for an Active customer. So now I know that condition is a business rule, effectively. Getting into specifics, the &#8220;no discount&#8221; condition holds when a customer that is Active makes a purchase that is less than or equal to $10.00.</p>
<p>All of that what I just said is one requirement.</p>
<p>We have a statement of intent (&#8220;there is no discount for active customers&#8221;) and the specific implementation which says specifically what that means (&#8220;purchases of less than or equal to $10.00&#8243;).</p>
<p>And, in fact, in the interests of quick parsing this is one area where the combination of the Given into the When can help:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  WHEN  an Active customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  an Active customer makes a purchase of exactly $10.00
  THEN  no discount is applied
</pre>
<p>But, being even more reductionist, then that can really become:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  * no discount is applied when an Active customer makes a purchase less than $10.00
  * no discount is applied when an Active customer makes a purchase of exactly $10.00
</pre>
<p>And then I suppose that could become this:</p</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  * no discount is applied when an Active customer makes a purchase less than or equal to $10.00
</pre>
<p>Largely that (or something close to it) is probably how a business analyst is initially going to state the situation. The question is where to stop trimming down. Personally, with the asterisk examples, I still like a line for each specific data condition ("less than $10.00", "exactly $10.00").</p>
<p>Wrapped up in this, of course, is that if you are using a TDL like this, you are probably also considering automating these tests. So you do have to consider how you will be able to automate the above phrases, particularly as you reduce them down. Clearly the more you reduce them down, the more specific your statement gets. Whether that makes it easier or harder to automate really depends on your framework for establishing data context and so forth.</p>
<p>I don't want to turn this into an "how to automate phraes" post, but just so it's clear I do think about these things, let's consider two variations from above:</p>
<p><strong>Variation 1</strong></p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
</pre>
<p><strong>Variation 2</strong></p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  WHEN  an Active customer makes a purchase less than $10.00
  THEN  no discount is applied
</pre>
<p>The only difference is that in the second one I wrap the context (GIVEN) with the action (WHEN). Is that valid? A purist would perhaps say no. My heuristic is usually that if the context is simple enough that it can be stated as part of the key test action without making the phrase cumbersome, it might be worth doing this. Some people disagree with this entirely. I still go back and forth on this myself, to be honest. The point here is that I would have no trouble automating either phrase set above. What I'm most concerned about is how readable these phrases are and how quickly they can be parsed to gather meaning.</p>
<p>This notion of "requirements as tests" (which, to me, is another way of saying "specification by example") means a rethinking of a "requirement" or, at least, how requirements are situated relative to tests. A requirement is something that is (obviously) required. But more specifically, a requirement is a specific behavior that we say must be exhibited by the application. However, that requirement is made executable by the test itself. Thus the tests and the requirements stop being distinct entities, at least to some extent.</p>
<p>Whether or not this is a "new way of thinking" really depends on the relationship you previously considered between requirements and tests. Further, regardless of whether you agree with my viewpoint on this, I hope you can see that it is important to at least consider what it means to "read a test spec", particularly from the viewpoint of different audiences.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=960</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A TDL Communicates Intent and Describes Behavior</title>
		<link>http://testerstories.com/?p=943</link>
		<comments>http://testerstories.com/?p=943#comments</comments>
		<pubDate>Thu, 07 Mar 2013 17:13:22 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[TDL]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=943</guid>
		<description><![CDATA[The goal of a TDL is to put a little structure and a little rigor around effective test writing, wherein &#8220;effective test writing&#8221; means tests that communicate intent (which correspond to your scenario title) and describe behavior (the steps of &#8230; <a href="http://testerstories.com/?p=943">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>The goal of a TDL is to put a little structure and a little rigor around effective test writing, wherein &#8220;effective test writing&#8221; means tests that communicate intent (which correspond to your scenario title) and describe behavior (the steps of your scenario). Since those attributes should be what all statements of requirement strive for, this means that requirements and tests are the same artifact, at least when you get down to specifying the behavior that users find value in.</p>
<p>As you build up your sets of scenarios, you will initially encode intent and you will gradually reveal implementation. There is a conceptual shift away from &#8220;individual test cases&#8221; to a &#8220;test specification&#8221;. It&#8217;s important to get testers to think in terms of functional suites of behavior that are based on feature, and elaborated by scenario.</p>
<p><span id="more-943"></span></p>
<p>Let&#8217;s say the Valve Corporation is using its Steam game delivery service to have one of their weekend sales. The Valve stakeholders want to implement a feature that will give discounts to customers based on what type of customer they are.</p>
<p>The business analyst provides this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  If the Customer Type is Active and Total Purchase is less than or equal to $10.00
  Then do not give a discount
  Otherwise, give a 1% discount

  If Customer Type is Gamer
  Then give a discount of 1% for any order

  If Total Purchase is greater than $50.00
  Then give a discount of 5%
</pre>
<p>Is this good enough for testing? There is at least one bit of missing information in there where you could make an assumption. </p>
<p><em>You might take a moment here and think about what that is.</em></p>
<p>Let&#8217;s reword the above business rules a bit more in Given-When-Then:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of exactly $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of $10.50
  THEN  a discount of 1% is applied
</pre>
<p>Okay, wait. I have a When&#8230;Then, When&#8230;Then, When&#8230;Then. Do I have a test smell here? Should I perhaps break this up?</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of exactly $10.00
  THEN  no discount is applied

Scenario: Discount for Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase of $10.50
  THEN  a discount of 1% is applied
</pre>
<p>Does that work? Let&#8217;s continue then:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Discount for Gamer Customer
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase of any value
  THEN  a discount of 1% is applied
  
Scenario: Discount for ??
  GIVEN a ?? customer
  WHEN  the customer makes a purchase greater than $50.00
  THEN  a discount of 5% is applied
</pre>
<p>Ah. There&#8217;s our possible assumption, right? Does that last business rule apply to a customer who has Active as well as Gamer? When giving this exercise to testers, I find many tend to blissfully breeze right by the assumption and either assume that the last rule applies to Gamer or assume it applies to both Active and Gamer. Either interpretation could be correct. But if you don&#8217;t know, you don&#8217;t know. Don&#8217;t encode what you don&#8217;t know in a test. Encode <em>the fact that you don&#8217;t know</em> in a test so it&#8217;s quite clear that you have something that isn&#8217;t testable.</p>
<p>But &#8230; wait? Isn&#8217;t there something we&#8217;re missing? Some other detail that might matter?</p>
<p><em>Think about it for a bit before moving on.</em></p>
<p>One question I would have is: are the second and third rules additive? What if a Gamer (automatic 1% discount for ANY order) makes a purchase of $60.00 (giving them their 5% discount)? Do they then have a 6% discount applied? Again, many testers breeze right by that.</p>
<p>Let&#8217;s say these questions are taken back to Valve (the customer, remember) and decisions are made:</p>
<ul>
<li>Active customers will not be given a 5% discount.</li>
<li>Discounts are additive.</li>
</ul>
<p>Okay, so let&#8217;s get those business rules encoded as tests:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Discount for Gamer Customer
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase of any value
  THEN  a discount of 1% is applied
  WHEN  the customer makes a purchase greater than $50.00
  THEN  a discount of 5% is applied
</pre>
<p>Well &#8230; yeah. But it&#8217;s not really clear that the rules are being applied, right? How about this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Automatic Discount for Gamer Customers
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase of any value
  THEN  a discount of 1% is applied

Scenario: Gamer Customers Get a High Discount for Big Purchases
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase greater than $50.00
  THEN  a discount of 5% is applied
</pre>
<p>Okay &#8230; but what about that additive part? Do I have a different scenario? Would I have this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Gamer Discounts are Additive
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase greater than $50.00
  THEN  an automatic discount of 1% is applied
  AND   a purchase discount of 5% is applied
</pre>
<p>First, note that here we might have introduced some domain terms: &#8220;automatic discount&#8221; and &#8220;purchase discount&#8221;. On the other hand, do I need to call out that it&#8217;s additive? Someone might say why not just make a scenario that says a 6% discount is applied?</p>
<p>There are very good reasons for breaking them out, I believe. But I&#8217;ve seen many testers do exactly what I just said: have one scenario that doesn&#8217;t talk about &#8216;additive&#8217; anything and simply says that a 6% discount will be applied to Gamer customer orders over $50.00.</p>
<p>Fine &#8230; but if I have the &#8220;additive&#8221; scenario do I really need the &#8220;high discount for big purchases&#8221; scenario? Well, see that&#8217;s the interesting thing isn&#8217;t it? I&#8217;m technically making clear two things here: a larger discount is applied to Gamer customers for big purchases. Yet I don&#8217;t really have anything that contrasts this. I don&#8217;t have a scenario that shows that an Active customer spending over $50.00 simply gets the 1% discount. I have the scenario that says when an Active customer makes a purchase of &#8220;any value.&#8221; That certainly could imply a value over $50.00 along with any other value &#8212; but should it be called out?</p>
<p>Wait &#8230; it could imply a value of over $50.00? Why? I know that the notion of a &#8220;big purchase&#8221; means over $50.00 because I read it in the business rule. Good for me &#8212; but my scenario doesn&#8217;t really call that out, does it? If you all had was my scenario to go on, how do you know that the cutoff isn&#8217;t in fact $40.00 and I just happened to choose $50.00 to make the value larger than the cutoff? What is and what is not a &#8220;big purchase&#8221; is not defined.</p>
<p>Before getting into data value specifics, which of those approaches above is easier to read and parse? Well, first, to be fair, let&#8217;s put the full examples together, with all the customer decisions made.</p>
<p>First here&#8217;s the business rules stated in one structured form:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  If the Customer Type is Active and Total Purchase is less than or equal to $10.00,
  Then do not give a discount,
  Otherwise, give a 1% discount.

  If Customer Type is Gamer,
  Then give a discount of 1% for any order.

  If the Customer Type is Gamer and the Total Purchase is greater than $50.00,
  Then apply a 6% discount, made up of the normal 1% discount plus a special 5% discount
</pre>
<p>Here is another structured form, this time in BDD format:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases

Scenario: No Discount For Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of exactly $10.00
  THEN  no discount is applied

Scenario: Discount for Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase of $10.50
  THEN  a discount of 1% is applied

Scenario: Automatic Discount for Gamer Customers
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase of any value
  THEN  a discount of 1% is applied

Scenario: Gamer Customers Get a High Discount for Big Purchases
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase greater than $50.00
  THEN  a discount of 5% is applied

Scenario: Gamer Discounts are Additive
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase greater than $50.00
  THEN  an automatic discount of 1% is applied
  AND   a purchase discount of 5% is applied
</pre>
<p>Take a moment to look at each collection. What seems to make sense?</p>
<p>I brought up some questions above regarding what I should and should not call out. And therein lies the art of constructing tests &#8212; whether you are using a TDL or not. Arguably you are <em>always</em> using a TDL. The question is whether and to what extent your TDL is structured and what <em>consistent</em> principles guide the expression of tests.</p>
<p>My questions so far are predicated upon boundaries or making data values clear. But when you have specific data values, it should be clear why you are using a specific data value rather than any value or any value within a range.</p>
<p>For example, consider the scenario of the automatic discount for a Gamer customer. Some would argue that you should start at the smallest possible total to test this out: $0.01. Consider the scenario where I make sure that an Active customer making a purchase &#8220;less than or equal to $10.00&#8243; results in no discount? Should I be more specific? Should I test more at the boundaries? Some would suggest I should test at $9.99 (no discount applied) and at $10.01 (discount applied). Likewise, consider the scenario of the purchase discount for a Gamer customer when their purchase is &#8220;greater than $50.00&#8243;. Should I be more specific? Some would say you should show this happens just after the $50.00 point: $50.01.</p>
<p>Notice here that you are starting to consider a breakdown of the scenarios based on specific data conditions. This is what I think drives the desire to have a more structured TDL, such as the Given-When-Then format. Granted, business analysts can write up more business rules but they are essentially doing so as a specific type of narrative. Is that what you want? Well, again, consider the differences in the above formats?</p>
<p>Incidentally, some would argue that you can make the above even simpler than with a BDD format. Consider:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
| Customer Type | Purchase Total | Discount Applied |
| Active        | $9.99          | 0%               |
| Active        | $10.00         | 0%               |
| Active        | $10.01         | 1%               |
| Gamer         | $0.01          | 1%               |
| Gamer         | $10.00         | 1%               |
| Gamer         | $50.00         | 1%               |
| Gamer         | $50.01         | 6%               |
</pre>
<p>Here we&#8217;re are sort of settling around boundaries although, again, that&#8217;s not clear. We still lose some of why the values are in place, right? Is it clear that the reason for data rows 4 through 6 is that the Gamer customer gets a 1% discount for any value purchase? Is it clear from data row 7 that the 6% is made up of automatic discount (for being a Gamer customer) plus the &#8216;big purchase&#8217; discount? Could I rectify this?</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
| Customer Type | Purchase Total             | Discount Applied |
| Active        | less than or equal $10.00  | 0%               |
| Active        | greater than $10.00        | 1%               |
| Gamer         | greater than $0.01         | 1%               |
| Gamer         | less than $50.00           | 1%               |
| Gamer         | greater than $50.00        | 6%               |
</pre>
<p>This might help call out why specific number ranges are being used, but there&#8217;s still some bits missing here, right? I still see the fact that I have a 6% discount, without any knowledge that this was because a 5% purchase discount was added to the 1% automatic discount.</p>
<p>These tables are certainly more concise but we might risk losing the business rule or at least aspects of it. Even the tactic of some test writers to include the table as part of the scenario may only make sense in certain cases. For example, with the BDD scenarios I listed, consider this one:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase less than $10.00
  THEN  no discount is applied
  WHEN  the customer makes a purchase of exactly $10.00
  THEN  no discount is applied
</pre>
<p>That one could potentially become:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase of
    | less than $10.00 |
    | exactly $10.00   |
  THEN  no discount is applied
</pre>
<p>But, then again, I could also just say:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount For Active Customer
  GIVEN an Active customer
  WHEN  the customer makes a purchase of less than or equal to $10.00
  THEN  no discount is applied
</pre>
<p>And, in fact, that&#8217;s pretty close to what we said here in the original business rule:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  If the Customer Type is Active and Total Purchase is less than or equal to $10.00,
  Then do not give a discount,
</pre>
<p>So then it really comes down to saying that if we are going to make such a short shift from the business rule as written to the test scenario, then why not just write it that way to begin with? That is what you do with a TDL: you communicate intent and you describe behavior. You essentially turn a business rule into business understanding &#8212; and you do that by taking acceptance criteria and turning them into acceptance tests.</p>
<p>What about this business rule?</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  If Customer Type is Gamer,
  Then give a discount of 1% for any order.
</pre>
<p>That became:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Automatic Discount for Gamer Customers
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase of any value
  THEN  a discount of 1% is applied
</pre>
<p>Again, we may as well write it in the more structured form to begin with. A question in both cases is whether we consider &#8220;any value&#8221; effective enough for a test? Why not spell it out like in the table format? Well &#8230; why? I would actually like a scenario like this that has a bit of fuzz testing built in. After all, each tester may try a different value. And we might learn something from that. For example, what if some tester makes a purchase that is less than $0.00?</p>
<p>Wait &#8230; what&#8217;s that now? <em>Less</em> than $0.00? Why would there be an item on the Steam library that is less than $0.00. There probably wouldn&#8217;t be but an astute tester is really implicitly asking: what should happen if Purchase Total is less than $0.00?</p>
<p>Lo and behold, the business users say that this could in fact happen because a type of rebate coupon or gift card might be used that is greater than the total of the items that the customer is purchasing. So in these cases the discount applied should be 0% if the purchase total is less than $0.00. And this should apply to any customer. This seems worth calling out in a scenario.</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: No Discount Applied For No Dollar Amount Purchases
  GIVEN an Active customer and a Gamer customer
  WHEN  the customer makes a purchase of any value
  AND   applies a rebate coupon greater than the purchase price
  THEN  no discount is applied
  WHEN  the customer makes a purchase of any value
  AND   applies a gift card greater than the purchase price
  THEN  no discount is applied
</pre>
<p>Feels kind of busy, right? At least it does to me. The &#8220;No Dollar Amount Purchases&#8221; phrase in the scenario title is being used to convey any mechanism that could lead to such a condition happening. Further, this general condition means I have a multi-faceted context: an Active customer and a Gamer customer. If we add more ways for a &#8220;No Dollar Amount Purchase&#8221; or if we add more customer types this can get cumbersome. Further, we want to change this condition only for one customer and not another, now I have to break them out. Beyond that, while these are related observables conceptually, there are different tests being done here. Even further, what if we have rebate coupons or gift cards that do not cover the entire purchase price?</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Gamer Customers Get No Discount with Rebate Coupons That Lead to No Dollar Purchase
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase of any value
  AND   applies a rebate coupon greater than the purchase price
  THEN  no discount is applied

Scenario: Active Customers Get No Discount with Rebate Coupons That Lead to No Dollar Purchase
  GIVEN an Active customer
  WHEN  the customer makes a purchase of any value
  AND   applies a rebate coupon greater than the purchase price
  THEN  no discount is applied

Scenario: Gamer Customers Get No Discount with Gift Cards That Lead to No Dollar Purchase
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase of any value
  AND   applies a gift card greater than the purchase price
  THEN  no discount is applied
  
Scenario: Active Customers Get No Discount with Gift Cards That Lead to No Dollar Purchase
  GIVEN an Active customer
  WHEN  the customer makes a purchase of any value
  AND   applies a gift card greater than the purchase price
  THEN  no discount is applied
</pre>
<p>Is that any better? Well, one thing that may be nice is that at a glance our scenario titles can be read individually to see the permutations we are considering.</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Gamer Customers Get No Discount with Rebate Coupons That Lead to No Dollar Purchase
Scenario: Active Customers Get No Discount with Rebate Coupons That Lead to No Dollar Purchase
Scenario: Gamer Customers Get No Discount with Gift Cards That Lead to No Dollar Purchase
Scenario: Active Customers Get No Discount with Gift Cards That Lead to No Dollar Purchase
</pre>
<p>This is handy for business, developers, and testers to make sure that the appropriate data conditions are being considered. In fact, let&#8217;s consider all of our scenarios just by title alone:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Apply a Discount for Weekend Sale Purchases

Scenario: No Discount For Active Customer
Scenario: Discount for Active Customer
Scenario: Automatic Discount for Gamer Customers
Scenario: Gamer Customers Get a High Discount for Big Purchases
Scenario: Gamer Discounts are Additive
Scenario: Gamer Customers Get No Discount with Rebate Coupons That Lead to No Dollar Purchase
Scenario: Active Customers Get No Discount with Rebate Coupons That Lead to No Dollar Purchase
Scenario: Gamer Customers Get No Discount with Gift Cards That Lead to No Dollar Purchase
Scenario: Active Customers Get No Discount with Gift Cards That Lead to No Dollar Purchase
</pre>
<p>The scenario title tells you, at a glance, what is different about <em>this</em> scenario from every other scenario. Could I tighten this up this language even further to make it easier to tell at a glance the intent of each scenario? Probably. It&#8217;s worth an exercise, I suppose. The key point I want to show here is that short, concise intentional behavior is what should be described. If your scenario titles become massively long, you are missing the spirit of intent and are probably including implementation.</p>
<p>Remember that &#8220;big purchase&#8221; concern I talked about? Here is what I had:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Gamer Customers Get a High Discount for Big Purchases
  GIVEN a Gamer customer
  WHEN  the customer makes a purchase greater than $50.00
  THEN  a discount of 5% is applied
</pre>
<p>Some might argue that the scenario title should have been this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Gamer Customers Get a High Discount for Purchases Over $50.00
  ...
</pre>
<p>What do you think? The good thing is it makes the intent clear, right? Well, actually, no &#8212; or it does, but with incidentals. What we need to understand is that we call a &#8220;big purchase&#8221; is a concept that is a specific condition that triggers behavior. It just so happens that our specific value for this is over $50.00. And that is called out in the steps. However, I argue that it should not be called out in the scenario title because the intent (&#8220;big purchase&#8221;) is different from the specific data condition for that intent (&#8220;greater than $50.00&#8243;).</p>
<p>What this might argue for is changing the wording. We might feel that &#8220;big purchase&#8221;, in the context of this feature, is too vague. So the title becomes:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Gamer Customers Get a High Discount for Qualifying Purchases
  ...
</pre>
<p>Is that any better? That could actually lead to problems if you have different types of qualifying purchases, such as, say, New Games, Premium Content Games, Game Collections &#8212; whatever, right? But this highlights a point: you will evolve your language as you go. I started out with one descriptor (&#8220;big purchases&#8221;), I eventually evolved that to another (&#8220;qualifying purchases&#8221;) and I&#8217;m already thinking why that might not be good enough either. But I only make those changes &#8212; those spec refinements &#8212; when I have information that leads me to make a responsible choice.</p>
<p>Speaking of refinement, one thing to understand here is that these scenario titles &#8212; and the debate that goes around constructing them &#8212; could be written during a spec workshop. This could be during the discovery phase or whatever else you want to call it or it could just be whenever people get together to discuss. The actual steps that describe the behavior &#8212; and how the intent is satisfied &#8212; could be written out during a further spec workshop. This could be during an elaboration phase.</p>
<p>Regardless of when the steps are constructed to flesh out the scenario, the steps should only be speaking to the intent as described in the scenario title. If your scenario title is kept short and concise, that tends to be a lot easier to do. Those final four scenarios in my above list are getting about as large as I would want to consider because scenario titles are all about conveying the intent for a defined action and observable.</p>
<p>Again, as I said earlier, I have encoded intent with these short, concise scenario titles. I will gradually reveal implementation as those scenarios are filled out with steps that written in terms of what the user is doing or experiencing in order to get value.</p>
<p>The final important point here is that all of this is being done in the context of a specific test specification or feature file. That feature file will have a feature title at the top of it. Every scenario you write should be a way of stating one bit of intentional behavior of that feature; it is a way that the feature can be used. If your feature is too broadly stated, you&#8217;re going to have a lot of scenarios and potentially a lot of confusion. If your feature is too narrowly stated, you may end up with only one scenario! Once you have those scenario titles, then your behavioral steps &#8212; written in the language of the domain tasks of your users &#8212; must all showcase a key action and an observable to that key action.</p>
<p>What you probably noticed here is that I&#8217;m not just giving you rules; I&#8217;m giving you heuristics. Constructing an expressive TDL that is also executable does not require a rule book. It requires an engaged team thinking about not just how to communicate now, but how to make sure that the communication stays relevant and useful as various aspects of an application evolve over time.</p>
<p>That said, I&#8217;m finding &#8220;better&#8221; and &#8220;worse&#8221; things you can do when you construct your tests as part of a TDL and I&#8217;ve covered at least my opinions on some of those areas above. This is an area where my thinking is still very much in an evolutionary phase. My purpose in this post was simply to give everyone some insight into my thinking on this subject.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=943</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Communicating In a Test Description Language</title>
		<link>http://testerstories.com/?p=931</link>
		<comments>http://testerstories.com/?p=931#comments</comments>
		<pubDate>Tue, 05 Mar 2013 18:41:07 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[TDL]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=931</guid>
		<description><![CDATA[A TDL (Test Description Language) is a constructed language that we use to describe, and thus specify, our requirements as tests. Or our tests as requirements, if you prefer. This is what allows testing to be a design activity. What &#8230; <a href="http://testerstories.com/?p=931">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A TDL (Test Description Language) is a constructed language that we use to describe, and thus specify, our requirements as tests. Or our tests as requirements, if you prefer. This is what allows testing to be a design activity. What makes a style of writing a TDL is adherence to a structuring element and a set of principles and patterns that are used to guide expression.</p>
<p>Current forms of TDL swirl around various BDD concepts, such as Given-When-Then. But it&#8217;s clear that just having that focus in place does nothing for you by itself because there is a lot of thought that goes into how you want to express yourself. I&#8217;ve found many testers really struggle with this but, equally, I&#8217;ve found I struggle in being able to adequately teach at what level you work at with a TDL.</p>
<p><span id="more-931"></span></p>
<p>In an article on <a href="http://dannorth.net/introducing-bdd/">Introducing BDD</a>, Dan North states that he and Chris Matts were trying to develop a template that, &#8220;had to be loose enough that it wouldn&#8217;t feel artificial or constraining to analysts but structured enough that we could break the story into its constituent fragments and automate them.&#8221; This gave birth to the Given, When, Then syntax. One of the examples they provide is this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario 1: Account is in credit
  Given the account is in credit
  And   the card is valid
  And   the dispenser contains cash
  When  the customer requests cash
  Then  ensure the account is debited
  And   ensure cash is dispensed
  And   ensure the card is returned
</pre>
<p>While reading that I came across an article <a href="http://testinfected.blogspot.com/2008/12/why-i-dont-use-given-when-then.html">about not using Given/When/Then</a>. The author says that the GWT format could instead be this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
The dispenser when the account is in credit and the dispenser has cash should debit the account.
The dispenser when the account is in credit and the dispenser has cash should dispense the requested cash.
The dispenser when the account is in credit and the dispenser has cash should return the card.
</pre>
<p>A commenter to that post says that, in fact, it could be this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
The dispenser should dispense cash when the account has credit.
The dispenser should refuse to dispense cash when the account does not have credit.
The dispenser should return the card when all transactions are complete.
</pre>
<p>That does sound a little more like useful English and while I would agree that the two later sets read better than the original from North&#8217;s original article, I think the problem with these latter two approaches is that they have sentences that are not necessarily connected. For example, does &#8220;when all transactions are complete&#8221; mean just those transactions that were in the sentences above? In the first statement, the account having credit may be one condition but what about if the account has a hold on it?</p>
<p>I don&#8217;t think the problem here is with Given/When/Then so much as it is with the specification of the details. The key thing is a domain phrase. Let&#8217;s take just part of the original specification from North&#8217;s article. Here&#8217;s the first part:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Given the account is in credit
  And   the card is valid
  And   the dispenser contains cash
</pre>
<p>This is set up as a context. Could we call that a &#8220;viable transaction?&#8221; Meaning, a &#8220;viable transaction&#8221; is defined as one where a valid card is being used against an account with sufficient credit and where the dispenser has cash on hand. Well, let&#8217;s replace the Given with that and see how the scenario reads as a whole:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Given a viable transaction
  When  the customer requests cash
  Then  ensure the account is debited
  And   ensure cash is dispensed
  And   ensure the card is returned
</pre>
<p>Not bad, I guess. But are we hiding too much detail there? Is it better to stick with saying &#8220;in credit&#8221; to indicate specifically what is meant? Let&#8217;s leave it as it is for now and consider the outputs from the original scenario in North&#8217;s article:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Then ensure the account is debited
  And  ensure cash is dispensed
  And  ensure the card is returned
</pre>
<p>Could we call that &#8220;appropriate transaction response&#8221;? In other words an &#8220;appropriate transaction response&#8221; is defined as one where the account is debited appropriately (based on the money being taken out), cash is actually given to the user, and the card is returned to the user. So let&#8217;s replace the Then:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Given a viable transaction
  When  the customer requests cash
  Then  an appropriate transaction response occurs
</pre>
<p>Hmmm. Well &#8230; that&#8217;s kind of useless, isn&#8217;t it? It&#8217;s close to saying &#8220;Given that everything is as it should be, then everything will work as it should.&#8221; As a thinking tester, I suppose this is nice in that it suggests a lot of things I could test. But that also depends on my skill as a tester. If I gave that to a developer to implement a solution, there are no doubt many ways that the developer could implement the idea that a &#8220;viable transaction&#8221; leads to an &#8220;appropriate transaction response.&#8221; If I gave the above to a business analyst, they certainly could agree that we have the high level idea down but they could not say whether we actually understand what it means to use the system in a way that was intended.</p>
<p>As a related side note, you can take this kind of thing way too far. In the realm of <em>reductio ad absurdum</em>, I could remove so much of the detail from a scenario that it loses its ability to tell a story:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: The Entire App
  Given the app is called up in a browser
  When  the app is used
  Then  the app works perfectly, every time, for every user
</pre>
<p>Obviously this scenario is silly &#8212; and we&#8217;d never write something like that, right? But this is illustrative of what can happen when you keep moving up the abstraction chain, climb so high that your scenario fails to effectively communicate intent and describe behavior. If you use scenarios like this, you would need a extremely high level of trust in the developers (to code something useful) and the testers (to actually test it usefully). Having telepathy wouldn&#8217;t hurt either. Clearly there&#8217;s no story being told here. (Or if there is it&#8217;s like saying: &#8220;Once upon a time, a lot of stuff happened. The end.&#8221;) Again, this example may seem silly but what I was showing above with the transaction example is how you might quite easily approach that sort of situation where your scenario basically says the equivalent of &#8220;as long as nothing goes wrong, everything will work fine.&#8221;</p>
<p>In another context, consider that I could say something like this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Customers should be prevented from entering invalid credit card details.
</pre>
<p>You could argue we have a statement of intent here. What we have is in fact a business rule. Here is a statement of intent regarding the details of what we mean by the business rule:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
If a customer enters a credit card number that is not sixteen digits, when they try to submit the shopping cart, the shopping cart should be redisplayed with an error message telling the customer that they entered too few digits.
</pre>
<p>Certainly we would argue the latter is more testable in that it more specifically calls out what needs to be tested. It describes what is meant by &#8220;invalid credit card details&#8221; and describes what is meant by &#8220;prevented&#8221;.</p>
<p>Some people would say this is getting too much into implementation details. I would argue it&#8217;s not, though. Implementation details would be describing how we parse the number, or what button is used to submit the form, or the specific color and placement of the error message. Here we are fleshing out the business rule or business feature by describing the responsibilities of the system as it fulfills this feature.</p>
<p>How would the above get translated into a test specification? Here&#8217;s one possible example:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Feedback provided for invalid credit card details
  
  In order to avoid having customers unclear about invalid transactions
  the system must provide feedback about what specifically went wrong.
  
  Background:
    Given a user buying an item
    And   the user enters a credit card number (<-- needed?)

  Scenario: Credit card number too short
    When  the card number entered is less than sixteen digits
    And   all the other details are correct (<-- needed?)
    And   the form is submitted (<-- needed?)
    Then  the form should be redisplayed
    And   a message should appear indicating the correct number of digits required
</pre>
<p>Notice a few places there that I have "(<-- needed?)" in the text. Here I'm calling out whether those statements are even necessary. Are they incidentals that convey nothing useful about the purpose of the scenario? Put another way, could I change this to read:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Background:
    Given a user buying an item

  Scenario: Credit card number too short
    When  the user tries to buy an item with a card number of less than sixteen digits
    Then  a message appears telling them that sixteen digits are required
</pre>
<p>What do I lose or gain by going with either scenario? It's worth thinking about. For example, in the second case I don't specify that the cart form is redisplayed so where the error message appears is not stated. Is that important? Or an incidental? In both cases, note, however, that my intent is clear ("credit card number too short") and the way I test it is clear ("card number of less than sixteen digits").</p>
<p>You might also notice that since this feature is general enough -- being about invalid credit cards -- other scenarios can clearly be put in place that would test out other variations of invalid credit card usage. Some examples, just giving the scenario title:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Scenario: Credit card that is not accepted by the vendor
Scenario: Credit card that has a hold on it
Scenario: Credit card that has been flagged as stolen
</pre>
<p>So now, rather than taking Dan North's original example, let's take one of those variations from above. Specifically, let's look at this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
The dispenser should dispense cash when the account has credit.
The dispenser should refuse to dispense cash when the account does not have credit.
The dispenser should return the card when all transactions are complete.
</pre>
<p>Looked at a certain way, isn't that really just saying the same thing as what I just came up with when I said this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Given a viable transaction
  When  the customer requests cash
  Then  an appropriate transaction response occurs
</pre>
<p>In a way, yes, but of course the example spells it all out a bit more than my very abstract scenario. So that's where the main decision point of a TDL starts to come in: how abstract are you? How imperative versus how declarative? To start looking at this, how would the become a test spec? One example:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
Feature: Dispensing Cash
  Background:
    Given a user with a valid account

  Scenario: Account has credit
    When  the user requests cash from an account with credit
    Then  the user is given cash
    And   the card is returned

  Scenario: Account does not have credit
    When  the user requests cash from an account with no credit
    Then  the user is not given cash
    And   the card is returned.
</pre>
<p>But ... there's still potentially an issue there, right? Or no? Well, the phrase "the user is given cash" and "the user is not given cash" indicate what will happen in each scenario, but obviously a test can't test if the user was actually given cash in their hand. The "card is returned" makes sense because it's calling out that the system will return the card in those cases, as opposed to, say, this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Scenario: Account is flagged as a security risk
    When the user requests cash from an account flagged as a security risk
    Then the user is not given cash
    And  the card is not returned.
</pre>
<p>We seem to have captured business rules at a high level here. Is that enough? In the post I referenced earlier, the author says "language and fluency are important." I agree, but specification is also important. Behavior is also important. And thus I think the first example (from the Introducing BDD article) is a little more in line with what I find useful, as it turns out. Why? Because it's providing a bit more specifics about what exactly happens or at least starts on that path. Consider that Dan North's original scenario says this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Then  ensure the account is debited
  And   ensure cash is dispensed
</pre>
<p>The "ensure the account is debited" gets closer to what we actually want to make sure happens. The "ensure cash is dispensed" gets back into the business rule a bit. Someone could read those two lines above as synonymous. In reality, of course, they are not. The system could dispense cash and yet have a bug that does not debit the account. But of those statements, the "ensure the account is debited" is the behavior I am looking for or, at least, that I can test for.</p>
<p>Yet with this, sometimes when I write scenarios out that way I feel like I'm crossing that line from intent to implementation. What about making sure that statements like "ensure the account is debited" are spelled out with examples? George Dinwiddie, in <a href="http://blog.gdinwiddie.com/2012/01/23/contemplating-given-when-then/">Contemplating Given-When-Then</a> gives an example similar to this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Given an account with $500
  When  $50 is withdrawn
  Then  the account has $450 remaining
</pre>
<p>Here there's no mention of "credit" or "dispense cash". Rather, it's just an example. What this gets us closer to is focusing on the output because that's what we are checking. You might even say:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  When $50 is withdrawn from an account with a $500 balance
  Then the account balance will be $450
</pre>
<p>The context and the action get wrapped up and what you really focus on is the output or the assertion.</p>
<p>When you start with the output, the example (business test) specifies the minimum necessary to get to the value or output in question. I can see this leading to smaller tests. I can see that leading to less cost per test. Yet, this might also challenge our assumptions about "BDD scenarios" and what level they should be written at. For example, with the above you could argue that we don't need to write a series of tests that showcase different numbers because the business rule is pretty clear:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
* The remaining balance after a valid transaction is the amount of the transaction subtracted from the original balance
</pre>
<p>In fact, we could have said that as a test, right? The example just clarifies it. So it really gets into how much information should be included. When you consider how much or little information to include, I came across <a href="http://blog.davidpeterson.co.uk/2010/09/refactoring-givenwhenthen.html">refactoring given/when/then</a> and that lead me to ask: what's to stop my examples from being totally minimalist?</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
$500 balance
$50 withdrawal
$450 remains
</pre>
<p>Nothing stops me from doing that, except perhaps readability. But more importantly this all leads me to ask: could the output ever NOT be what I think it is? Is there ever a reason why taking out $50 from an account with $500 would NOT have $450 remaining? Like what? Well, what about a fee on the account for some reason. Or perhaps there's some penalty applied to certain transactions. Now everything can become a variation on the key scenario. Let's say this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  Given an account with $500
  And   a fee of 6% applied to transactions
  When  $50 is withdrawn
  Then  the account has $447 remaining
</pre>
<p>Or I could write it as:</.p></p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
  When $50 is withdrawn from an account with a $500 balance and a 6% fee
  Then the account balance will be $447
</pre>
<p>Then I came across the idea that <a href="http://blog.davidpeterson.co.uk/2011/01/bdd-concrete-examples-arent-enough.html">concrete examples like this may be too little</a>. Okay, going with that idea, we still need our big picture. What if we state the required behavior in a sentence or two before giving the examples? Each behavior is described by a specification like this:</p>
<pre style="white-space: pre-wrap; background-color: white; border: 1px solid;">
The remaining balance after a valid transaction is the amount of the transaction
subtracted from the original balance and taking into account any fees.

  Scenario:
    When $50 is withdrawn from an account with a $500 balance
    Then the account balance will be $450

  Scenario:
    When $50 is withdrawn from an account with a $500 balance and a 6% fee
    Then the account balance will be $447
</pre>
<p>In the Given/When/Then approach the business rule describing the behavior generally isn't made explicit. The reader is often expected to guess -- or at least determine -- the rule from the examples, so naturally those examples have to have more context. That's why you often end up with complicated Given's.</p>
<p>If we don't make the rule explicit then we only have the concrete examples, so they have to be made much more verbose -- and potentially implementation-specific -- so that readers can correctly interpret them.</p>
<p>I would argue that context-free examples with explicitly stated rules are better, both in terms of avoiding lock-in (very implementation specific) and in terms of readability (how long it takes the reader to understand the behavior expected). And this isn't actually all that new of an idea. For awhile it has been argued that in order to identify features in your system, you can use what has been called a "feature injection template." Something like this:</p>
<ul>
<li>In order to (meet some goal) as a (type of user) I want (a feature)</li>
<li>As a (type of user) I need (a feature) so that (I can meet some goal)</li>
</ul>
<p>The requirements of an application are determined by asking these kinds of question:</p>
<ul>
<li>What goals are the users trying to achieve when using this feature?</li>
<li>What tasks must the users perform to achieve those goals?</li>
<li>How does my application support those tasks?</li>
</ul>
<p>My struggle is that I prefer having the rules specified as executable tests. I think what's important is to keep the test scenarios free of what Dale Emery calls "incidental details" and make those scenarios as declarative as possible. To conceptualize this, I often suggest that tester describe the behavior in general terms (acceptance criteria), then provide some examples around that behavior to help ensure a common understanding (acceptance tests).</p>
<p>On these ideas consider <a href="http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html">Imperative vs Declarative Scenarios in User Stories</a> or <a href="http://www.jackkinsella.ie/2011/09/26/why-bother-with-cucumber-testing.html">Why Bother with Cucumber Testing?</a>.</p>
<p>I do think it's important to push toward the more abstract, declarative form of describing behavior. The trick is finding the right level to frame your scenarios at. What you want to aim for is a style is that is not coupled to any specific implementation of the user interface, to the extent that this makes sense. What I have observed is this:</p>
<ul>
<li>The more imperative you get, the more you get into how to do something rather than talking about what you are doing.</li>
<li>The more imperative you get, the more you are failing to create a domain language. Instead you will end up speaking in the language of the user interface elements.</li>
<li>The more imperative you get, the closer you get to creating fragile scenarios.</li>
<li>The more imperative you get, the easier it is to fall into using incidental details.</li>
</ul>
<p>Yet, all this said, I'm finding it is difficult to get people to find the right balance. What's the appropriate amount of information that conveys intent, describes behavior, and reveals task (as opposed to app) implementation? The answer is that it seems to vary based on what you are doing and the people you have available to work on it with you. My thoughts are in flux on this and I will be posting more on the concept of a TDL as I figure out better ways to express myself.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=931</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Building Simple Web Apps with Ruby, Part 6</title>
		<link>http://testerstories.com/?p=914</link>
		<comments>http://testerstories.com/?p=914#comments</comments>
		<pubDate>Sat, 05 Jan 2013 11:28:53 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[Sinatra]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=914</guid>
		<description><![CDATA[In this post I&#8217;ll continue what I started in the previous post: using Sass. We&#8217;ll explore a different option around how to use this engine. Also, while I&#8217;ve focused on changing the CSS and HTML elements of our application, I&#8217;ve &#8230; <a href="http://testerstories.com/?p=914">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In this post I&#8217;ll continue what I started in the previous post: using Sass. We&#8217;ll explore a different option around how to use this engine. Also, while I&#8217;ve focused on changing the CSS and HTML elements of our application, I&#8217;ve done very little with the JavaScript portion. So here we&#8217;ll explore that a little bit as well.</p>
<p><span id="more-914"></span></p>
<p>In the last post you converted to using Sass (specifically the SCSS portion of it). As I mentioned in that post, SCSS was simply introduced as a syntax for Sass to use, similar to CSS but with some additions. This time, let&#8217;s use Sass more directly, as a compilation aspect.</p>
<p>We&#8217;re going to change a lot here so you might want to make a branch in Git in case you easily want to go back to what you were doing before.</p>
<h2>Using Sass, Not Just SCSS</h2>
<p>I&#8217;m going to be using the Sass gem&#8217;s Sass::Plugin::Rack functionality. Sass was given native support for all Rack-based frameworks and this plugin is what you use to take advantage of that. For every request, the plugin looks for Sass files in the  public/stylesheets/sass directory and compiles them to CSS files in the public/stylesheets directory, if necessary. If the file has already been compiled, then nothing happens.</p>
<p>To get this working, change your config.ru file to look like this:</p>
<p></p><pre class="crayon-plain-tag">require './app'

require 'sass/plugin/rack'

Sass::Plugin.options[:style] = :expanded
use Sass::Plugin::Rack

run Project::TestApp</pre><p></p>
<p>With this in place, you can (and must) put your stylesheets into the public/stylesheets/sass/ directory, and they will be automatically compiled to CSS when a call is made to serve up CSS. So first make a directory called <strong>public/stylesheets/sass</strong>.</p>
<p>If you still have the public/css directory hanging around (perhaps with a style.css file in it), delete that directory. Now use Git to move your scss file (from the views directory) to the sass directory you just created, giving it the extension .sass in the process:</p>
<pre>git mv views/style.scss public/stylesheets/sass/style.sass</pre>
<p>Incidentally, I will note that you can configure a different path for where Sass will look for the stylesheets. Specifically, you could include this in config.ru:</p>
<p></p><pre class="crayon-plain-tag">Sass::Plugin.options[:css_location] = &quot;./css&quot;</pre><p></p>
<p>While that would have allowed me to be consistent with my previous location in the public folder, I opted to not go this route for a reason I&#8217;ll discuss a bit later. That said, the reason I did this is not a technical one so feel free to choose your own path.</p>
<p>Now we come to an implementation detail: the structure of Sass is different than SCSS. So open your style.sass file. Put the following in it:</p>
<p></p><pre class="crayon-plain-tag">$success: #02d330

header
  background: #cccccc
  border: 1px solid
  text-align: center
  letter-spacing: 0.3em
  h1
    font: 42px normal Georgia, &quot;Times New Roman&quot;, Times, serif

.notice
  color: $success
  text-align: center
  border: 1px solid

.error
  color: red</pre><p></p>
<p>Assuming you followed the last post in this series, you might want to compare this sass version with your previous scss version. What you will probably notice is that you are just further tightening up how rules are expressed.</p>
<p>Here things can get confusing if you don&#8217;t know what&#8217;s going to happen next. Given this default structure, when style.sass is compiled, it will be compiled to style.css and that generated file will be put in your public/stylesheets directory. What this means is that you should change your layout.slim file so that the call to the css file in the head section looks like this:</p>
<p></p><pre class="crayon-plain-tag">...
  link href=&quot;/stylesheets/style.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot;
...</pre><p></p>
<p>This will now serve up your css file correctly. Any css files will be generated so you will want to add this to your .gitignore file:</p>
<pre>public/stylesheets/*.css</pre>
<p>The reason for that is to prevent checking generated CSS files into git during development.</p>
<p>Test it out. Is it working? If so, you can also get rid of this now-superfluous route in app.rb:</p>
<p></p><pre class="crayon-plain-tag">get '/css/style.css' do
  scss :style
end</pre><p></p>
<p>As you get rid of that, keep in mind that what that route was doing was very simple: it was telling Sinatra that if a style.css file was referenced, instead of simply sending it to the browser, that file should be processed by the Scss engine (which is really the Sass engine using SCSS as a syntax).</p>
<p>Okay, so now why did I go this stylesheets directory path and why not just keep that route above in place? It seems easier, right? The reason is that what I&#8217;m doing here takes you a step closer to how Rails does things with its asset pipeline, including the directories that are used and the way that elements, like stylesheets, are generated from a compilation mechanism. I won&#8217;t go into details here but suffice it to say that our Sinatra application &#8212; at least for the web-specific components &#8212; is starting to look at least a little more like how a Rails app would.</p>
<p>At this point: try to deploy to Heroku. Everything I&#8217;ve done here with you <em>should</em> work just fine. I say that cautiously because hosting Sass (or any dynamically generated asset) on Heroku used to be a challenge, as most of the libraries that generate browser-ready versions of these assets expect to have write access to the filesystem. I have tested this out with my own application and everything works fine but there was a time when the public folder on Heroku was only readable and thus you could not compile resources into it.<br />
<h2>Coffee With Your JavaScript?</h2>
<p>Now let&#8217;s look at a way to replace our JavaScript. A lot of people are talking about <a href="http://coffeescript.org/">CoffeeScript</a>. I&#8217;m not one of the them and I&#8217;m not even sure I like CoffeeScript all that much. I don&#8217;t mind Slim and Sass because they are basically slight variations on the existing technologies of HTML and CSS and thus, to me, don&#8217;t hide too much. CoffeeScript covers up a lot of what JavaScript is actually doing. That may be great if you know JavaScript really well. If you don&#8217;t, that can be a problem.</p>
<p>That said, jQuery is a way to abstract complex JavaScript functionality and I&#8217;ve never had a problem with that. So I don&#8217;t know. What I can say is you are getting into a slightly different world if you go the CoffeeScript route. Nevertheless, I think it&#8217;s good to know about it and good to try it out and make sure you understand how to use it with Sinatra in case you do want to use it as your main scripting language.</p>
<p>As with HTML to Slim and CSS to SCSS, there are coverters out there to help you along, such as <a href="http://js2coffee.org/">js2coffee</a>. The usual caveats apply with converters &#8212; but even moreso with something like this because you are converting a scripting and/or programming language, which tends to be fraught with peril.</p>
<p>With what we&#8217;re going to do here, you can put either CoffeeScript (.coffee) or regular Javascript (.js) files in a public/javascripts/ directory and those scripts will be available in your application. So change your public/js directory to <strong>public/javascripts</strong>. Again, this is also to start matching up what Rails does with its asset pipeline. Now change your application.js file to <strong>application.coffee</strong>.</p>
<pre>git mv public/javascripts/application.js public/javascripts/application.coffee</pre>
<p>Here is the startdate calculator in CoffeeScript:</p>
<p></p><pre class="crayon-plain-tag">@convertToCalendar = (form) -&gt;
  origin = new Date(&quot;July 5, 2318 12:00:00&quot;)
  stardate = eval(document.forms.computeStardate.stardateValue.value)
  stardatesPerYear = stardate * 34367056.4
  milliseconds = origin.getTime() + stardatesPerYear
  result = new Date()
  
  result.setTime milliseconds
  form.calendarValue.value = result
  true</pre><p></p>
<p>A few things to note. If you do a conversion from the original JavaScript, you might find that the &#8220;eval&#8221; function is rendered as &#8220;eval_&#8221;. I have no idea why but just change it back to &#8220;eval&#8221;. It certainly won&#8217;t work otherwise. Also note the @ in front of convertToCalendar function. A lot of converters won&#8217;t put that in place for you. What that does is make the function available as part of the global scope so that it can be called from the event methods in your markup page. If you don&#8217;t do that, your JavaScript will never be called.</p>
<p>So that&#8217;s the basic details in place. Now in order to actually get this to work, we&#8217;re going to need the rack-coffee gem. Add that to your Gemfile:</p>
<p></p><pre class="crayon-plain-tag">source :rubygems

ruby '1.9.3'

gem 'sinatra', '1.3.3'
gem 'sinatra-reloader'
gem 'sinatra-flash'
gem 'thin'
gem 'slim'
gem 'sass'
gem 'rack-coffee'</pre><p></p>
<p>And, as before, make sure to update your Gemfile.lock:</p>
<pre>bundle update</pre>
<p>In app.rb, make sure you add a require for your new gem:</p>
<p></p><pre class="crayon-plain-tag">require 'sinatra'
require 'sinatra/reloader'
require 'sinatra/flash'
require 'slim'
require 'sass'
require 'rack/coffee'
...</pre><p></p>
<p>In your config.ru file, add just one line:</p>
<p></p><pre class="crayon-plain-tag">require './app'

require 'sass/plugin/rack'

Sass::Plugin.options[:style] = :expanded
use Sass::Plugin::Rack

use Rack::Coffee, root: 'public', urls: '/javascripts'

run Symbiont::TestApp</pre><p></p>
<p>As with the stylesheet reference change in layout.slim, we have to change the javascript reference as well since we are now using &#8220;javascripts&#8221; rather than &#8220;js&#8221;. So make this change in layout.slim:</p>
<p></p><pre class="crayon-plain-tag">...
script src=&quot;/javascripts/application.js&quot;
...</pre><p></p>
<p>With that, go to <a href="http://localhost:9292/stardate">http://localhost:9292/stardate</a> and you should see that the stardate calculator works just as it did before.</p>
<p>You should most definitely redeploy to Heroku at this point and make sure the JavaScript is working.</p>
<p>Incidentally, all of this may seem more confusing than it would otherwise be because I essentially started you down one path: HTML/ERB, CSS, and JavaScript. Along the way we want to Slim, SCSS then Sass, and finally CoffeeScript. That meant we had to periodically add gems, get our execution environment in sync, change files and directories and so on. Obviously had I made decisions about technologies I wanted to use at the start, there would have been less churn.</p>
<p>And that&#8217;s at least part of what I hope I did here: give you a glimpse into the possibilities that are available to you and a way to structure them.</p>
<p>This may be a good place to end this series. You have a way to use a simplified web development solution (Sinatra) and you know how to deploy it to the cloud (Heroku). You know how to use the common elements of web development (HTML, CSS, JavaScript) with this solution. You saw how to make pages dynamic by sending parameters to them or having embedded logic within them. You saw how to use alternative technologies for all of the common elements (Slim, Sass/SCSS, CoffeeScript).</p>
<p>For me, my next steps will be to take what I&#8217;ve learned here and deploy to a different platform, most likely <a href="https://openshift.redhat.com">OpenShift</a>. I also want to get into a database-backed web application. This can prove a little challenging because how you use a database on your local environment can differ quite a bit when you attempt to deploy to a remote solution like Heroku. Anyway, this series may pick up again in a bit after I have a solution worked out.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=914</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Building Simple Web Apps with Ruby, Part 5</title>
		<link>http://testerstories.com/?p=909</link>
		<comments>http://testerstories.com/?p=909#comments</comments>
		<pubDate>Fri, 04 Jan 2013 10:44:35 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[Sinatra]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=909</guid>
		<description><![CDATA[In this post I want to switch around some of what we already did regarding HTML and CSS, by using &#8220;variants&#8221; of these. Specifically, I&#8217;ll look at Slim (to replace our HTML/ERB) and Sass (to replace our CSS). The easiest &#8230; <a href="http://testerstories.com/?p=909">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In this post I want to switch around some of what we already did regarding HTML and CSS, by using &#8220;variants&#8221; of these. Specifically, I&#8217;ll look at Slim (to replace our HTML/ERB) and Sass (to replace our CSS).</p>
<p><span id="more-909"></span></p>
<p>The easiest change to make is to that of our HTML. So let&#8217;s say we no longer want to use ERB. We want to use Slim. <a href="http://slim-lang.com/">Slim</a> is a template engine just like ERB is. The idea behind Slim is that you can trim down the amount of writing you do with HTML or ERB. There is, in fact, another templating engine out there called <a href="http://haml.info/">HAML</a> that some people recommend over Slim. Really, the choice is up to you. In fact, there are more than just these two variants. What I&#8217;ll show you how to do here is experiment with at least one of them. Then you can use these same techniques to incorporate other engines.</p>
<p>I also want to consider using <a href="http://sass-lang.com/">Sass</a> (Syntactically Awesome Stylesheets). This is a CSS templating engine, which means that you write your styles in Sass which then get compiled on the server side into the CSS that is sent to the browser.</p>
<h2>Getting Slim and Sassy</h2>
<p>Okay, so how do we convert our ERB approach to a Slim approach and our CSS approach to Sass?</p>
<p>Since Slim and Sass are both gems, you need to require this at the top of your app.rb script:</p>
<p></p><pre class="crayon-plain-tag">require 'sinatra'
require 'sinatra/reloader'
require 'sinatra/flash'
require 'slim'
require 'sass'
...</pre><p></p>
<p>Because we are adding gems, you do have to go through the modify-Gemfile-bundle-update procedure. So let&#8217;s update Gemfile:</p>
<p></p><pre class="crayon-plain-tag">source :rubygems

ruby '1.9.3'

gem 'sinatra', '1.3.3'
gem 'sinatra-reloader'
gem 'sinatra-flash'
gem 'thin'
gem 'slim'
gem 'sass'</pre><p></p>
<p>Make sure to do this:</p>
<pre>bundle update</pre>
<h2>Slimming Your Markup</h2>
<p>We&#8217;ll start off with Slim because that&#8217;s a bit easier. The easiest way to convert to a Slim approach is to change all your routes such that instead of this line:</p>
<p></p><pre class="crayon-plain-tag">erb :index</pre><p></p>
<p>you have this instead</p>
<p></p><pre class="crayon-plain-tag">slim :index</pre><p></p>
<p>What that&#8217;s going to do is tell Sinatra that you want to use Slim to template your files. Because of this, you need to change the extension of your files in the views directory from &#8220;*.erb&#8221; to &#8220;*.slim&#8221;. Remember that since you&#8217;re using Git, you&#8217;ll want to do this:</p>
<pre>git mv views/*.erb views/*.slim</pre>
<p>That will make sure Git knows an existing file has been changed rather than a new file being added.</p>
<p>Make sure you do the above two actions: (1) change all erb lines in your app.rb file to slim and then (2) make sure all of your erb files in the views directory now have the extension &#8220;.slim&#8221;.</p>
<p>With just that done, if you try to visit any of your pages, you will get an error that talks about &#8220;malformed indentation&#8221;. This is an important thing to understand: Slim (like HAML) is indentation based. This is similar to how Python works. Some people utterly hate this and others just dislike it severely. Personally I&#8217;ve always been okay with indentation approaches since it helps enforce a nested structure.</p>
<p>So to fix the error you now have to convert your HTML/ERB format to Slim. As you might imagine, just changing a file extension is not enough. The good news is that there are apps out there to help you do this, such as <a href="http://html2slim.herokuapp.com/">Html2Slim</a>. That being said: be careful of converters. As you can imagine, they don&#8217;t always quite get everything right.</p>
<p>This isn&#8217;t really the place to go into a tutorial of Slim, so I&#8217;ll settle for showing you what each of my files look like after conversion:</p>
<p><strong>layout.slim</strong></p>
<p></p><pre class="crayon-plain-tag">| &lt;!doctype html&gt;
html dir=&quot;ltr&quot; lang=&quot;en&quot;
  head
    meta charset=&quot;utf-8&quot;
      title= @title + ' | Test Application'
      link href=&quot;/css/style.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot;
        script src=&quot;/js/application.js&quot;
  body
    header
      hgroup
        h1 Testing App
        h2 Minimal Testing Application
    #main
      - if flash[:notice]
        p.notice= flash[:notice]
      - if flash[:error]
        p.error
          = flash[:error]
      == yield
    footer
      p
        small An Automated Testing Tool Site</pre><p></p>
<p><strong>Note:</strong> It&#8217;s quite possible that some converters will change your yield line &#8220;= yield&#8221; rather than &#8220;== yield&#8221;. If that&#8217;s the case, make the change as you see it above or your layout will not work.</p>
<p><strong>index.slim</strong></p>
<p></p><pre class="crayon-plain-tag">p Index Page - From Views
p
  | Time is: #{Time.now}</pre><p></p>
<p>Check it at: <a href="http://localhost:9292/">http://localhost:9292/</a>.</p>
<p><strong>adhoc.slim</strong></p>
<p></p><pre class="crayon-plain-tag">form action=&quot;/adhoc&quot; method=&quot;post&quot;
  input name=&quot;message&quot; type=&quot;text&quot;
    input type=&quot;submit&quot;</pre><p></p>
<p>Check it at: <a href="http://localhost:9292/adhoc">http://localhost:9292/adhoc</a>.</p>
<p><strong>stardate.slim</strong></p>
<p></p><pre class="crayon-plain-tag">form name=&quot;computeStardate&quot;
  h3 Stardate Calculator
  p Enter five digit (new era) stardate:
  input name=&quot;stardateValue&quot; onBlur=&quot;convertToCalendar(this.form)&quot; size=&quot;15&quot; type=&quot;text&quot; value=&quot;42353.7&quot;
  input onClick=&quot;convertToCalendar(this.form)&quot; type=&quot;button&quot; value=&quot;Convert&quot;
  br/
  input name=&quot;calendarValue&quot; size=&quot;60&quot; type=&quot;text&quot;</pre><p></p>
<p>Check it at: <a href="http://localhost:9292/stardate">http://localhost:9292/stardate</a>.</p>
<p>Congratulations &#8212; you&#8217;ve just slimmed down your HTML. Again, I&#8217;m not really going to go into a tutorial of Slim at this point. There are plenty of resources out there that can do a better job than I can. Just note that the indentation does matter. Further, you can see that some of the boilerplate type markup has been removed. Beyond the basics, I just wanted you to see how to use an alternative templating engine for HTML beyond ERB. The same steps you followed here would largely apply to any templating engine you decide to use, like HAML, for example.</p>
<p>There is one other thing I&#8217;d like to show you. Each templating engine has its own way of displaying the markup. If you view the page source for any of the pages you just &#8220;slimmed&#8221; you will see it is very hard to read. That may not matter to you and it certainly does not impact how the markup is displayed. But if you want the source to look a little nicer, you can add the following to your app.rb script:</p>
<p></p><pre class="crayon-plain-tag">...
  configure do
    set :sessions, true
    set :slim, pretty: true
  end
...</pre><p></p>
<p>This is a slim-specific configuration that lets you have the page markup formatted a litter nicer in terms of readability. I bring this up because each templating engine will have its own configurations and the above place in your app.rb script is where you would set those configurations.</p>
<h2>Sassing Your Styles</h2>
<p>Now let&#8217;s talk about Sass. This can get confusing because you will hear about SCSS (Sassy CSS) and Sass (Syntatically Awesome StyleSheets). There&#8217;s lots of sites out there that explain the difference but basically Sass eventually introduced SCSS as the syntax of Sass. Think of Sass as an engine that can compile SCSS and have that become the CSS that browsers will recognize.</p>
<p>If you want a little history, Sass was originally designed to handle some of the issues people felt existed with CSS, such as, for example, the lack of ability to specify variables that could be used in more than one CSS rule. So Sass was basically an attempt to make a better CSS. The idea was that Sass was a type of compiler &#8212; or more accurately a preprocessor &#8212; that would translate this new syntax into CSS syntax. Why go to all this trouble just to end up with the same thing? Because the CSS you write with Sass could use some new features that would make everything less complicated to write in the first place and maintain later.</p>
<p>While a lot of people liked the idea behind Sass, it was felt that the design was too complicated for web designers who were used to the relatively more simple, straight-forward CSS syntax. So eventually SCSS (Sassy CSS) was introduced as part of Sass. SCSS is a superset of CSS, which means any valid CSS will work as valid SCSS. (Similar to how valid HTML worked just fine as valid ERB.) However, SCSS is a scripting language and thus it does have expressions, functions, the ability to use conditional logic, and so on. You don&#8217;t have to use those things, but you can.</p>
<p>First, add the following handler to app.rb:</p>
<p></p><pre class="crayon-plain-tag">get '/css/style.css' do
  scss :style
end</pre><p></p>
<p>This basically picks up the reference to css/style.css that you already have in your layout file and loads the Sass file called style.scss. Make sure that&#8217;s clear: the get request is for &#8220;css/style.css&#8221; because that&#8217;s what is referenced in the head section of your layout.slim file. You will never reference a &#8220;style.scss&#8221; because a browser (currently anyway) won&#8217;t know what to do with a .scss file. So what Sinatra does here is follow the route but then overrides what happens.</p>
<p>This is great but we don&#8217;t have a style.scss file yet. Now, a problem rears its head here and it&#8217;s not necesarily an obvious one: going the path I am showing you here, this scss file needs to be saved in the views directory. So let&#8217;s do this: copy your style.css to your views directory and name it style.scss:</p>
<pre>cp public\css\style.css views\style.scss</pre>
<p>So now the contents of style.css (in the public folder) matches the contents of the style.scss (in the views folder). But which one is being used? Well, let&#8217;s make this change in the style.scss file (in the views directory):</p>
<p></p><pre class="crayon-plain-tag">.notice {
  color: green;
  border: 1px solid;
  text-align: center;
}</pre><p></p>
<p>If you go to <a href="http://localhost:9292/adhoc">http://localhost:9292/adhoc</a> and submit the form, the border and text alignment should show up for the flash message. That means the scss file is being correctly read since that change is not in your css file. In fact, you could actually delete the style.css at this point if you wanted to.</p>
<p>If you take a look at how the app now looks in the browser, nothing should have changed. This is because SCSS is a superset of CSS, so any regular CSS will just work as expected. So all we have just done is moved from using standard CSS to SCSS. But what if you wanted to use some of the SCSS specific stuff? Well, here&#8217;s my original style.css:</p>
<p></p><pre class="crayon-plain-tag">header {
  background: #cccccc;
  border: 1px solid;
  text-align: center;
  letter-spacing: 0.3em;
}

header h1 {
  font: 42px normal Georgia, &quot;Times New Roman&quot;, Times, serif;
}

.notice {
  color: green;
  text-align: center;
  border: 1px solid;
}

.error {
  color: red;
}</pre><p></p>
<p>Let&#8217;s convert that to SCSS. As with going from HTML to Slim, there are converters out there that attempt to help you, such as <a href="http://css2sass.heroku.com/">css2sass</a>. And, as with the previous caveat, note that converters can sometimes lead you down a bad path. Notice with this tool that there are two buttons: convert to SASS and convert to SCSS. For now, I&#8217;m using just SCSS. So here is my css converted to scss:</p>
<p></p><pre class="crayon-plain-tag">header {
  background: #cccccc;
  border: 1px solid;
  text-align: center;
  letter-spacing: 0.3em;
  h1 {
    font: 42px normal Georgia, &quot;Times New Roman&quot;, Times, serif;
  }
}

.notice {
  color: green;
  text-align: center;
  border: 1px solid;
}

.error {
  color: red;
}</pre><p></p>
<p>Not a whole lot of difference, right? One thing you might notice there is ability to nest your declarations. See how the &#8220;header h1&#8243; became an &#8220;h1&#8243; nested underneath &#8220;header&#8221;. At first I didn&#8217;t care about this feature at all, but I&#8217;ve come to really appreciate it. I also mentioned that SCSS is a scripting language. One of the things you can do with it is create a variable. At the top of the style.scss file, add this:</p>
<p></p><pre class="crayon-plain-tag">$success: #02d330;</pre><p></p>
<p>Now change the notice rule declaration to this:</p>
<p></p><pre class="crayon-plain-tag">.notice {
  color: $success;
  text-align: center;
  border: 1px solid;
}</pre><p></p>
<p>I&#8217;m just scratching the surface here so that you can see there are, in fact, differences.</p>
<p>If you check your file system now, you will see that there is a .sass-cache directory in your root project directory. The reason this exists is that Sass is a compilation system. Since Sass does compiling, very large files or very complex files could add time to rendering the page with the styles. So the cache is a way to store compiled elements for re-use so that performance is quicker.</p>
<p>All that said, you definitely don&#8217;t want to track this as part of Git, so add a <strong>.gitignore</strong> file to your root project directory and put the following in it:</p>
<pre>.sass-cache</pre>
<p>One thing you should do at this point is redploy to Heroku and make sure everything still works. Remember that you can use foreman to try out the execution environment before you do so. The reason I say this is a good thing to try is because you&#8217;ve done a lot here. You&#8217;ve used two new gems (Slim and Sass) as part of your operating context and you&#8217;ve changed how your markup is generated as well as how your stylesheets are generated.</p>
<p>In the next post I&#8217;ll explore a little more about using Sass directly (rather than just SCSS) and I&#8217;ll also look at the possibility of using another alternative, this time to JavaScript.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=909</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Building Simple Web Apps with Ruby, Part 4</title>
		<link>http://testerstories.com/?p=898</link>
		<comments>http://testerstories.com/?p=898#comments</comments>
		<pubDate>Thu, 03 Jan 2013 10:05:04 +0000</pubDate>
		<dc:creator>Jeff Nyman</dc:creator>
				<category><![CDATA[Sinatra]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://testerstories.com/?p=898</guid>
		<description><![CDATA[Following on from the other posts in this series, here I want to focus more on the static and dynamic content aspects. This will actually be fairly tame stuff for the most part but it&#8217;s a way to make sure &#8230; <a href="http://testerstories.com/?p=898">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Following on from the other posts in this series, here I want to focus more on the static and dynamic content aspects. This will actually be fairly tame stuff for the most part but it&#8217;s a way to make sure we can do some of the basics with Sinatra &#8212; just in time to change them all around a bit.</p>
<p><span id="more-898"></span></p>
<p>First, let&#8217;s clean up the index.erb. We&#8217;ll start this process of by creating a file called <strong>adhoc.erb</strong> in your views directory. This will just be a file where you can test out certain things before they become part of your web application. Now move only the form part from index.erb to the adhoc.erb file. Your adhoc.erb should look like this:</p>
<p></p><pre class="crayon-plain-tag">&lt;form action=&quot;/adhoc&quot; method=&quot;post&quot;&gt;
  &lt;input type=&quot;text&quot; name=&quot;message&quot;&gt;
  &lt;input type=&quot;submit&quot;&gt;
&lt;/form&gt;</pre><p></p>
<p>Please note that I changed the action value so the url referenced is now &#8220;/adhoc&#8221; rather than &#8220;/&#8221;. With that done, let&#8217;s clean up index.erb so that it looks like this:</p>
<p></p><pre class="crayon-plain-tag">&lt;p&gt;Index Page - From Views&lt;/p&gt;
&lt;p&gt;Time is: &lt;%= Time.now %&gt;&lt;/p&gt;</pre><p></p>
<p>What you&#8217;ll probably notice is that while I&#8217;m still using HTML, I took away all the surrounding elements that HTML tends to have, such as the &lt;html&gt; and &lt;body&gt; tags. I&#8217;ll come back to why I did that momentarily.</p>
<p>In order for the new adhoc.erb page to be viewed, you will have to add a route to your script. You can probably guess how to do this based on what you already have in place. Here is what you need to do:</p>
<p></p><pre class="crayon-plain-tag">get '/adhoc' do
  erb :adhoc
end</pre><p></p>
<p>Finally, since I changed where the form action goes to, you should change your post route handler so it looks like this:</p>
<p></p><pre class="crayon-plain-tag">...
  post '/adhoc' do
    &quot;You said '#{params[:message]}'.&quot;
  end</pre><p></p>
<p>Now you can visit <a href="http://localhost:9292/">http://localhost:9292/</a> and <a href="http://localhost:9292/adhoc">http://localhost:9292/adhoc</a> to see your &#8220;minified&#8221; pages. At this point all of the surrounding &#8216;template&#8217; HTML stuff has been removed, including the title tag. But since it&#8217;s valid HTML it all still shows up just fine. Still, though, this is not the way to do web development? In the &#8220;wild west&#8221; days of web development it was fine to leave out just about everything and have the browsers (hopefully) compensate for our lackluster web development skills. (Ah, the bad old days. Miss them? Me either.)</p>
<p>So how do we get all that back? Well it&#8217;s probably obvious that we could just include all of the scaffolding HTML in the index.erb and adhoc.erb files. And any other files we create. Or we could use a layout. So here we&#8217;ll construct a layout that Sinatra will use for all of your pages.</p>
<h2>Provide a Common Layout</h2>
<p>In the views directory create a file called <strong>layout.erb</strong>. Put the following (or something like it) in place:</p>
<p></p><pre class="crayon-plain-tag">&lt;!doctype html&gt;
&lt;html dir=&quot;ltr&quot; lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;title&gt;Test Application&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;header&gt;
      &lt;hgroup&gt;
        &lt;h1&gt;Testing App&lt;/h1&gt;
        &lt;h2&gt;Minimal Testing Application&lt;/h2&gt;
      &lt;/hgroup&gt;
    &lt;/header&gt;

    &lt;div id=&quot;main&quot;&gt;
      &lt;%= yield %&gt;
    &lt;/div&gt;

    &lt;footer&gt;
      &lt;p&gt;&lt;small&gt;An Automated Testing Tool Site&lt;/small&gt;&lt;/p&gt;
    &lt;/footer&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre><p></p>
<p>With that file in place, if you now visit both of your pages you will see that both have the layout you provided in the layout file. This works because Sinatra automatically looks in the views directory for a layout template file to render before loading any other views. The extension looked for depends on what you are using for your template engine. Since I have used ERB, the file sought is layout.erb.</p>
<p>The really important line in that layout.erb file is the Ruby yield method. That will return the contents of whatever page is being called at that point in the layout file. Pretty handy! So basically what happens is this:</p>
<ol>
<li>Sinatra sees a GET request for the adhoc page using the erb template engine.</li>
<li>Sinatra looks for a layout.erb file in the views directory.</li>
<li>Sinatra looks for an adhoc.erb file in the views directory.</li>
<li>Sinatra generates the content to display from the layout.erb file.</li>
<li>The ERB template engine sees the yield statement embedded in layout.erb.</li>
<li>The yield state tells Sinatra &#8220;yield to whatever page was called and display its content here&#8221;.</li>
<li>Sinatra generates the content to display from the adhoc.erb file.</li>
<li>Sinatra sends the layout.erb + adhoc.erb content to the browser.</li>
</ol>
<p>One thing this has done, however, has made every page have the same title. This is because the title tag is specified in the layout. This is another area where we can be a little dynamic. First change the title tag in your layout.erb to the following:</p>
<p></p><pre class="crayon-plain-tag">&lt;title&gt;&lt;%= @title + ' | Test Application' %&gt;&lt;/title&gt;</pre><p></p>
<p>If you want to see how your Sinatra app generates stack traces, browse to one of your pages with that line in place.</p>
<p>To have this work, add the following to your route handlers:</p>
<p></p><pre class="crayon-plain-tag">...
  get '/' do
    @title = &quot;Home&quot;
    erb :index
  end
...
  get '/adhoc' do
    @title = &quot;Ad Hoc&quot;
    erb :adhoc
  end
...</pre><p></p>
<p>All I did there was create an instance variable that is available to the route. That variable is available to the dynamic resource called up by that route. Since layout is called up for all resources, it too can use the instance variable. Granted, this is about the most common trick in the book for Sinatra apps but it&#8217;s a good example of how you can use instance variables to pass information to your application.</p>
<h2>Sinatra Can Flash</h2>
<p>Now let&#8217;s try to add another feature of Sinatra: flash messages. These are used to display a message within a session. The most common use for this is when you have a form that submits, generates a message, and sends you to another page. Well, in this case sending you to another page causes you to not see the message, right? (<em>It&#8217;s not a bug! It&#8217;s a feature!!</em>) What you really need is for the message to appear on the page that you were directed to so that, you know, you have a chance of actually reading it.</p>
<p>So the first thing we have to do is require the Sinatra flash module. If you followed the first post, you already got the gem for this. So add the following to your script file:</p>
<p></p><pre class="crayon-plain-tag">require 'sinatra'
require 'sinatra/reloader'
require 'sinatra/flash'

module Symbiont
  class TestApp &lt; Sinatra::Base
    register Sinatra::Reloader
    register Sinatra::Flash
    
    configure do
      set :sessions, true
    end
...</pre><p></p>
<p>What we&#8217;ve done here is establish that our Sinatra application is configured to use sessions. Now, I will add here that I&#8217;m doing about the simplest thing possible in terms of setting sessions. Things can get much more involved than this. For now, however, I&#8217;m keeping it simple.</p>
<p>Here I&#8217;ve also made sure that the Sinatra Flash module is available to us. However, this isn&#8217;t quite enough. Remember that Gemfile? You have to make the following addition to that:</p>
<p></p><pre class="crayon-plain-tag">source :rubygems

ruby '1.9.3'

gem 'sinatra', '1.3.3'
gem 'sinatra-reloader'
gem 'sinatra-flash'
gem 'thin'</pre><p></p>
<p>Then you have to run the following at the command line:</p>
<pre>bundle update</pre>
<p>Note that this is necessary any time you have to include a new gem in your project. Also note that this is a case where you will have to restart the server because it needs to be re-executed in the context of the added gem. Just in case it&#8217;s not clear: the reason the above is necessary is because it generates a new Gemfile.lock file and that file is what sets up the execution environment, in terms of saying what gems are required to execute your application.</p>
<p>Now let&#8217;s use our new module to produce a flash message. Change your post route handler message to look like this:</p>
<p></p><pre class="crayon-plain-tag">post '/adhoc' do
    flash[:notice] = &quot;You said '#{params[:message]}'.&quot;
    redirect '/'
  end</pre><p></p>
<p>Also note I&#8217;ve added a redirect line there to redirect the form submission to the root page. Keep in mind what&#8217;s happening here. A post action is being done on the &#8220;/adhoc&#8221; page and a message is being generated on that page. What this means is that the message will be lost during the redirect. So what Sinatra is doing here is saving that message as part of the session. In order to display it, we have to modify our layout.erb file as follows:</p>
<p></p><pre class="crayon-plain-tag">...
  &lt;div id=&quot;main&quot;&gt;
    &lt;% if flash[:notice] %&gt;
      &lt;p class=&quot;notice&quot;&gt;&lt;%= flash[:notice] %&gt;&lt;/p&gt;
    &lt;% end %&gt;
    &lt;% if flash[:error] %&gt;
      &lt;p class=&quot;error&quot;&gt;&lt;%= flash[:error] %&gt;
    &lt;% end %&gt;
    &lt;%= yield %&gt;
  &lt;/div&gt;
...</pre><p></p>
<p>Wow! Look at all that, huh? This is actually more than you need but what I&#8217;ve done here is put in some embedded logic that says if a flash notice has been generated &#8212; and we know our route handler does generate one &#8212; then display that notice. The same applies to an flash error. The paragraph tags would just allow you to style the errors to look a certain way.</p>
<p>So if you now go to <a href="http://localhost:9292/adhoc">http://localhost:9292/adhoc</a> and submit the form with some text, what should happen is that the root page is displayed and the message appears near the top of the page. Obviously the message isn&#8217;t too obvious, which is probably why you would want to style it.</p>
<p>And that brings up a good point: stylesheets. How do we use them in this Sinatra world? And, for that matter, what about JavaScript? Yeah, those are good questions.</p>
<h2>Stylesheets and JavaScript</h2>
<p>So let&#8217;s add some CSS and JavaScript. Now, I don&#8217;t want to go crazy here because I want to eventually switch up a few things in terms of how I&#8217;ve structured everything. So let&#8217;s do something simple to get a JavaScript file in place. Let&#8217;s also create a simple stylesheet. If nothing else, we can style that flash message of ours.</p>
<p>Add the following line to the head section of your layout.erb file:</p>
<p></p><pre class="crayon-plain-tag">&lt;link href=&quot;/css/style.css&quot; media=&quot;screen&quot; rel=&quot;stylesheet&quot;&gt;</pre><p></p>
<p>Now the key thing to note here is that Sinatra is going to default to looking in the public directory for this path. You can instruct Sinatra to do things differently but, for right now, I see no reason to. So create a directory called <strong>css</strong> in the public directory. (If you had previously deleted the public directory, recreated it.) Within that css directory create a file called <strong>style.css</strong>. Obviously you can style things how you want. Here&#8217;s something to get you started just so you can verify that your css file is being read:</p>
<p></p><pre class="crayon-plain-tag">header {
  background: #cccccc;
  border: 1px solid;
  text-align: center;
  letter-spacing: 0.3em;
}

header h1 {
  font: 42px normal Georgia, &quot;Times New Roman&quot;, Times, serif;
}

.notice {
  color: green;
}

.error {
  color: red;
}</pre><p></p>
<p>If you now go to <a href="http://localhost:9292">http://localhost:9292</a> and submit a message via the form, you should now see that the flash message is green.</p>
<p>So that&#8217;s pretty simple. You use style sheets just as you normally would. The key thing is knowing that, by default, Sinatra is going to go looking in the public directory.</p>
<p>Now let&#8217;s add some JavaScript and make sure that works. Add the following line to your layout file in the head section:</p>
<p></p><pre class="crayon-plain-tag">&lt;script src=&quot;/js/application.js&quot;&gt;&lt;/script&gt;</pre><p></p>
<p>Once again, Sinatra is going to be looking in your public directory by default. So just create a directory called <strong>js</strong> in the public directory and, within the js directory, create a file called <strong>application.js</strong>. You could just put a simple alert() method call in that file and see if it triggers when you visit the page. (It would.) But let&#8217;s make sure that a page can actually call and use the JavaScript.</p>
<p>So create a new page called <strong>stardate.erb</strong> in your views directory. You&#8217;re going to have to create a route for this page in your app.rb file. Feel free to try that on your own. (I&#8217;ll show you how I did it in a bit but it&#8217;s nothing you haven&#8217;t already seen.) In this file put the following:</p>
<p></p><pre class="crayon-plain-tag">&lt;form name=&quot;computeStardate&quot;&gt;
&lt;h3&gt;Stardate Calculator&lt;/h3&gt;
&lt;p&gt;Enter five digit (new era) stardate:&lt;/p&gt;

&lt;input type=&quot;text&quot; name=&quot;stardateValue&quot; size=&quot;15&quot; value=&quot;42353.7&quot; onBlur=&quot;convertToCalendar(this.form)&quot;&gt;&lt;/input&gt;
&lt;input type=&quot;button&quot; value=&quot;Convert&quot; onClick=&quot;convertToCalendar(this.form)&quot;&gt;&lt;/input&gt;
&lt;br /&gt;
&lt;input type=&quot;text&quot; name=&quot;calendarValue&quot; size=&quot;60&quot;&gt; &lt;/input&gt;
&lt;/form&gt;</pre><p></p>
<p>Now in application.js put the following:</p>
<p></p><pre class="crayon-plain-tag">function convertToCalendar(form) {
  var origin = new Date(&quot;July 5, 2318 12:00:00&quot;);
  var stardate = eval(document.forms.computeStardate.stardateValue.value);
  var stardatesPerYear = stardate * 34367056.4;
  var milliseconds = origin.getTime() + stardatesPerYear;
  var result = new Date();
  
  result.setTime(milliseconds);
  form.calendarValue.value = result;
  return true; 
}</pre><p></p>
<p>Remember to put in that route! Here&#8217;s how I did it:</p>
<p></p><pre class="crayon-plain-tag">get '/stardate' do
  @title = &quot;Stardate Calculator&quot;
  erb :stardate
end</pre><p></p>
<p>Now if you go to <a href="http://localhost:9292/stardate">http://localhost:9292/stardate</a> you should see that you can click the Convert button and get a calendar value for whatever five digit stardate you enter.</p>
<p>Note: Since these are five digit stardates, these are strictly new era &#8212; &#8220;The Next Generation&#8221;, &#8220;Deep Space Nine&#8221;, and &#8220;Voyager&#8221;. You will not be able to compute old era (&#8220;The Original Series&#8221;) with this calculator.</p>
<p>As I said at the start, this post is kind of tame in that very little here was anything other than just basic web development. Granted, you now know how to use flash a little bit. It might not hurt for me to explore that a bit more in a future post. But most importantly what you&#8217;ve seen here is that you can use JavaScript and CSS in the way you normally would with your HTML. This is all handy because in the next post I want to talk about how you can use a different templating engine for your markup and how you can use one of the streamlined CSS variants. This latter area, incidentally, is an area of great debate among some.</p>
]]></content:encoded>
			<wfw:commentRss>http://testerstories.com/?feed=rss2&#038;p=898</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
