Smart Contracts

Updating Solidity code and Testing a Smart Contract

Books on the Blockchain

Publica Self Publishing

Goodbye Contracting

Hello brave new old world...

Ruby-Selenium Webdriver

In under 10 Minutes

%w or %W? Secrets revealed!

Delimited Input discussed in depth.

Tuesday, 18 November 2014

Auto-refresh a web page

Today I discovered the main website I keep at wasn't live. Shockfest! I say the main site, but it's the main 'static' site, the main site is perhaps the blog over at now. Either way, the website was (is) down and I'm waiting for support to email it's back up.

The email will be appreciated but just trying to load the site is the best way to know it's there. What I don't want to do is keep hitting F5 though. Thankfully HTML has the reload() method available. Wrapped in a little JavaScript we can use this to poll the site and avoid having to refresh it ourselves.

The script is pretty straight forward and useful for other things. You can plug in that auction site, page with a hit counter, flight status or test results dashboard page showing on a large screen in the office.

Paste the below into your favourite text editor and save it as a .html page.

           <script type="text/JavaScript">  
                function pageCheckRefresh(timeoutPeriod) {  
                //  -->  
      <!--- change this to the refresh time you want -->  
      <body onload="JavaScript:pageCheckRefresh(10000);">  
           <!--- This first url is just a control, one we know WILL be there, so we know this checker is working -->  
           <p><iframe height="200" width="750" src=""></iframe></p>  
           <!--- You can have more pages in iframes, just copy the below ( <p> to </p> ) -->  
           <p><iframe height="300" width="750" src=""></iframe></p>  

You'll need to edit two things and add one:

Edit the refresh
It's currently set to 10000, which is 10 seconds.

Edit the target URL
Change to the URL you're interested in.

Add additional URLs
Copy and paste the ...
section and add another URL to check multiple pages.

That's it, straight forward but handy.



Liked this post?

Say thanks by clicking an Ad


Wednesday, 1 October 2014

Ruby Selenium-Webdriver - Quick Start

Guess how old Selenium is? If you didn't know, it's now (over) 10 years old... no really! How about Selenium 2? Well that was released in July of 2011, so it's not 'new' by any means. 

If you've not had a look at it yet, now's the time! Selenium-Webdriver will allow you to execute web tests using a range of browser easier than before. You can also use your favourite programming or scripting language and a range of other tools to enhance your testing.

As always, I'll be using Ruby on Windows for this demo and assume you have Firefox browser available - let's get going!


1. Install Ruby
To do that either read the blog post here or watch the video on YouTube:

Set-up and install Ruby


2. Check your Gems
We're going to need the selenium-webdriver gem. To install that, open a CMD window (start > run > 'cmd') and type gem install selenium-webdriver. You can check installed Gems by typing gem list which shows what's available and their version.

3. Start Interactive Ruby (IRB)
For this demo we'll just run commands straight from IRB. Using a CMD window type irb to start IRB.

In IRB type require 'selenium-webdriver' to start a webdriver instance so we can pass it commands to execute.

4.  Open the browser!
Yes, we're ready to start using Webdriver. Now type the following to invoke an instance of Firefox with the reference of browser.

browser = Selenium::WebDriver.for(:firefox)

If all is OK then Firefox will open. If you get an 'access' warning, just click OK.

5.  Run some tests
Now work through the following commands to run a basic test using Google.

Google will now load in the blank browser instance.

Type: browser.find_element(:name, "q").send_keys("Hello)
This will type 'Hello' in the query text field, but not return it.

Type: browser.find_element(:name, "btnG".click)
We'll now see search results returned.


Watch the video!

References for DYOR:


Liked this post?


Ruby Basics » Part 15 | Hashes - A Quick Intro

Welcome to the first post of the second part, in our series on Ruby Basics. To see what's coming up, check out the Trello board:


When we looked at Arrays, we saw that collections of data were stored under a given Array name. These were accessed by knowing the integer value of the data item’s location in the array. If you recall in the Basics 1 Wrap Up, we had the following Array:

        rolesArray = ["Developer", "Tester"]

To access these we need to use [0] and [1], as in

        print rolesArray[0]
Later on we assigned David or Alan as one of these roles and this worked fine. But what if we now wanted to assign them individual salaries, periods of employment, holidays allocated or other relevant data. We could create Arrays and put the data in the same sequence as the employee array. For example we might set-up:

rolesArray = ["Developer", "Tester"]
rolesHolder = ["Dave", "Alan"]
rolesSalary = [40000, 35000]
rolesHoliday = [25, 25]
I’m guessing you can see that’s all well and good if everything stays in order. For those with a little Database knowledge this problems with the above approach scream even louder. What we need is a way to explicitly pair the data above with a key bit of data that won’t change. In this case that key bit of data is the employee name.  How can we label the various bits of data with the employee name?

What we need is a key --> value pairing of data, so no matter what order they are stored, we can find, edit, update, and delete the correct one. As luck (Ruby) would have it, what we need is a Hash.


A Hash is a collection of Key-Value pairs. Hashes are also referred to as associative arrays, maps and dictionaries. They’re like Arrays in that they’re still variables storing variables, however unlike Arrays the data isn’t stored in a particular order. Also unlike Arrays, we don’t push/pop data into and out of the Hash, we simply insert and delete Hash values. Let’s look at making a Hash for some of the above data.

We can make a new empty Hash in a similar way to a new empty Array;

        rolesHash =

If we print the above, of course nothing will be returned. As we then acquire data to add to it, we can insert the data by giving the key-value pairs:

        rolesHash["David"] = "Developer"

Try running the entire snippet below:

rolesHash =
puts rolesHash

rolesHash["David"] = "Developer"
rolesHash["Alan"] = "Tester"

puts rolesHash

Here we add two key-value pairs to our newly created Hash and print the entire Hash out, which looks something like this:

        {"David"=>"Developer", "Alan"=>"Tester"}

If we wanted to find out what role David was currently in we could look it up using the key:

                    puts rolesHash["David"]

If you try this with a name that is not in the Hash, then the result will be nil which isn’t very informative. A better way is to define a default value, for example:

                    rolesHash ="No Role Assigned")

Try it again and watch the default message get printed.

Adding to the Hash is good, but we also need to delete items too. To do this we simply call the delete method on the hash and specify which key we want deleting.


If you’d prefer to just build out your Hash from the start, you can do that too.

salaryHash = Hash["David" => 30000, "Alan" => 35000]
puts salaryHash

We’ll leave the basics of Hashes there, as always have a look at the Ruby docs to see more of the methods available. Later on, we’ll look at some of the more complex aspects of Hashes, but for now we have what we need!

Monday, 29 September 2014

NightwatchJS - JavaScript web automation with Selenium-Webdriver


As the website says "Nightwatch.js is an easy to use Node.js based End-to-End (E2E) testing solution for browser based apps and websites... Simple but powerful syntax which enables you to write tests very quickly, using only Javascript and CSS selectors."

If you're happy writing a bit of JavaScript, then Nightwatch is an interesting option to look at. It uses Selenium Webdriver at it's core and so fits the tech stack commonly used for web testing.

This post is a no-fluff Quickstart to get nightwatch.js set-up on a WINDOWS system - because as usual the Nix* crew have posted for that side already. Here nothing is 'explained'. For a more details and how to set-up on other systems, see the Nightwatch website and Github repo. 

This is describing set-up on a **Windows 7 Professional** 64-bit system with Firefox installed. 

For the epicness, in a new tab, open this and leave it open until you are complete!



1) Base folder  
  • On your system create a folder called dev on the root, e.g. C:\dev

2) Install Node.js
  • Under C:\dev create a new folder called nodejs.  
  • Go to and install nodejs in the new folder, ensure you include the npm (Node Package Manager) tool in your installation.  

3) Install nightwatch.js  

  • Under C:\dev create a new folder called nightwatch.  
  • Got to Start > Run > and type 'cmd' to get a console window.  
  • Type `npm install nightwatch` and note the location and structure of the install.  

4) Get Selenium Server  
  • Download "selenium-server-standalone-{latest version}.jar" from;  
  • Place the file in the nightwatch/lib folder created as part of the nightwatch.js installation.  
  • Rename the file to `sel-serv.jar` for ease of reference.  

5) File to call the runner  

  • On your system navigate to C:\Dev\nightwatch\node_modules\nightwatch  
  • Create a new file called nightwatch.js
  • Add the following line and save the file; `require('nightwatch/bin/runner.js');`

Basic set-up is now complete!  

6) Start Selenium
  • Open a console window (or reuse the one from step 3) and navigate to: C:\Dev\nightwatch\node_modules\nightwatch\lib
  • Now type `java -jar sel-serv.jar` to start Selenium Server.  
  • Open Firefox and navigate to `http://localhost:4444/` to check the server is up (ignore the 403 error).  

7) Run some tests!
  • Open a new console window.  
  • Navigate to C:\Dev\nightwatch\node_modules\nightwatch\
  • Run all example tests by typing `node nightwatch.js`  
  • Run a group group of tests by typing `node nightwatch.js -g google`  
  • Run a single test by typing `node nightwatch.js -t examples/tests/nightwatch.js`  

Yay!  Your first nightwatch.js tests!


p.s. Look out for the post on creating a VBScript report viewer for Nightwatch.

Enjoyed this post?
Say thanks by sharing, clicking an advert or checking out the links above!

Monday, 22 September 2014

Testing Search

I got thinking about Search testing the other day and ended up waking at 4am to scribble a mind-map of thoughts before I lost them. As you do.

The main thought was how Search testing traverses the three main layers of testing we typically consider.

* Where - the web front end in which the user builds their search queries
* How - the Search 'engine' that does the work of polling the available data

* What - the data that is being searched

Target of the search
Before any testing commences, we need to understand as fully as possible what it is that can be searched for. To do that we need to be clear on the data that is the target for the search. Though reasonable to expect the searched for data to be static in a database, the returned results might also be dynamically generated by the search query. Not all data returned may be under the control of the business, remember the search may also be fed by external data.

- What data is the user searching for? (e.g. products, account records, flights, ...)
- What data sets are available? (e.g. product attributes, transactions/payment types, current/future flights, ...)
- What is the source of the data? (e.g. static data, dynamically created data, external sources, ...)

The Search Engine
The most informative way of learning this is via the API documentation for the search engine. With this we'll know what can be passed to the engine and so shape the scope and structure of allowable queries. Some good public examples of Search APIs are those for Google ( and Twitter (

If your development team can't provide the API docs, ask for access to the Java docs, Unit Tests or whatever else can inform you about the implementation specifics. In my experience, the design of search is rarely sufficiently detailed enough for testers, in specification documents or requirements statements. Indeed in a more agilistic setting it's very likely this detail is closer to the code - get sauce! You can't properly test the implementation from just the original specification.

To counter the obvious challenge here of 'you don't need to worry about that... just run your tests... confirm the requirements have been met... ', as part of the implementation team you are not restricted to just looking at the acceptance tests or requirements. As part of the implementation team, in the tester role, you are working with equality with all other roles and so the code, unit tests, etc. are not 'off limits', just as your tests and automation code is not off-limits to anyone. If you are told they are, then you are not in an agile team or whoever is saying this needs to get off the agile team. (Whether you can understand the code, tests, etc. or not is another matter)

Building Queries
Our next concern close to the user, is the UI and how it allows the search queries to be crafted.

- How can a search query be entered? (free text, drop-down, ...)
- How can search options be used? (Boolean, switches, ...)

Now that we have knowledge of what the search functionality actually is, as a component of the system, let's think about what testing will be needed.

We clearly have out typical functional testing, that will include submitting search queries. However, we need to break that down too, to ensure we're clear about what we're actually testing.

As we have a UI, we'll need to test the functionality a user is provided to build a search query. This might be a simple free-text field like Google, where the user just enters whatever text they want with no switched, drop-downs or options. Be aware this can have hidden nuances too though. At first glance Google search functionality is just a text field, but in fact we have a bunch of ways to structure our search query.

For example, you can enter 'define: testing' to get a dictionary definition or search for files in a given directory, try '-inurl:htm -inurl:html intitle:"index of" + ("/secret")' to see how not to hide your password files and pictures of your ex girlfriend. Don't do that search in work by the way! If you've reviewed the API docs or something similar you should know if the above types of searches are available to you.

For searches constructed by selecting from drop-down boxes, using radio buttons, etc. it'll be more apparent what choices you have. Again, be careful to understand where the data in drop-downs for example is coming from. As always, view source. Is that drop-down populated via an Ajax call, a fixed list in the HTML or a list from another JavaScript? Depending on how those selectable search options can be chosen, it will affect the specific test cases that will be possible. Remember to do some equivalence partitioning where any lists are concerned, like other tests it's highly unlikely you'll need to test all combinations.

Obvious initial tests will be data entry, using valid and invalid inputs, leading spaces, special characters and all the other standard cheat-sheet heuristics. However, we need to be careful here as this is more likely form-field input validation, which is not search testing. Be sure again to view source and see where that validation is taking place, client or server side. Hopefully it's not an embedded JavaScript, check source and if you see a src=validation sounding JavaScript name, save a local copy and inspect it. Oh wait, you don't need to do that because other members of your implementation team have shared these items via your CVS / Git / etc. and you can review them.

We've all experienced using a search engine and getting a result that is nothing like what we were after. The underlying challenge here is a code and engineering problem, but it's part of our job to show how inaccurate results are. The definition of this will likely be a combination of referring to requirements and our experience / gut-feel. When we use search engines ourselves, we'll often get results that are technically correct and yet wrong. It'll be a bunch of blog posts on a given topic where half are barely relevant or a search for 'coco' that uncovers a family (un)friendly set of pictures of a lady looking rather 'distorted'. 

When we perform a search it's reasonable to expect the results will be the same if the underlying data and search engine logic are the same. This will form the basis for some of the regression testing we'll want to conduct over successive releases.
However, there are occasions when the same search string will bring back different results.

* The search database is replicated and data varies between the databases
* Data has changed since we last run the query

This should be noticed due to a problem with search result consistency. Either the search string will be consistently different than was returned in a previous test run or it will sometimes be different. Where data is different consistently, we just need to validate this is as expected then update our script. For results that should be the same but are sometimes as expected and at other times not, we need to look at where the query is going. A common problem for search consistency is the combination of data replication across multiple data-bases and routing due to load balancing. When we conduct our search, we might not be 100% certain as to what data sets we are hitting and which server our query is hitting. These are questions to take up with whoever is fulfilling the Dev Ops / Infrastructure role in the team. We need to understand the data replication process, are all servers copied to at the same time or in some kind of order? Is there a back-up process that takes servers off-line when we might be testing?

For all of the above we could be using a simple tool such as Selenium with a dashboard to show results. Selenium allows us to run the tests in a loop, vary the query, save down results files, etc. What i would not use it for, although I know it does get used for this, is performance.

Another aspect of search is the speed at which we get back our search results. We'd expect this to vary but not by much, usual changes in network traffic and resources on machines are fine to a degree. When we start to see notable slowdowns then we need to investigate. To help with testing of performance use a performance testing tool, as above, Selenium ain't it. Grab a copy of JMeter if you're working with open source tools. It should be an easy matter to replicate your test in JMeter and build them out into a test plan that let's your performance test search results.

In closing
In this post we've looked at the fact search testing is not just putting a few search strings into a text field and reviewing the results don't look wrong. We have the full scope of functional and performance, along with data accuracy and consistency to consider. To test thoroughly we need sight of the requirements but also the code or API docs and an understanding of the network infrastructure that's in place.


Testing search functionality on websites and applications

Thursday, 14 August 2014

Why you're NOT a Software Testing Expert, probably

I see it often on people's profiles and CVs, Expert. It's one of those words that get my attention straight away - and is often badly defined. I'm sure that trying to work out where you are, on a scale from clueless to expert, is something I'm not alone in doing. I was recently invited to review a training course on the basis feedback from an expert like me would be useful. Hmm...

In a recent set of interviews for my next contract and (shock) a permanent role, I've been thinking about this more than often, as you would. It's important to be clear about what you do and don't know, then answer truthfully... no really ;). In some of the calls I've been asked to rate myself on a scale of 1 to 10 either for specific skills and technologies or say as a tester or manager. This creates a problem, given my expectations of what an Expert is, being set so high. The problem being, I rank myself much lower than perhaps I would be expected to say. I could state big numbers, but I don't have an ego the size of a planet. I probably don't have 'marketing' smarts either.

Thinking through what an expert or a 10 is, I came to the conclusion that people at this level are almost unheard of, certainly rarely encountered and almost definitely not doing telephone interviews. That's why you're probably not an expert, probably. We could argue on the 'label' but let's use Expert as the top and Clueless as the bottom. I'll make up ones in between. The reason you're probably not an expert is due to the second issue, the labels are used too broadly.

Imagine I introduced myself as an Engineering Expert, Medical Expert, Physics Expert, Agricultural Expert, Legal Expert. You would immediately need to ask "In what field?" or maybe "In what area?". These descriptions are too broad. There's no way you're a 10 in brain surgery and a 10 in gerontology, you won't be a 10 in family law and a 10 in contract law, you can't be a 10 in civil engineering and a 10 in aeronautical engineering. You can't therefore be a 10, a Software Testing Expert. By definition it doesn't make sense.

Just at a high level we could break testing down into say Functional, Performance and Security, though we could add in other major testing areas. Straight away with just these, I'm sure you'll agree we all know people who are more 'expert' in some of these areas than others. Add in that there are people who focus on test management or on the other end of the scale perhaps automation. Even then, when we say "they're an automation expert", we mean they have expertise in a certain set of tools, technologies and techniques (TTT).

OK then, so when asked to rate ourselves and if we're an expert how might we define that?

On a scale of 1 to 10...

1 - Clueless
You have no awareness of the TTT. When someone says Git, Capybara, C and Java to you, you think it's about animals who are idiots living across the sea on an exotic island.
But hey, well done for reading this blog, stay a while, click an ad. Now go and get yourself the ISTQB Foundation certificate and become a real expert! (that was a joke...).

You resolve to continue pushing yourself. Perhaps there's more to you than you thought.

Given the above, the rest of us fit somewhere after. However, one more refinement, we don't need to worry about exact numbers. In any given role your skills and aspects of them, will be needed to a greater or lesser degree. "about a nor n, depending on the demands of the project" is a reasonable answer when asked about your skill, on a scale of 1 to 10.


2 to 3 - Beginner
At this level you've been exposed to the technology, though your understanding of it is limited. You are starting to remember what you are shown step-by-step to do, though constant guidance is needed when encountering issues outside of direct tuition. As a beginner you won't yet understand how the TTTs fits into the overall testing domain. You may recognise the need, e.g. why continuous integration is a good idea, why end of day reporting is valuable, but you carry out tasks as shown, in a rote fashion. With more practice, you start to take on more complete tasks under guidance and begin to need less day to day reference to mentors or help sources.

You realize that all your life you have been coasting along as if you were in a dream. Suddenly, facing the trials of the recent past, you have come alive.

4 to 5 - Able
Now you've started to gain some ability to use the TTT day to day as expected. You're fully comfortable with the basics and have started to understand why the TTT is needed. In addition, you now start to see what value it adds, how it integrates with and supports other TTT. You can be readily delegated to but might not always be completely successful or fully efficient in using the TTT to complete a task. Some remediation by more experienced staff might be needed, though when given you gain useful insight into whatever was previously unclear and make positive advances in your overall ability.

You sense yourself more aware, more open to new ideas. You've learned a lot about Software Testing. It's hard to believe how ignorant you were -- but now you have so much more to learn.

6 to 7 - Capable
At this level you're able to carry out whatever needs to be done, with guidance and support not expected to be needed. You fully understand how the TTT works and integrates with others, have insight into common and more obscure issues and problems that occur. You can now start to mentor others in the team and comfortably bring the TTT to projects as part of your professional tool-kit. When thinking of what you 'do' and how you work, the TTT will be part of how you define yourself and your capabilities. many sources of information on the TTT and others people's understanding of them are notably less than yours. You may start to find it difficult to discover new ways of improving your understanding and use of the TTT because what's to learn is getting less and less mainstream, more difficult to find.

It's all suddenly obvious to you. You just have to concentrate. All the energy and time you've wasted -- it's a sin. But without the experience you've gained, taking risks, taking responsibility for failure, how could you have understood?

8 to 9 - Competent
Once you become competent you've gained a full professional understanding of whatever TTT you're working with. By definition you are now possessing all the necessary ability, knowledge, experience and skill to do something successfully, efficiently and with complete consistency. Doing it with your eyes closed... on auto pilot... hardly thinking about it - are all phrases that people are whispering behind your back. You will certainly understand the shortcomings and limitations too, identifying ways to work around them or improve them and integrate with other TTT. By now you'll be known as a key go-to person for the TTT in the profession and likely blog or write on the topic. You competency is so complete, that you can begin to subvert the methods and reasons for using the TTT to deliver unexpected improvements and start to re-wire the ways of working and benefits derived.

You're really good. Maybe the best. And that's why it's so hard to get better. But you just keep trying, because that's the way you are.

10 - Expert
There has to be a level that is the absolute pinnacle of knowledge and expertise, a level so high it cannot be surpassed. This is the level 10 Expert.

To be a level 10 Expert you invented the TTT, several years ago and others are still playing catch-up. You published a book on it and/or get speaking engagements to explain the awesomeness to the masses. Alternatively, you have gained such a level of understanding that you have gone back to the inventors and pointed out where they're getting it wrong, heck you probably decided they're so missing the point that you went and spun off your own TTT to show how it REALLY should be done. You don't look for jobs with this TTT, they come to you.

You'll never be better than you are today. If you are lucky, by superhuman effort, you can avoid slipping backwards for a while. But sooner or later, you're going to lose a step, or drop a beat, or miss a detail -- and you'll be gone forever.

(it was going to be this, but the above was wittier ;} )

Like a Spartan of the tech world, you search the globe for your equal, but it's a lonely pilgrimage - Mark Crowther

Extra bonus points if you can place the quotations...



Liked this post?


Tuesday, 5 August 2014

Ruby Basics - Wrap Up 1

Hey All!

Well here we are, 15 videos in and already at a wrap up of what we've learned so far!

In this post, let's do a code walk-through of a script that includes the elements we've covered in the rough order of the videos. Be sure to check out the Ruby Playlist on YouTube if you've not done so already. Grab a copy of the script here


The first thing to look at is getting user input and assigning the data to local variables. Here we do a basic puts and using a local variable called userFirstName we assign it a value the user enters. On this value we call the string class methods of chompdowncase and capitalize. In the second set of lines, we use #{interpolation} and call a string method on that too. Quite a lot in 4 lines!

# Let's declare our LOCAL variables and get some values straight away (Video 2 and 5)
puts "Welcome, what's your first name? (Dave, Alan or yours)"
userFirstName = gets.chomp.downcase

puts "Hi, #{userFirstName.capitalize}. What's your surname?" 
userLastName = gets.chomp.capitalize

Next we assign a global variable so we have access to it anywhere in our script, pretty similar to what we've just done. Global variables are identified by the $ symbol.

# Let's create an example GLOBAL variable (Video 6)
$globalNameText = "User name is: "

While we're looking at variables, let's declare an instance variable and so some concatenation. You'll recall that instance variables are identified by using the @ symbol. (We'll look at Class @@ later). We also snuck in another string method, upcase.

Here there are two ways to concatenate text, using either the + symbol or << symbol. Ruby docs tell us that + creates a new string, where as << appends the string to whatever precedes it. In terms of speed and memory usage this could be significant on large data sets! Let's be clear, userFirstName + " " creates a new string that now includes a space. Doing << UserLastName just adds it to the existing string.

Can you design a test to prove this?

# Now we'll make an INSTANCE variable from the user name (Video 7)
@userFullname = userFirstName.upcase + " " << userLastName
#upcase is also string method 

Next we define a Constant, which we do by using all uppercase. Age isn't a good exmaple but it works for our purposes :) As we're getting a number, we don't use the usual downcase, as that wouldn't make sense. Try it and see what happens.

# Finally let's get a CONSTANT in use (Video 8)
puts "#{userFirstName.capitalize}, how old are you?"
USER_AGE = gets.chomp #we UPPERCASE Constants to differentiate against variables

We print out a message using our Global and Instance variables, showing concatenation works just fine on these too.

# Put the correctly formatted name to screen
puts $globalNameText + @userFullname

As we want to have data already stored for our program to use, we next create a simple array of data, just with strings in this example.

# set up an array with the template roles (Video 9)
rolesArray = ["Developer", "Tester"]

Now that we have our data, let's do some evaluation of it and decide what the outcome of that should be. The first step is a Case statement, against whatever names the user entered above.

Here, we respond to the user with data we've pulled out of the array we just set up. You'll recall that we index into arrays starting at position 0. So when we run the script, Dave will be assigned the role at position 0, a Developer.

# Depending on what the users first name is we'll respond with more details (Video 10)
case userFirstName
when "dave"
    puts "#{userFirstName.capitalize} you are a #{USER_AGE} year old #{rolesArray[0]}"
    userRole = rolesArray[0]
  when "alan"
    puts "#{userFirstName.capitalize} you are a #{USER_AGE} year old #{rolesArray[1]}"
    userRole = rolesArray[1]
    puts "You must be a new member of staff, welcome!"

Next, we'll ask about a career change and instead of using a Case statement to control the flow of our response, we'll use a basic if and then a nested if statement.

As we've discussed before, we can evaluate the response using regular expressions or direct evaluation.

# Here we use a nested IF to check for career changes (Video 12)
puts "Do you want a change of career? (Yes or Y or No or N)"
careerChange = gets.chomp.downcase

if careerChange =~ /\A(yes|y)\z/ then
    if userFirstName == "dave" # (Video 11)
      puts "#{userFirstName.capitalize}, you are a now a #{rolesArray[1]}"
      userRole = rolesArray[1]
      elsif userFirstName == "alan" or userFirstName == "Alan"
        puts "#{userFirstName.capitalize}, you are now a #{rolesArray[0]}"
        userRole = rolesArray[0]
        puts "Easy #{userFirstName.capitalize}, you just joined us!"
  elsif careerChange =~ /\A(no|n)\z/ then
    puts "Great, keep up the good work!"
To finish off the main body of the example script we'll now use a While statement, to keep asking a question until a condition is met. We've also snuck in an If ternary to decide how to respond if the hoursWorked value is under 8.

# Now we'll check if the user has done a days work! 
hoursWorked = 0
userRecord = [userFirstName, userLastName, userRole, USER_AGE]

while hoursWorked < 8 # we could do an UNTIL hoursWorked == 8 here instead   # (Video 13)
  puts "How many more hours have you now worked #{userFirstName}? (enter 0 to 8)"
  puts "total hrs worked is so far: #{hoursWorked}"
  hoursWorked = hoursWorked + gets.chomp.to_i

    hoursWorked < 8 ? (puts "Keep going, the day's not over!") : (puts "Well done, go home and relax.") #example of if Ternary (Video 13)

Just to finish, let's add a new data element to the end of the UserRecord array and print the results.

userRecord.push hoursWorked #Pushing to an array (Video 14)
puts userRecord

Don't forget to grab a copy of the script and play through it yourself!


Read More