Automating the Windows Desktop Calculator’s UI using Winium

Ever since I learned how to use Selenium to automate browsers and web applications a few years back, I’ve wondered from time to time whether I can use the same process or technology to automate Windows desktop applications via its user interface. There’s no particular use case at work considering our apps are all in the web, but I challenged myself to find an answer only for curiosity’s sake. It didn’t turn out to be a thought-provoking experiment but at least it was somehow amusing.

Here’s what I got from the quick study:

Click the image to view the GIF full-size on another browser tab 🙂

And a few notes:

  • We can’t use Selenium to automate Windows desktop applications.
  • A quick search about automating Windows apps tells us that there’s actually a number of tools we can use for such purpose, some paid, others free. Other than Winium, I found out that we can also use Sikuli (or its successor SikuliX), WinTask, autoIT, TestStack.White, Automa, MacroSchedulerCobra, or Pywinauto. There’s probably more tools out there. I just chose to use Winium because writing tests and automating the app with it is similar to how Selenium works, which means very little learning curve for me.
  • Source code for this short experiment can be found here: Win-Calculator. It uses Maven for handling installation of project dependencies while the test code is written in Java. The tests run locally, I’m not sure whether there’s a way to manipulate a Windows app on another machine using Winium. I have not researched that far.
  • Winium will actually take control of the machine’s mouse to move to the element locations set in the tests. This means that interrupting the position of the mouse while the tests are running would likely fail the test. This is annoying, and I’m not sure whether the other Windows app automation tools behave otherwise or the same.

Uploading Images in Watir 6.0.2

Even when most of the automated checks in our test server are running via the HTTP layer instead of using the browser, I have kept the automated UI versions of those tests for review purposes. They’re not very practical for continuous integration but still fun to watch sometimes, at least for me. It is also good practice to fix them when they break, to see whether I’m still updated with how Selenium or Watir runs.

And recently I found out that I’m unable to upload images in Watir 6.0.2 using the usual way, giving me an error:

element located, but timed out after 30 seconds, waiting for true condition on <element location> (Watir::Exception::UnknownObjectException)

The test code in question was this, written using the page-object gem

self.photo = IMAGE_FILEPATH

where photo is just a given name for a file field in the page where an image is to be uploaded. In basic Watir, this can also be written as

@browser.file_field(:id, "LOCATOR_PATH").set(IMAGE_FILEPATH)

Both test code are timing out, and the test failing because of the exception error. When manually checked, there are no issues in uploading images whatsoever.

Apparently, this an open issue in Watir and the workaround at the moment is to properly set the values of Watir’s relaxed_locate before and after the actual image upload code, like so

Watir.relaxed_locate = false
self.photo = IMAGE_FILEPATH
Watir.relaxed_locate = true

or

Watir.relaxed_locate = false
@browser.file_field(:id, "LOCATOR_PATH").set(IMAGE_FILEPATH)
Watir.relaxed_locate = true

And that makes the image upload work again. Both work for Google Chrome and Mozilla Firefox. 🙂

An Experiment on Executable Specifications

What: Create executable specifications for an ongoing project sprint. Executable specifications are written examples of a business need that can be run anytime and acts as a source of truth for how applications behave. It is a living documentation of what our software does, and it helps us focus more on solving the unusual and noteworthy problems instead of wasting time with the ones that we know we shouldn’t have been worrying about.

How:

  1. Join a software development team for one sprint duration.
  2. Discuss project tasks for that sprint with everyone.
  3. Ask about requirements examples and create executable specifications for those tasks as the application is being written.
  4. Refine the specifications when necessary.
  5. Continuously update the specifications until they pass.
  6. Keep the specifications running on a preferred schedule.

Why: To see if writing executable specifications alongside development is feasible during the duration of a sprint.

Limitations: Tester writes the executable specifications, programmers work as is.

Experiment Realizations:

  • Writing executable specifications can be done during actual app development, provided that tester is experienced with the tools for implementing it and understands well why the need for such specifications.
  • It is of course more beneficial if everyone in the team learn how executable specifications work and write/run the specifications, and why the need to implement it.
  • It will take quite a long while before executable specifications becomes a norm in the existing software development process, if ever. This is a function of whether everyone believes that such specifications are actually useful in practice, and then building the skills and habit of including these specifications in the team’s definition of done.

An Encounter with the ‘cucumber.yml was found, but could not be parsed’ Error

One day last week I merged a colleague’s new feature tests to the existing test repository. Routinely after that, I logged in to our dedicated test server, updated the existing running test suite by retrieving the latest merged code, and ran a ‘bundle update’ because the updated code required the latest versions of the dependencies. The updates finished without hitches as expected after a minute or so. Task’s done, I just need to run a sample test to be certain everything’s well and good.

An error blows up in my face:

cucumber.yml was found, but cannot be parsed. Please refer to cucumber’s documentation on correct profile usage.

Before all these, I had run a simulation of the gem updates on my local machine including running all tests to make sure there were no surprises when updating the test server. But I was still caught off-guard. I didn’t see that coming.

What? That’s always the first question. I squinted at the screen and looked at the error message again; it says something about the cucumber.yml file unable to be read by the machine, like it was corrupted. I opened the file to check (which contains various cucumber profile configuration set up for running tests on different test environments), was able to view its contents in the text editor, inspected it for unfamiliar code and found nothing. It looks okay, but the machine says otherwise. Why?

I tried an initial Google search for the error message and saw a fix that was written five years ago, saying that the error occurs because of a particular ‘rerun.txt’ file. The post tells me that the problem will go away if I delete that file.

Except that I don’t have that file in my code repository. What now?

Maybe there’s really something going on with the test code. Let’s see what happens if I delete a particular profile in the cucumber.yml file. Done. No changes in behavior, error still exist. What if I delete everything? Done. Error didn’t go away. Hmm.. that’s odd. It seems that the file contents are not the problem, is valid YAML code too according to online checkers, and the file is not damaged in any way I can see.

I went to back to looking at the search results for possible solutions People keep telling me its about the rerun.txt file. Others say I need to edit a cucumber library file in order to see what test code specifically causes the error for cucumber’s runner. No more other clues. Now this is difficult.

I kept researching for plausible fixes online for a few hours, I thought that there may still be something that can help me but I missed. No such luck. Okay, let’s try editing that library file and see what happens. It was a first time viewing library code, because I didn’t have any reason to do it before, and told myself that maybe I should actually check it out more often.

I found the command-line interface profile_loader file and the particular code which loads the cucumber.yml  file in question:

Found you, cucumber's profile loader!

Found you, cucumber’s profile loader!

Commented out some few lines of code as suggested:

Now let's see what your problem really is

Now let’s see what your problem really is

Then ran the sample cucumber test again:

A problem with the Psych module! What's that? :O

A problem with the Psych module! What’s that? :O

Okay. It says that a missing private method named ‘load’ is being called for a particular Psych module. No wonder cucumber is failing. Bummer, I don’t have a single idea about a Psych module that cucumber runs. All I can do is another Google search for the new error message and maybe find a workaround.

I am reminded that problems in building systems for automated test suites are not limited to writing test code and the application under test. Just like any other software, they can sometimes break in areas we do not know anything.

Eventually I found this enlightening post on a Github repository:

Interestingly, a very short solution. It was a rubygems bug after all, and what I needed to do was to run a ‘gem update –system’ command to get our cucumber tests back up and running.

 

The Lessons I Learned This Year About Software Testing

Last year I told myself I would take a step back from automation because I’ve already built tests with a working knowledge of Java and TestNG. Apparently, with the way things went this year, I was not satisfied after all with what I had. I went on to study Ruby with Watir and Cucumber for about half of 2016, and I learned how to run web applications without using browsers after that. And for a second year in a row I feel I overdid studying again, and maybe I’m getting too comfortable about writing test code. In any case, programming has become such a useful tool in my workflow – performing checks automatically that otherwise would have eaten up a chunk of my time and enabling me to test other things.

Some other realizations during the year:

  • Re-writing test code using Ruby with Watir and Cucumber and other useful ruby gems pointed out how messy the checks I wrote last year using Java was. It helps that the Ruby language has less boilerplate syntax but my earlier mistakes are more about refactoring and design rather than about the programming language itself. I still need more deliberate practice at that.
  • I’ve found out that I actually do security testing in my normal day-to-day exploratory work, but I’m not especially great at it because nobody has taught me how to perform good web security testing before. It seems that getting comfortable reading and manipulating API calls is a step towards becoming better at it.
  • Teams who develop software with agility does not necessarily mean they implement scrum or kanban. If there’s good communication and teamwork, teams can actually forego many of the rituals and focus on the actual work.
  • Writing automated checks with healthy test description language is an important skill.
  • People only learn to solve problems when they feel that those problems are worth solving. And problems that are worth solving for me does not mean they’re worth solving for other people too, so I should never stop using perspectives.
  • We can leverage REST calls with web automation to make them run a lot faster and more stable.
  • Exploratory testing is a prerequisite to automation.
  • Building a great team is difficult. There are a lot of factors to consider – team composition, empathy, attitude, member skill set, strengths and weaknesses, to name a few. It takes some time too.

Speeding Up a Suite of Web Application Automated End-to-End Checks

Speed is always an issue when running a full suite of automated end-to-end checks for web applications because they are inherently slow. Tests open a browser on a desired machine, navigate to a required application state (and hence often wait for the app to load completely), do an action on the system, validate results, and finally perform cleanup if necessary. A single check runs for some good number of seconds especially if it goes through several phases, and this means that a suite of tests can easily total to an hour or more. It’s easy to add tests. It’s difficult to have the full suite of tests run in under only a few minutes, especially when the only infrastructure available is only a local machine.

Some ideas on speeding up automated end-to-end checks:

  • Bundle related tests together in a group, running on top of each other, the resulting state of one test becomes the requirement of the next test. This is risky. What happens when the first test fails? The next test does not run anymore, even if the test probably passes. But we don’t know that because the test did not run. Ideal automated checks should be independent of each other, should be as atomic as possible.
  • Run tests in parallel. TestNG does this with Java, the parallel_tests gem can do it with Ruby. Jenkins (among other continuous integration tools) can run multiple jobs if fancied. Remember however that running automated checks in parallel is a processor-intensive task and has some tendency to fail tests because of system lag, timing, or application state sharing between tests, especially on low-end machines. Investing in dedicated infrastructure (whether physical computers or software-as-a-service systems on the cloud like SauceLabs) definitely helps, but the decision for that depends on the organization’s financial prioritization.
  • Minimize end-to-end checks as much as possible. This is viable for systems built with a healthy dose of existing unit and component tests within the application stack, usually teams who practice good test-driven development (TDD) or behavior-driven development (BDD) when building software. For a lot of teams without such unit tests to fall back to, reducing the number of working automated end-to-end checks will prove to be difficult.
  • Use headless browsers. I haven’t had much experience running checks on headless browsers but people do use them, often successfully using xvfb on Ubuntu.
  • Leverage REST calls. How does the browser load a page URL? How are users are redirected from one page to another? How are form values submitted properly when a call-to-action button is clicked? Using REST calls, one can log in on a system with the right credentials, retrieve data from where it is displayed, or send data to the application without opening a browser. We can use that for automation, either for simulating a desired application state or for testing responses to manipulated requests whether that’s data or the resulting page. This can help our tests run faster, the only catch is that the tester will have to learn how REST calls work and (more importantly) understand how the web application under test runs under the hood of the browser.

Post-Installation Notes after Setting-Up Cucumber-Ruby-Watir Automated Checks with Jenkins on a Windows 10 Amazon EC2 Server

Had a chance to set up cucumber tests to run via Jenkins on a Windows 10 Amazon EC2 server last week. It’s been a while since I installed everything from scratch, so that was good practice. I ran into some problems, which was a bit expected since my local setup was on Windows 7, so this post serves as a guide for possible future installations.

The process:

  • Install desired browsers where the tests will run.
  • Install Java and the latest JDK. Include the JDK path to Window’s system environment variables. This is necessary for running the selenium server.
  • Install the latest Ruby and DevKit versions, required for installing ruby gems and running the test suite.
  • Install Jenkins, which will take care of scheduling and test results reporting. Also install Jenkins as a service, to run automatically after the server boots up.
  • Install Git on the machine, and setup the credentials for retrieving the test code from the remote repository.
  • Check out the test code from the remote repository.
  • Set the selenium server to run automatically after the machine boots.
  • Install the required ruby gems using bundler.
  • Check if cucumber tests run properly by running a sample via the command line interface.
  • Create/Import Jenkins jobs for the cucumber tests. Install the Jenkins plugins necessary for test results reporting. Possibly set up Jenkins to pull the latest test code from the remote repository.
  • Run cucumber tests via Jenkins.

Some reminders for future installs:

  • Install the 32-bit version of Ruby’s DevKit instead of the 64-bit because the latter version creates problems with gem installs.
  • Windows 10 has trouble installing ruby gems (using the bundle install command) from the default HTTPS source. To fix this, replace the gems source list in the Gemfile from HTTPS to HTTP.
  • Install Jenkins using the MSI-based Windows installer on its own directory on the C drive, then install it as a service afterwards.
  • Do not install all suggested Jenkins plugins at first, especially the ones related to Git. These will break Jenkins on Windows so install only those that are actually needed for cucumber tests to run.
  • Via Jenkin’s Configure System module, set the shell executable to the location of the command line’s executable file (i.e., C:\Windows\system32\cmd.exe) so that Jenkins can run cucumber tests via the default Windows command line interface. In addition, each Jenkins job Build needs to be set as “Execute Windows Batch Command” instead of “Execute Shell”.
  • Remember to change the timezone of the machine to the proper timezone.
  • Test a sample basic cucumber project first to see if cucumber is properly running on the machine before retrieving the actual test suite from the Git repository.
  • In saving the machine’s generated public SSH identification (via Putty or the ssh keygen command using Cygwin), do not include a name for the file to be saved so that the system generates the default id_rsa.pub file.