Sunday, November 3, 2019

On Having Become #CodeConfident

For 2019, I've once more made a pact with my learning partner Toyer Mamoojee. This year my personal challenge was to become code-confident. To learn about my hypothesis, the experiment I designed and who influenced me to embark on this journey, please read the origin story. Now that the challenge is officially over, it's time to look back and forth.

Why This Challenge

Why did I pick this challenge? This question followed me throughout the year. Here are the reasons I discovered on my journey.
  • Programming is a skill that many people benefit from; no matter their role. I think this is the case already now, and presumably even more in the future.
  • Many of my peers in the testing community program every day.
  • People say coding skills are essential for us testers. Even to stay "employable" and get new jobs. Whenever I heard this, I felt I don't belong and that soon enough everyone will see that, too. Even worse, many people consider you only technical when you're able to code. I absolutely don't share these viewpoints, but still felt the need to prove myself that I am not only able to read code but also write code myself. It was about time to conquer this fear of losing my face by showing how much I don't know yet and to see for myself how much I can increase my programming skills in a certain time frame.
  • I feel I „specialize in generalizing“ (as Patrick Prill likes to say) - so I wanted to upskill as a generalist. To strengthen my strength by adding coding to my toolbox.
  • I wanted to be able to help my testing better through automation and tool creation.
  • I wanted to understand our product architecture better, how things work together, where they tend to break, where the risks are.
  • My knowledge is quite broad yet scattered, and never really deep. I have lots of bits and pieces of knowledge and often try to puzzle them together to see the bigger picture. I wanted to see how far I can go with this when it comes to coding. The good thing: I realized I don‘t have to know everything to belong. The main key is to keep yourself aware of your contributions and the value-add you bring, and then to keep going and learning new things, adding to that toolbox you bring.


Continuous Practicing

In the beginning I found the very first steps to be the easiest and the hardest at the same time. If you want to know more, read about my first steps until picking my first coding challenge. As soon as I published my first ever GitHub commit, things started to roll.

As I started out on this coding journey, I soon felt the urge to blog about my experiences and lessons. At the same time I wanted to avoid spending too much effort on blogging and rather put it into practicing. I decided to experiment with a new lightweight blog post type in the form of a coding journal, documenting my raw notes while coding. My hope was was that these kind of posts will serve three goals.
  1. Act as learning journal for myself, making my learning journey visible helping me acknowledge what I achieved
  2. Provide context for anyone who would like to check out my repositories and maybe provide feedback and support
  3. Potentially provide a source of learning and inspiration for anyone else following my journey
So I had finally started, I blogged about my journey - next thing to do was to call for collaborators, people to pair with me hands-on or provide feedback on my code. Once more I learned about the joy of doing things together when you put trust in each other. Compared to my Testing Tour last year, I did a lot on my own as well. However, I wouldn’t be where I am without my wonderful collaborators, so here’s a huge shout out to these great people!
Not mentioned above but never forgotten are my dear teammates supporting, encouraging and teaching me during work time. Thank you.

Besides those that paired with me, this wonderful community was a great factor and motivator on my journey by providing dearly needed encouragement! Like Angie Jones who recognized my growth in her technical workshops - which meant a lot to me! She even triggered me to submit to Test.bash();. Without her I wouldn’t have presented my lessons from this challenge at TestBash Manchster. Also, during the code-related workshops I attended this year I realized people thanked me for helping them - which made me realize I was indeed able to help them!

After getting started with my first challenge, I decided to go from more familiar topics to the least familiar ones for me. So I came up with the following plan.
  1. Start with automated testing through the UI (though these tests might actually be the most complex, starting with something familiar made perfect sense to me);
  2. Then go a level deeper to API testing;
  3. Then to unit testing;
  4. Now cross over to writing features myself, first implement a small backend feature;
  5. Then implement a small frontend feature.
I hoped afterwards I would already be ready to start my proof of concept project.

Last but not least: while working on my challenges, I had to keep an eye on my self-imposed constraints.
  • Pause criteria - play computer games at least once a week
  • No online courses or tutorials - at least not for the actual practice scope
  • Time - at some point I realized I had to speed up, especially for the TestBash Manchester talk
The great news is: I fulfilled the promise to myself to have at least five repositories of practice projects published on GitHub - even in five months!

Time to Tackle the End Game

As I had hoped, I was now ready to build an application myself. I pondered for a long time what I could do as my final proof of concept app. In the end I decided to create a learning journal. An app that would help me tackle my challenges, based on what I learned so far - and other people could use the same approach. A place to define a challenge, a hypothesis, the experiment. A place to track your progress, to evaluate your results.

So this it was! I created “Journey” - a learning journal application. I wanted to use a similar tech stack to what we have at work. In the end not as similar as I intended yet still really useful for practice.

However, there‘s a twist to it. I decided to kick-start the project so I wouldn’t have to deal with the whole setup. I chose a tool called Jhipster which allows you to generate apps from scratch. Great, right? Well, this approach had upsides and downsides to it. First and foremost: I felt guilty, like I cheated by doing this jump start; while being well aware that at work we also used code generators in the beginning of a project, like the Spring Initalizer or the generated snippets by Angular. It was great to already have a running base to work on; yet the project was bloated from the beginning, with features added that I did not need (like user management or auditing). When you start something from scratch, you know everything (or most of it); with this kick-start, I felt I immediately entered a legacy project, I had to learn how things work together. Yet after all it was still valuable for practice and learning! So I decided to move on with it.

Based on the generated code I then introduced my own entities, created views, modeled what I wanted it to do. What you can do with it is you can define your challenge, and you can create journal entries for your challenge, tracking your progress. Just that, serving as proof of concept. The project is absolutely not finished yet. There's so much more to do, and so much more there could be. It would be a great playground to practice all kinds of testing as well. Though my challenge is done, I can still continue work on it - which feels amazing!

Let's Evaluate

First of all: I could prove my hypothesis true. I did practice, I paired up, and in the end I did develop a small product.

Even more: My whole year was under the focus of coding. At conferences I chose courses, workshops, and talks according to my goal. I attended sessions about mutation testing, automation in testing, clean code practices, approval testing, Python for testers, Jest, and more.

The outcome was indeed actual confidence! End of August I finally realized how much I had worked on code at work over the last weeks. I found myself writing unit tests for our new frontend, to help my developers with our safety net here and to understand our product architecture better to see where it breaks. We were experimenting with mutation testing. I even did some refactoring myself! I finally realized it was the result of having become code-confident (past tense!). To illustrate that, for example I found myself having inner dialogs like the following:
"Okay, now I’m tackling the split of this dialog component into two. Or - nah, maybe someone else should do it, they could do it more efficiently. Or maybe we do it together! Pairing is great. Well, let's have a short look at it first. Oh, that looks like more than I thought it would... Well, whatever, let’s try anyways."
And I was able to do it! In addition, by doing so I understood our application a lot better. The thing is: I would have been capable of doing this before already - yet I didn’t dare to do so. I hesitated, found excuses.  Now I am not afraid anymore to try and to learn by doing. I know there’s a lot more to learn - and that’s fine!
All this made me think. I could stop now with confidence - yet what about if I dare even more? Step even more out of my comfort zone? When preparing my TestBash talk about this whole challenge, my original idea was to have no slides at all, just code, walking people through. Well - obviously I still had slides in the end, I did not dare go without them (yet!). Still I wanted to dare even more. So I decided to do some live coding on stage to show my confidence. I considered that this might go horribly wrong - yet at least I would have tried it. I thought, even if I failed I would have succeeded as I would have dared; and I would have learned what not to do in these situations. ;-) So I prepared for it. I chose my proof of concept project Journey as my target app. I chose a super small change to make it less scary, to not take too long, something that would still allow me to narrate what I am doing at the same time. Small steps, right? Also, I chose a frontend change so people could see the impact right away without me having to restart the app. So that's how I did it - and it worked out!

Plenty of Lessons Learned

There are a lot of lessons to take away from this journey. Let's start with the lessons learned when working with code.
  • Learn how to go in small steps. And then even smaller steps.
  • Googling is a real skill - if you know what to look for it will save you lots of time.
  • Read things carefully. Documentation, exceptions, what methods expect - don't skim over them but read them properly! Sometimes you really need to read everything to get the information you need.
  • Keep maintenance in mind. Would a method now take more than three parameters? Then it's time to refactor as it's getting too big to keep it in the head. One method, one purpose; keep it small. Shall we extract a method for a line that's used in two places? It might not be worth the effort, yet should be consistent. The most elegant solution might not be most readable one, find the middle way.
  • Test the tests. I encountered this classic several times: a test that's constantly green but not checking the right thing (or no thing at all). Sigh.
  • Learn IDE shortcuts by heart; especially for all features you constantly use.
When it comes to code review:
  • Get feedback early and incrementally.
  • Don’t take it personal.
  • Learn from it.
  • Thank people for their feedback.
  • Respond to each feedback.
  • Need to discuss? Then rather discuss in person.
  • Stay patient.
  • It’s scary but worth it!
And finally, I also learned a lot on the personal challenge itself.
  • Learning by exploring is really valuable (and very close to our everyday work). I have a hunch, thought, that it might be best combined with some more structured training.
  • In the end it’s all about practice, practice, practice. It's not about doing things perfect from the start, but about daring imperfection and getting feedback to improve.
  • Pair up for success. (Obviously.)
  • Follow your energies and don’t forget to take breaks. Tired days are not helping. For a private project you have the luxury of leaving a problem for a while and follow your energies instead to keep the momentum. After a while you can either come back to the problem or leave it there (if it’s just for practice); at work we often have to push through, yet defocusing can still help there as well.
Overall, I learned a lot! But I also struggled a lot. My biggest struggle increased my empathy for my developers. Not only the kind of work they do as problem solvers, or having your own work reviewed, but especially when it comes to testing.

When developing I caught myself just wanting to make things work and then move on. The sad truth is, I postponed errors. I sometimes did not test a change at all, neither using exploration nor automation. I just wanted to move to the next change and the next and the next… I really should know better and yet did not care! (Still can't believe this. Super embarrassing.) I really had to remind myself of switching between development and testing modes, or rather intertwine them. This is not easy and I will need to continue practicing. Now I know better how they feel and how difficult it can be to not jump to the next feature.


What else?

Besides this challenge: I‘m finally enjoying my hobby again! As I promised to myself, I played a computer game each week since 2018, December 16th. :D Yet honestly, I struggled to achieve even that. I did not play too much each week. The sad truth is, I dearly needed this personal limit to take better care of myself. So, I'm still working on finding a better balance. We should not put our personal lives behind our personal development.

Now that I survived puzzling bits and pieces of knowledge together to create something myself - I can go back to school! :-) I wanted to fill my theoretical knowledge gaps and get a deeper understanding of the languages, or at least revisit the basics. To begin with, I finally did a bunch of more courses offered by the Test Automation University. By doing so, I discovered that I knew a lot of these things already! This kind of confirmation is a really encouraging. Also, this made me revisit some important concepts that I had heard of already yet never really memorized. As a side effect, I know now that these courses are very worth recommending, they are well taught and provide a wealth of easily accessible, free knowledge. If you haven't done so already, check them out.

At work, I continued to contribute in new ways, using and practicing my coding skills a lot more. This feels so good! Especially as researching real problems open up so many opportunities to learn more.

Oh, and I'm sure there will be another personal challenge for 2020! :-) I'm already thinking about it. Yet no matter what I might choose, I already made a decision to continuously offer pairing sessions, on various topics. Over the last years this proved to be extremely beneficial to all parties. In case you're up for it, feel free to check my availability for the next period on Calendly and book a session with me.

In Summary

If you want to go on your own journey and tackle your own challenge, then break it down so it becomes testable and therefore achievable. Explore using the knowledge you already picked up on your way, and practice! Yet always remember: take care of yourself first.