Dockerizing Our Legacy Apps: Some Notes

I spent the recent weeks of January tinkering with Docker in both Windows 7 and Mac OS. I played with it a lot because I thought it’s something that’s useful for a grand new project we have at work, and I thought that integrating our legacy application code to it would help me learn about it more. And the exercise did help me understand the tool better, including some nuances with application performance and database connections. I was able to dockerize our legacy apps too! 🙂

Some notes to remember related to the exercise:

  • Windows 7 Docker Toolbox and Docker for Mac has a performance issue with volume mounts through docker-compose. Legacy apps composed of a large number of files (especially with dependency directories) will run, but they will be painfully slow out-of-the-box. Fortunately for Docker for Mac users, docker-sync has an effective workaround for this problem. It involves running an in-sync container for the application code, separate from the docker-compose file. Unfortunately, I have not found any workarounds for said performance issue for Windows 7 (and perhaps Windows 8) Docker Toolbox users.
  • Often we have to update the host file of our server machine so that we can run applications locally using a distinct, easy-to-remember URL through a browser. This means we need to add extra hosts to necessary docker containers too if we dockerize our apps. We can do this by using the extra_hosts command in docker-compose.
  • The official Postgresql docker container does not include the pdo, pdo_pgsql, and pgsql drivers, which handles the connection between the application and the database. To install those drivers inside the official container, we’ll need to use a Dockerfile and build it from the docker-compose file with the build and context commands.
  • Sometimes we have a need to copy the Postgresql DB files from a running container to set up a proper volume mount of database data from host to container. We can copy that data by using the convenient docker cp <source> <destination> command. I had this work in Docker for Mac. However, for Windows 7 Docker Toolbox users, a docker container is unable to use such copied data, perhaps because of the difference in OS between host and container, so I had to resort to restoring and backing up data every time I start and stop my application containers.
  • As a tester, what Docker provides me is a convenient tool to test all sorts of interesting application configurations as much as I want to on a single machine, see if the apps break if I changed some service config, and find out which configurations work or not. I can add or remove a new service, or even update an existing service to a new version, like updating PHP from 5.6 to 7.1, and immediately see what impact it has on the apps themselves. These kinds of tests are often left to operations engineers, but I’m glad there is a now a way to do such tests on my own machine, before application changes even reach a dedicated testing server.
  • Even if Docker makes it easy to setup an application development environment from scratch with docker-compose and Dockerfiles, it is still important to maintain a wiki of the necessary machine configurations a programmer needs to perform in order to reset or build the apps with only a single command, or two. Subtle things like custom docker-compose files, .env and php.ini files, host files, Nginx configs, or turning long docker commands into shortcuts with shell scripts or make commands.
  • Makefile tasks can help put specific scripts into an easy-to-remember command with context. I assume Rakefile does the same thing in Ruby, or Jakefile in JavaScript.
  • Dockerizing our legacy apps pushed me on a discussion with programmers about the ways they run said applications on their machines. Most of them actually just test code changes directly on Staging or another available development server. That speaks about one habit we have as a development team, and likely the reason why our apps are a pain to setup locally.

Five People and Their Thoughts (Part 5)

It’s been a while since I’ve shared interesting articles and recordings about topics surrounding software development and testing.

Here are a few videos, for the curious:

  • Continuous Delivery – Sound’s Great But It Won’t Work Here (by Jez Humble, about continuous delivery, the excuses organizations tell people when they fail to implement it, and what those excuses actually mean)
  • There and Back Again – A Hobbit / Developer / Tester’s Journey (by Pete Walen, on how software was built in the old days, how testing and programming broke up into silos, and a challenge for both parties to go back at excelling at each other’s skills and teaming up)
  • Feature Injection (by Chris Matts, about business analysts and tea bags, understanding that requirements are just dependencies, and finding out where the value is in requested features by asking for examples)
  • A Day of Mob Programming (by Woody Zuill, on mob programming, and how taking a whole team approach to coding can help us align and build better software together)
  • Testability vs Automatability (by Alan Richardson, about the differences between testability and automatability, what each term actually mean, and recognizing how specific words can help people tell stories better or not)


The past few years I managed in-office software testing knowledge-sharing and tools-tutoring sessions for junior testers at work. It’s not something fancy, sessions are minimal but somewhat regular, and my goal was only to pass on some of the interesting lessons I’ve come to believe to be true based on studying and experience. I want them to become curious about the industry they’re in and I want them to take ownership of their own growth as testers.

I’ve always done the sessions in a group since there are only a few of them. It’s easier to manage that way. But this year I’ll try working with each tester one on one. And this year I’m having them select a skill they think is something they need to learn more of instead of me just providing some agenda in the group meetings. Each tester will have a weekly one-hour one-on-one schedule with me, we’ll review what the tester understands about the topic of their choosing, we’ll study together, and then I’ll provide challenges for them to go through until the next one-on-one. It’s an engaging setup I haven’t done before, something that’s likely to eat more of my time and attention but something that warrants testing since the organization recently changed work schedules to working remotely about half of the time.

6 Curious New Tools to Try for Writing Automated Checks for Browser Apps

While I don’t find myself writing a lot of browser-based automated checks these days, I still am on the look out for interesting new tools in that space. The reason: the new tool solves an existing problem I have with setting up such a testing suite from scratch or provides a solution for certain curious use cases I’ve never experienced before. While using Ruby and Watir together in writing tests running through the browser for me is sufficient for common tasks, such a new tool could be a better fit for another project.

Here’s a list of such tools that popped up in my feed in recent months:

  • Cypress. What I like about Cypress, aside from the standalone package installation option and the built-in pretty test report page, is that the pre-defined browser tests that the actual team runs on its own site is included out-of-the-box. This way they made it easy for me to write custom tests; I just had to search for an example of what I wanted to do, copy-pasted it to my own test, and updated the parts that needed changing. Tests are written in Javascript. I have yet to try running the tests via the terminal though, which is important when running tests on a CI server. Using their test runner is free for all projects, however there is a pricing plan for using their dashboard service which helps keep test recordings private.
  • Katalon Studio. This is a full-blown automation solution that is completely free. There’s a pricing plan for business support services. The record-and-playback feature built-in to the tool failed to impress me when I ran it through our legacy apps, but perhaps writing the actual test code through their GUI fares better (using which there will be a high learning curve for people like me who like to use the CLI and personally-configured IDEs).
  • PuppeteerBuild to control Google’s headless Chrome or Chromium browser, running over the DevTools protocol. Tests are written in Javascript. Easy to try and get into using their web playground. Alister Scott has tried it running with Mocha and Circle CI on a demo project.
  • Chromeless. Similar to Puppeteer, but built to automate an army of Chrome browsers running in parallel. It gives us the option to run tests on AWS Lamba too. Again, tests are written in Javascript, which we can try on their demo playground.
  • Laravel Dusk. This gives PHP developers familiar with Laravel the ability to write and run their own browser app tests, using a programming language they’re much accustomed to.
  • Appraise. Similar to BackstopJS, a tool for visually validating browsers apps. Tests are written in Markdown.

Lessons Learned from Richard Bach’s “Curious Lives: Adventures from the Ferret Chronicles”

I always start the new year like most people, spending quality time with friends and family, some reflection and goal setting, with good food, many cheers, and hearty laughs. I also often choose a wonderful book or two to go on an adventure with during the holidays, because it is always worth the while. This time, I got lucky finding a paperback copy of an old Richard Bach collection, titled “Curious Lives: Adventures from the Ferret Chronicles”, was glad to meet up with ferret friends, old and new both, and got valuable reminders about the courtesies and living accordingly to our highest sense of right, along with the fun ride.

Here are my favorite lines from the book:

  • Whatever harm I would do to another, I shall do first to myself. As I respect and am kind to myself, so shall I respect and be kind to peers, to elders, to kits. I claim for others the freedom to live as they wish, to think and believe as they will. I claim that freedom for myself. I shall make each choice and live each day to my highest sense of right.
  • Once, long ago, we changed our minds: end violence. In its place, no matter what: courtesy.
  • If you excel at your craft, there is a good chance that curious ferrets will need to know why, to find out what makes you different.
  • With the adventures we choose and the mysteries we solve we build our own credentials, write our own introduction to others around the world who value adventure and mystery themselves.
  • Trust. There’s a light, when we close our eyes, the light of what we want to do more than anything else in the world. Trust that light. Follow, wherever it leads.
  • Giving our visions and stories and characters to become friends to others lifts not only ourselves but the world and all its futures.
  • “There’s a time to work on a book and you know it,” said the muse. “There’s a time to think about the story, a time to care about your readers, your publisher, about rhythm and timing and grammar and spelling and punctuation, about design and advertising and publicity. But none of those times, Budgeron, is when you’re writing!”
  • Her husband had told her long ago that she didn’t need to please everyone with her stories – if a book pleases only half of one percent of the reading public, though no one else bought a single copy, it will be a massive bestseller.
  • Budgeron Ferret had chosen to be a writer. With his choice came poverty, loneliness, rejection, frustration, despair, perseverance, delight, attention, riches, love, understanding, fulfilment, a life of ideas that mattered to him, shared now and then with kings and kits.
  • How strange, he thought. Find the greatest teachers, ask the hardest questions, they never say, ‘Study philosophy’, or, ‘Get your degree’. They say, ‘You already know’.
  • The mark of true flight is not our altitude but our attitude, not our speed but our joy in the paths we find above the earth.
  • No one taught her, but she knew: more important than talent or gifts or education is the determination to make one’s wish come true.
  • “Vink, if you want to meet the one ferret who can fix any trouble, no matter how bad it is, the one who can bring you happiness when nobody else can do it – why, just look in the mirror and say hello.”

Testing Goals for 2018

I think that I have more or less accomplished my testing goals for this year. As expected there weren’t many changes at work; workload remained pretty much the same and I had enough free time to try the tools that I thought were interesting. I read most of the books on my reading list. I was able to get the testing team curious on API testing. I re-wrote the existing UI test suite to API-based tests because they’re faster, more readable, and easier to extend and maintain that way. I learned new skills – web application pentesting basics and a nifty test-driven software development workflow – that will be put to the test in the coming years.

What about 2018?

Hmm. Besides continued knowledge-sharing sessions and the practice of test-driven software development I don’t really have that many goals next year in terms of testing and development of software. I’m sure I’ll continue to take interesting online courses and be updated on what’s happening in the testing community but other than that I don’t know.

What I do know and what I believe I want to focus on more next year is taking better care of myself, outside of work. I’d like to get better at both preparing good food and exercising. I’d like to put my drawing skills to work once again. I’d like to take better care of friends and family. The skills I want to get better at now are not those that I can practice in front of a computer but on the field, both when alone and with other people.

I’ll have to try changing some of my existing ineffective habits and stories. It’s going to be a difficult 2018.

The Lessons I Learned This Year In Software Testing

It was only several years ago when I started writing Selenium tests, first with Selenium IDE, then in Java with Webdriver, then in Ruby with Watir. Now I don’t write a lot of Selenium tests anymore, ever since I found out that it is often better (faster and more stable) to write automated checks for application features through the API. Or through unit tests. Selenium has its place in checking user flows or automating the UI, but only if I have to, if its value exceeds that of its costs. There lies an important lesson in automation: there is not a single tool that does it all. It is us who decides which tool to use for a particular test, and it helps to understand if a tool fits the specific use case.

And I think I’ve familiarized myself with a number of tools this year: Postman for API testing, Winium for automating Windows applications, BackstopJS for open-source visual testing, Cloud9 for cloud-based software development, Phonegap for HTML-based mobile app development, Docker for building shareable self-contained images of applications for development or testing, PHP testing tools (PHPUnit, Guzzle, Behat), and source code linting tools like Rubocop for Ruby. I’m not a master of these tools, but I know enough to be able to decide whether I need them (or not) for a particular thing I want to achieve. They’re in my tool belt.

Needless to say, I have outgrown the hype of automation. It is programming and tooling at its core. It helps us perform repeatable tasks without breaking a sweat, not limited to testing apps, if done with care. It is not easy. It can be rewarding. It all starts with a deep understanding of what definite task or problem actually needs solving.

And this year’s experiences has lead me to better grasp the nuances of software development, which is actually a problem of people, of teams and their habits and biases. Our team certainly has its defaults, some of which are not helping us get better at what we do. And as such from here on I’d like to contribute in key areas I believe our programmers have not had much time to think about because of project deadlines and resource constraints – dockerized application environments and shift-left testing – solutions for providing testing feedback earlier in the software development cycle, which in turn can help us build better apps and release faster.