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.
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.”
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.
In an ongoing software development project we are using Makefile tasks to make running long and repetitive commands as easy and as fun as possible to run. They’re like bash aliases, shortcuts to performing recurrent jobs we frequently have to do while writing new code or testing applications. For example, we could define a task that runs unit tests and code standard checks on an application running in a Docker container like so:
echo "Checking application code with PSR2 standards ..."
docker-compose exec -T php phpcs -v --standard=phpcs.xml ./app/src
echo "Running unit tests ..."
docker-compose exec -T php phpunit --colors=always --configuration ./app
and we would run the task with only the following command:
Cool, right? I don’t have to remember all the exact commands to do what I need to do. And even if I forget the right task name (in this case,
make test) I can just run the
make command in the CLI and I’ll be provided a list of the tasks that I can use for the project.
Now Makefile tasks will run on Unix terminals out of the box. For Windows however, we still have to do some setup before Makefile tasks can run. For my machine at work, I did the following:
- Download and install GnuWin32
- Go to the install folder
C:\Program Files (x86)\GnuWin32\bin
- Copy all files inside the bin folder to the root project directory (
- Add the installation bin directory to the system environment variables
There are other tools that we can use to configure Makefile to run on Windows but this is a quick and easy way to do it. After that we can run
make.exe test on the default cmd CLI but on some Unix-like terminals like the Docker Quickstart Terminal we can definitely use
Problem: I want to automatically run unit tests, lint the application code, and check it’s state against team standards every time I try to commit my changes to a project. It would be nice if the commit aborts if any of the existing tests fails or if I did not follow a particular standard that the team agrees to uphold. The commit pushes through if there are no errors. If possible, I don’t have to change anything in my software development workflow.
Solution: Use a Git pre-commit hook. Under the .git/hooks hidden folder in the project directory, create a new file called pre-commit (without any file extension) containing something like the following bash script (for testing PHP code):
stagedFiles=$(git diff-index --cached HEAD | grep ".php" | grep "^:" | sed 's:.*[DAM][ \\''t]*\([^ \\''t]*\):\1:g');
errorMessage="Please correct the errors above. Commit aborted."
printf "Linting and checking code standards ..."
for file in $stagedFiles
php -l $file
if [[ $LINTVAL != 0 ]]
php core/phpcs.phar --colors --standard=phpcs.xml $file
if [[ $STANDVAL != 0 ]]
printf "Running unit tests ..."
core/vendor/bin/phpunit --colors="always" [TESTS_DIRECTORY]
if [[ $TESTSVAL != 0 ]]
- linting and code standard checks only runs for the files you want to commit changes to
- code standard checks are based on a certain phpcs.xml file
- unit tests inside a particular TESTS_DIRECTORY will run
- the commit will abort whenever any of the lints, code standard checks, or unit tests fails
For any software tester or any software professional it matters to be curious about the industry we choose to be a part in, to be knowledgeable about the people we work with and the tools we use to perform our best work. It helps to be aware of existing practices and be in the loop with the news, well, because that’s how we find solutions to problems, and sometimes more problems to solve. We use the software we test. We find answers on the web. We try applications that could maybe make us be more productive. We network with people like us on the internet, and we go online, study, and digest whatever we can. That’s part of how we improve our skills. That’s part of how we grow, and help others along the way.
But learning takes time and effort and energy. It’s not just about reading and watching everything, taking every online course and going to every conference there is. Our minds does not work like that. We have to pace ourselves well. We need to take breaks in between, we need time for details to sink in, we need contemplation and scrutiny to guide us where to move next and why exactly. Some reflection happens in discussions with colleagues, family, and friends, while other realizations occur only when we are truly alone with ourselves.
So.. after about a week or so since I asked permission for read-write access to our application code repository I’m glad to say that I’m almost done with setting up a version of our apps locally on my machine. It is necessary because I first need to check my changes if they work locally before committing those changes. No code commits yet until said local apps have the same stability as our apps in Staging.
But there are no unit tests. How would I know if everything works after cloning the app repository and running the local settings? Only one option: I had to run local versions of my Staging application API tests. They’re slower than unit tests but at least they let me know if the apps work on some good enough level.
Running tests on local applications!
We’re in business! 🙂
Most of the problems that I encountered whilst setting up were database problems. That’s because no one was maintaining a small-but-updated version of the database. As told, I had to manually match which queries to run according to what problems my tests found. Not pretty, though I could say that in retrospect looking at the errors and finding the DB fix on my own was good exercise. Not elegant, but it helped me get familiarized a little bit with our applications as code.
There was also no documentation about the application and how to run them on various machines. Guides are important but README files were mostly left blank. I had to rely on programmer friends for clues about what to do next whenever I got stuck.
Such problems took time and patience to solve. I had to take notes about updating certain pieces too. Sometimes, I had to make changes to the code itself in order for some features to not fail locally. And yes, I need to remember not to accidentally commit those changes to the remote repository.
It would be nice if we can just go to some private repository and download an environment image or two which runs smoothly when integrated with the app repository. Update the code on a local machine and the environment updates automatically. Set up would have been done in a matter of minutes, not days. But, alas, that’s a problem worth solving for another day.