Sunday, June 2, 2019

Nordic Testing Days 2019 - Seamless and Surprising

This year I had the opportunity to be at Nordic Testing Days for the first time. I had heard lots of good things about the conference and seen intriguing tweets about it. Therefore I was especially happy when my paper proposal got accepted for the 2019 edition!

Arriving in Great Company

At Tallinn airport I was lucky to run into Gwen Diagram, Ash Winter and Nicola Sedgwick. Super nice to meet them again! As it was quite late already we went for dinner (or rather tea, as I learned) together with Shey Crompton. Wonderful evening with lots of good food and great conversations!

Tutorial Day & Speakers Dinner

Showing up at the venue for the first time was a big revelation: what an amazing place for a conference! The venue was formerly a power station and got now transformed to host events like this. I heard people had mixed feelings about the venue - they seemed to either love it or hate it. I for one was absolutely on the loving side! I had registered for the Android Application Security Testing tutorial by Marko Belzetski. I wanted to extend my security testing knowledge, to learn about mobile apps and security specifics to broaden my horizon, and in general to practice - and I wasn't disappointed! All expectations were fulfilled. The tutorial was a great mixture of conveying knowledge and hands-on practice (I especially love the latter). It was well structured and instructed, the setup was working perfectly, and we received concise tips and concrete advice. The only downside: for the fourth and final part in the afternoon we had too much content left so we had to rush through and only receive a short demo instead of being able to practice ourselves. For a long day this felt a bit overwhelming, and yet it was very useful knowledge which I wouldn't have missed.

In the evening it was time for the speakers dinner. I knew that last year they had visited the TV tower together so I was curious where we were led this year. We started off to the lovely seaside (I really regret I did not take any pictures there). We went on - and ended up on a boat. Yay? Well, boats and I are not quite friends so I was skeptic how dinner on a boat might turn out for me. In the end it was okay and I could grab more than a bite. The best part of speakers dinner isn't the dinner anyway - it's getting to know speakers you haven't met yet and enjoy the reunion with speakers you know already. Like Alex Schladebeck, Lena Wiberg, Elizabeth Zagroba, Guna Petrova and many more. We had an amazing time!

The Conference Days

The program was packed full of awesomeness. When I realized that the workshops I wanted to go to were completely overlapping with three talks each, I had a hard time making choices. In the end I went to workshops only besides the keynotes due to their topics and my wish to practice my skills hands-on. Also, I learned that some of the talks got recorded so I hope I still get a chance to watch them later.
  • Keynote: Machine Learning from System Quality Perspective by Mikhail Iljin. Really interesting topic in general, yet the core message and takeaways of the talk stayed unclear to me. Unfortunately I could not relate to the talk and would have loved to have an inspiring, thought-provoking, or enlightening opening keynote to set the tone and atmosphere of the conference instead.
  • Workshop: Unit Testing for Non-Coders by Amit Wertheimer. Great session! Amit made a great effort with preparing not only the flawless tech setup (and even backup), but also preparing the people on what they can expect, to explain everything in a language all understand without assuming knowing or not knowing, and kindly supporting them throughout. The provided cheat sheets and exercises were really helpful also for people more comfortable with code to really reflect about things and gain a deeper understanding. The only pity was that we ran out of time in the end; practicing seeing the gap that's not tested, writing a test and discussing their quality would have really rounded up the great workshop.
  • Workshop: Explicit Exploring Using Testopsies and Microheuristics by Alex Schladebeck. Awesome session. Included the right amount of valuable information sharing and hands-on exercises. Ended shortly before time. Lots of energy and fun in the room. Awesome topic as well and really relevant, also for very experienced explorers! The only thing I missed a bit was a short individual debrief after the testopsy pairing session to learn about my own testing better and to practice providing my observations and feedback to another tester. All in all Alex did a great job, being smart, entertaining and engaging.
  • Keynote: How Come Testers Are so Incredibly Successful by Raimond Sinivee. Great speaker on a great topic! Was a really relevant call to action for everyone, perfect for a keynote. We all need to get out of our comfort zones and grow. Loved the personal stories to illustrate this message! Very well presented, with lots of energy and stage presence, while still being authentic - great after a long day to keep the audience focused. Very well done!
  • Keynote: Why Should Exploratory Testing Even Be the Subject of a Keynote? by Alex Schladebeck. Brilliant! The topic definitely deserved to be a keynote, especially presented this way. Lots of relatable stories, lots of energy on stage, lots of thought put in to the content, lots of very relevant and applicable messages. What else could I want? Together with her related workshop Alex was the best speaker of the conference for me.
  • Workshop: Testing with Jest by Blanchรฉ Carstens & Calvin Moore. Great workshop, providing basic concepts, usages, examples and approaches when using Jest. I only had two points that could have improved which I also told Calvin. First, the workshop started a bit slow. It's always difficult to plan for an unknown audience yet a mechanism to scale and cater for different experience levels would have been nice. Second, the workshop ended quite early; instead it would have been great to have the group implement their own tests to apply the gained knowledge. Still, all in all, I got a first introduction into Jest which was what I was coming for.
  • Keynote: Life After QA by Erik Kaju. Interesting keynote with good content, based on experience, well presented. Really relevant topic as well.
In the evening of the first conference day an evening program was announced, including party, game night, lightening talks, and Powerpoint Karaoke. All great! However, what had not been announced and came as a surprise, was that this evening got kicked off by an acrobatic duo of "two old ladies" - what a hilarious and astonishing performance! Love it.

My Workshop

On the last afternoon, just before the closing keynote of the conference, I facilitated a workshop I had done a few times already: Learning to Learn in a Mob. We had a great group of people who did really well and obviously enjoyed the session. It was fun facilitating and I learned a bunch! Joep Schuurkes had asked me upfront if he could join the session and just observe my facilitation of a mob, as he is doing a weekly mob with the testers of his company to share knowledge. Of course, he was very welcome! This turned out to be super valuable to me, as right after the conference we had a super interesting conversation about the observations he had and the ideas it triggered for both of us to improve our mob facilitation skills.

Post-conference Socializing

Part of each conference is conferring - especially during breaks or after the conference already ended. Several speakers had to leave early this time, and still we found a nice small group to relax and have a nice dinner with: Amit Wertheimer, Elizabeth Zagroba and Joep Schuurkes. No wonder our conversations continued in the hotel lobby until early in the morning! We ended up talking about all things programming languages, tools, design patterns, what is "technical", beliefs we got raised with, what changed in tech since the 70s, learning on the job, essential fundamentals and in general educational approaches to teaching programming (by the way, Angie Jones' new free Java programming course just got released!), and many more.
The next day I had time to sleep in and do some sightseeing. In the evening I enjoyed a lovely dinner (or shall I say feast?) with Amit Wertheimer at the wonderful medieval-style old restaurant Olde Hansa where we could dive even deeper into further topics.

A Great Time

All in all: it was a wonderful conference. Huge thanks to the organizers, everything was seamless and smooth, and everyone was extremely kind and supportive. My special shout-out goes to Guna Petrova who supported me just as if she would have been my track chair - which she wasn't. In addition, my actual track chair did an amazing job as well! I loved to see so many awesome speakers. The best thing is that several of them will also be at Romanian Testing Conference in only two weeks!

Monday, May 27, 2019

#CodeConfident: Angular7 Example App

After my recently fulfilled challenge to implement a backend feature for an existing application, I now wanted to do the same on the frontend side. Once again, as soon as I had found my practice application to extend, I could not let go. What helped me accomplish my goal within one week in the end was to pair up, this time with the wonderful Mirjana Andovska! We had already paired on my Testing Tour last year which was a great experience. Now she saw my call for collaboration for my #CodeConfident challenge on Twitter and scheduled a session with me. It was super fun and enlightening and it definitely won't be the last! I feel really honored and lucky that even further pairing sessions are coming up Amitai Schleier and Parveen Khan. Can't wait!


May 19


May 20


May 21

  • small things are easy to change, like removing the GitHub link, removing the footer, etc.; looking for something bigger where I can learn more
  • learned about Firebase, the example app is using a cloud database for all instances, same for the deployed example https://www.angularexampleapp.com
  • learned that even opening a hero detail page will result in POST requests to the Firebase database (interesting to follow up on!)
  • one of the first goals was to be able to open the detail page for newly created heroes instead of getting routed to the hero list itself --> found this decision is done in the heroes list page component html, just a basic case detection
  • feels now that this is the right practice project to work on, forked it
  • played a bit more with "default" and non-default heroes, adapted the search to include both, checked how to display default avatar images for detail page for non-default heroes etc.
  • feature idea would be the one from the project: implement material tables

May 22

  • recent feature idea were to implement tables
  • alternative feature idea would be to implement "Personal heroes", the heroes you liked
  • tried the latter, copy & paste & adapt

May 23


May 24

  • made first steps in Visual Studio Code, had not used it as IDE yet, got really popular at work for frontend development, even over IntelliJ
  • filtered list of heroes not displayed; debugging in Chrome shows that heroes is undefined
  • TODO: display list; write tests

May 25

  • cleaned commits to what is already working (without filtering for heroes that I liked)
  • tried to push, got error that translations are not configured correctly for spec file; lesson learned: run the tests first... -_-
  • found the culprit, fixed, now tests are passing
  • learned how git controls work in Visual Studio Code; yet lacking permissions to push
  • pushed again using IntelliJ UI, failed again due to quite cryptic message
    Push failed: 0% compiling�������������� 10% building 0/0 modules 0 active���������������������������������� 10% building 0/1 modules 1 active ...s! ...
  • using git push in command line finally revealed the prerequisites to push, like running tests in advance etc.; this explained why it took so long... and it worked in the end!
  • TODO: learn how to add authorization to VisualCode to be able to push from IDE as well
  • TODO: filter for heroes I liked only

May 26

  • paired with Mirjana Andovska
  • Mirjana already checked out my practice project and had a look how to filter for personal heroes
  • we found out that the live app URL https://www.angularexampleapp.com runs into a timeout (522) for her, yet does work for me although be both shared the same browser versions; she's located in Skopje, would be interesting path to investigate in itself (yet not now)
  • we shared our approaches how to filter for personal heroes, by using the Angular filters in the html or directly in the TypeScript component like it's also done on the home page; I showed I tried to use the filter function there yet no personal hero was listed; Mirjana had found that the value was always reset to false by logging, so the filter would work it just did not list any as they were set again to false
  • in the hero model the attribute personalHero was set to false whenever we fetched them; we could confirm this by adding simple console logs; for now we just used simple console logs, yet for proper logging we would use the framework used; Mirjana: "logging is like adding adjectives in an essay"
  • we changed the constructor's attribute value to and it was working!
    this.personalHero = hero.personalHero || false;
  • when testing this in different browsers we found that now not only any likes are stored in the global database, but seemingly also the personalHero flag; which we did not intend to, to not interfere with the global database but keep things local for practicing
  • we started learning more about Firebase and how to verify whether we actually stored it globally
    https://medium.com/factory-mind/angular-firebase-typescript-step-by-step-tutorial-2ef887fc7d71
    https://www.learnhowtoprogram.com/javascript/angular-extended/firebase-retrieving-data
    https://www.learnrxjs.io/operators/transformation/map.html
  • we found that we could log the values when subscribing:
    getHero(id: string): Observable<any> {
      const retrievedHero = this.afs.doc(`${AppConfig.routes.heroes}/${id}`).get().pipe(
        map((hero) => {
          return new Hero({id, ...hero.data()});
        }),
        tap(() => LoggerService.log(`fetched hero ${id}`)),
        catchError(HeroService.handleError('getHero', []))
      );

      const subscribe = retrievedHero.subscribe(val => console.log(val));
      return null;
    }
  • this way we could verify it's really stored in the global database; when looking at the tests, we found the same way was done for the mocked databases! Lesson learned: should have looked at the tests in the beginning :)
  • we reset all values by setting the flag to false again, and then re-implemented it using the local storage of the browser instead, setting a new entry for each hero we liked; we tested things out, it worked! we noted for later to change this store a list of ids instead to avoid creating new entries and save memory (https://www.taniarascia.com/how-to-use-local-storage-with-javascript/)
  • we wanted to have our feature covered in the tests as well; added expectations that a hero should be a personal hero after liking them; wanted to test the filtering as well; learned to add a new fixture for a different test setup
  • shortly investigated how to run a single test but then skipped this for later; UPDATE: as we're using Karma & Jasmine here, we can just focus on one test or suite by using "fit" instead of "it" or "fdescribe" instead of "describe"; f = focused, x = ignored
  • we cleaned up files for commit and tried to push; yet TSLint checks failed; we ran the tests but forgot to run about them! fixed them; then the push was successful :D
  • the scope of my personal challenge is now fulfilled, yet we identified next steps we could do to improve and extend the code to practice further:
    1. store the personal heroes ids in an array in the local storage
    2. add proper logging using the framework used
    3. write e2e tests for our new feature
    4. show the user which heroes they liked, either by adding an icon or not allowing them to vote again for the same hero and marking the heart icon gray
  • Retrospective:
    • Mirjana: normally it's a great thing to go to the tests first, can learn a lot from them; now we rushed ahead due to time, but would have been valuable as well
    • Mirjana: we had to be reminded of writing tests; interestingly this would be the first thing we as testers would remark, yet when developing we often stay inside our little box, this is why it's crucial to have someone with a different perspective looking at it from a different angle
    • Lisi: learned there's so much more to learn, there are so many more question marks now in my head as it usually is with learning and trying to puzzle all bits and pieces of knowledge together; thank you so much for sharing your knowledge with me, learned a lot in this session!
    • Mirjana this whole challenge idea a super cool thing to learn outside of our work's boundaries! Would like to create a GitHub account herself and contribute to the project or future ones, we could create pull requests and also learn so much by reading code from each other
    • Mirjana: you reminded me how to learn! use a small project to practice, and especially pair! Lisi: pairing helps me so much, it keeps me accountable and also together we always generated new ideas so we did not get stuck, or at least quickly unstuck again
    • Looking back, we paired for nearly 4h instead of the originally planned 1.5h! It was fun and super enlightening, and afterwards we could fully enjoy our evenings :)

What else?

The great news is: I fulfilled now the promise to myself to have at least 5 repositories published on GitHub. Even in 5 months! Still can't quite believe it. The next and final step: build an application from scratch which will serve as my proof of concept. I'm really excited. And that's not the only thing I'm excited about these days. These are busy days, great days, and especially exciting days!

Sunday, May 19, 2019

#CodeConfident: Spring PetClinic

My last weeks were super busy. As a result, I had to neglect my code-confident challenge and was feeling sad about it. I knew already knew for longer what my next practice project should be about: extending an existing backend feature. I found, however, that getting it started was a lot more difficult than I expected. When I finally could start, I got intrigued yet realized I need to learn a lot more. In the end, I did the biggest part just on one day as I couldn't let go anymore!


April 27


May 12


May 13


May 14

  • pairing session with Amitai Schleier
  • presented him my current problem, first lack of time and now stuck in researching projects trying to decide which one to work on
  • told him about my criteria and desired tech stack
  • started to present my latest list of 5 candidates
  • Amitai: likes to look at tests first to see if they are readable and to see what the app is supposed to be doing
  • after the first project he stopped me and suggested a project he just found by using Duck Duck Go search "open source spring-based application": Pet Clinic, a Spring demo project
    https://github.com/spring-projects/spring-petclinic
    http://projects.spring.io/spring-petclinic/
  • cloned the project
  • Amitai: let's try to run it first
  • ran it using the run configuration detected by IntelliJ; ran but did not find css
  • the readme showed how to run the app --> worked this time including building of css
    ./mvnw package
    java -jar target/*.jar
  • wanted to use IntelliJ and make it faster, found we could add the package step as Maven goal step before launch: "package"; tried out different variants, found we needed to keep the build step before
  • discussed general approach to tackle an existing app; I shared it depends what I am looking for, if I'm reviewing other people's code or if I'd like to contribute myself, etc.; Amitai: wants to see if he can quickly get something to change, see the cause and effect; he could read a lot and model and everything but rather prefers changing something as better test of understanding; wrote a tweet thread about cause & effect
  • we decided to change the pet picture on the welcome page to a different one; used this as valid reason to google for cute animal pictures ^^; replaced the image, replaced the image reference, verified the change got applied after application restart
  • before going further, we felt that packaging took too long as it was running all tests; wanted to comment them out, but could not find them in the pom; looked upMaven lifecycle (https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) and found that tests are included by default; found we can skip them by calling "package -Dmaven.test.skip=true"; startup now a lot faster, still a bit slow for actual fast feedback during development, yet doable
  • had a look at what the app already provided, like "find owner"; decided to add "find pets"
  • added a new menu item (copy & paste from find owners), restarted - nice, we land on the error page as expected
  • added a controller, copied over from owners; copied the owners html page, adapted as well; our "hopothesis" would have been that now we would be able to access a find pets page with a form to search for owners; yet we knew we probably missed something and indeed, we got the error page instead
  • we realized the relationship of owners and pets was not modeled parallel as assumed, but having pets subordinate to owners
  • Retrospective:
    • Lisi: thank you so much, you got me unstuck in a few minutes! Amitai: seems like my super power, as I have to always get myself unstuck: I know how to orient myself in my problem space, and know how to help people orient themselves in their problem spaces
    • Amitai stayed in the navigator role, Lisi as driver; both thought it went well, were not sure if it was okay for the other one but only addressed it in the end; Amitai: felt you picked up things, needed to instruct less and less, you already knew what I wanted; Lisi: when I want to learn, I try to keep myself on the driver seat; I also learn a lot as navigator, having to express my intent and decide where to go next, yet now it's about hands-on practice; Amitai: agree, it's always good to practice; agreed to switch roles next time
    • learned that copy & paste is not always working, we have to learn more; was a good reminder to think about the model and how we would want it to be; having pets subordinate to owners did not feel right; what if a pet changes the owner? We would not want to loose the record for the pet, or the past owners; also from a moral standpoint a partnership would be better
    • I will have to decide where to go next and define my scope for this practice project; Amitai: Gilded Rose is known as refactoring kata, but he likes to call it the "when to stop" kata; what's the cheapest thing you can do? It's about business, not about the cleanest code; it's really important to zoom out, zoom back in, zoom out again, and realize when to stop
    • Lisi: last session and this one as well I gained a lot of benefit from what you shared, bits and pieces of knowledge here and there, and especially from your approaches, how to tackle things; they work well for the concrete thing, but are also applicable in a generic way, will also help me later
    • Amitai: last time you gave me energy, happy to give it back this time!
    • agreed to do a third session end of June / July
  • TODO:
    • set up practice project
    • define scope
    • do it

May 15


May 16

  • tried to understand app better
  • need debugging to understand more
  • not much time today

May 18

  • debugging the owner controller: did not stop in debugger - why? still haven't found out; would be something to investigate in a pairing session
  • learned more about the demo project; https://projects.spring.io/spring-petclinic/ provided lots of info, however, for an outdated version
  • found the community built a lot more versions: https://github.com/spring-petclinic among them also one for Angular :) https://github.com/spring-petclinic/spring-petclinic-angular (could be the perfect target for my next challenge!)
  • learned more about MVC (Model View Controller): https://spring.io/guides/gs/serving-web-content/
  • saw our get mapping is a bit different, realized I need to look that up and learn more
  • learned more about Thymeleaf inputs https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#inputs
  • trying to adjust controller to have correct result collection for binding, adding results from search by first name to the results from search by last name https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#addAll-java.util.Collection-; assumed the resulting collection will contain duplicates --> assumption was correct! keeping fields empty to get full list is now showing duplicates; also, existing first name is still showing full list
  • https://www.geeksforgeeks.org/how-to-remove-duplicates-from-arraylist-in-java/ tried the Stream version and found it cannot be cast to a collection
  • used set instead of collection and it works! bye bye duplicates :)
  • found that when I provide values for both fields, search by first name does work now indeed! --> found I always list all in case one field is empty... o_O changed this to only show all in case both are empty --> still, one empty field will show the list of all owners
  • cases:
    • last name empty, first name empty => list all owners
    • last name exists once, first name empty => show owner details (does not work yet)
    • last name empty, first name exists once => show owner details (does not work yet)
    • last name exists multiple times, first name empty => list selection of owners (does not work yet)
    • last name empty, first name exists multiple times => list selection of owners (does not work yet)
    • last name does not exist, first name exists once => show owner not found (does not work yet)
    • last name exists once, first name does not exist => show owner not found (does not work yet)
    • last name does not exist, first name exists multiple times => show owner not found (does not work yet)
    • last name exists multiple times , first name does not exist => show owner not found (does not work yet)
    • last name does not exist, first name does not exist => show owner not found
    • last name empty, first name does not exist => show owner not found (does not work yet)
    • last name does not exist, first name empty => show owner not found (does not work yet)
    • ...
    • more cases:
    • both names exist, but for different records => show owner not found (now shows both records)
    • parameterless GET request /owners should still list all
  • feel the database query should already take care of filtering everything; implemented look up by full name for results list --> oh my it works!!
  • what about exact same full name, but different entries? should still list both entries --> and it does!
  • not flawless but worth to commit it :D
  • added tests for new controller feature; test for not existing first name fails, not sure why yet --> experimenting made me finally understand better what the "rejectValue" method does in the controller! added handling in case first name is not found; now error message is displayed twice! ^^
  • researched a lot more regarding Thymeleaf and error messages
    https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#validation-and-error-messages
    https://stackoverflow.com/questions/50005969/thymeleaf-or-operator-in-thif?rq=1
    https://spring.io/guides/gs/validating-form-input/
    https://teamtreehouse.com/community/where-does-thymeleaf-get-the-error-messages-from
    https://howtodoinjava.com/spring-mvc/spring-mvc-display-validate-and-submit-form-example/
  • found how to display an error for a specific field:
    <p th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}">Error</p>
  • however, wanted to have a combined message if an owner is not found, not separated per field; found how to add and display global error:
    • Controller:
      result.reject("ownerNotFound", "not found");
    • Template:
      <p th:if="${#fields.hasGlobalErrors()}" th:each="err : ${#fields.globalErrors()}" th:text="${err}">Global Errors</p>
  • downside: the test for the global error is super generic, did not find a way to test for exact error
    https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html
    https://blog.codeleak.pl/2014/08/spring-mvc-test-assert-given-model-attribute-global-errors.html
  • tested the tests, made them fail, added assertions; how to assert at least for the number of results found? haven't found an answer yet
  • still, the scope of this challenge is fulfilled for now, I implemented a small new feature :D can still extend it, improve it further and clarify the open questions when pairing with others

Friday, April 26, 2019

#CodeConfident: FizzBuzz

My previous challenges on my way of becoming code-confident felt too long. Granted, my Serenity Cucumber Practice (part 2, part 3) was my first challenge ever, and during Rest Practice I had a long period of travels. Still, right now I craved for a quick and simple challenge just to practice and learn just a bit more, not overdoing things. Last but not least, I wanted to go one level deeper regarding implementation and testing.

April 23


April 24

  • changed setup a bit to better suit the purpose
  • wrote test for second case, then wrote code to make it pass
  • agreed with myself that I will commit frequently, at least every time a new test is passing
  • had to remember to run test first, see it fail, then implement, run the test again, see it pass
  • baby steps and frequent commits (trying not to care about how elegant the solution is in the beginning as long as it's working) really helped get myself into a flow! Feeling I accomplish something and am on the right track
  • first implementation fulfilling requirements was done very quickly
  • personal observation: though doing quick commits (even when small) was at first still strange, it now felt a lot more natural to just create a repo and make several commits to it; was so scary in the beginning!!! A lot less already, can be proud :)
  • TODO: decide on what else to do, like reduce to required tests
  • TODO: finish challenge and seek the next one, this was meant to be a very small and short one

April 25

Monday, April 22, 2019

#CodeConfident: Rest Practice

My second #CodeConfident challenge is finally done! It was all about RESTful services. Here's my coding journal, as raw as it is.

March 3


March 4


March 5

  • decided to follow a tutorial to create own REST service, then test it with Rest Assured: https://spring.io/guides/tutorials/bookmarks/ This way I will not only learn how to use the library, but gain a deeper understanding how RESTful services are built
  • also, it's only one step further into the learning zone, as the tech stack is still familiar
  • set up base project using Spring Initializr; added Serenity and REST Assured dependencies; adapted license and readme files
  • created new GitHub repo, cloned it, committed base project, configured repo

March 6


March 9


March 11


March 12

  • pairing session with Amitai Schleier
  • we walked through the project, I explained my reasoning behind
  • Amitai: the build step includes test, that comes unexpected
  • found the included Gradle wrapper was not executable, marked it as such
  • we had to add the Lombok annotation to the classpath; this came unexpected, did not already come with the repo or Gradle; we deferred identifying the root cause here; was a great reminder to run a project locally on a fresh computer from time to time to see what's missing
  • Amitai: shared he would desire fast tests that can run without the app running, just triggered by a key stroke; however, this comes from the perspective of test driving an app, we're in a different context here
  • we learned that the extract method was not instantly comprehensible, not clear what it's doing
  • learned about fluent interfaces (see https://en.wikipedia.org/wiki/Fluent_interface); Amitai: they are nicely readable but might not be instantly comprehensible
  • we both shared concerns like: do we really need to have multiple given/when/thens in a test when we only want to test one action? How to make sure the deletion test really deleted the record, e.g. by calling it again? How can we declare the base path in a nice way at one place?
  • what to test for in which test? Amitai: in general he is thinking of what if this test fails, how hard do I have to think? When it goes red, how obvious is it what I have to do?
  • Amitai: uses the following principle when it comes to tests: make it work, make it right, make it fast
  • Amitai: using auto-format on save a lot; uses a plugin for Intellij: "Save Actions"
  • we committed several changes together throughout the session :)
  • we left TODOs in the code to make it obvious for any one else what's troubling and what is still worked on
  • learned several IntelliJ shortcuts (for MacOS): that were new to me:
    • cmd+9: toggle version control tool window; then cmd+D: on versioned file shows the diff
    • option+cmd+K: commit (& push)
    • option+P: push
    • option+Up/Down: extend / shrink selection
    • after test run, double-click on test lets us jump to the test
  • retrospective:
    • Amitai: already shared his feelings throughout; that was one key learning for him after all the coaching and pairing and mobbing: we don't have to wait to talk about it later, we can talk about it now
    • we were feeling the same pain; how much do we have to say to set up a test; it's a screenful and shouldn't be --> could improve it a bit by reformatting and extracting the test data setup in a separate private helper method (did so); this matters as a test should be so simple that we don't need a test for it; it's supposed to serve us
    • Amitai in general does like the given / when / then structure
    • learned about "TDD as if you meant it" as subcategory; implement class inside test until you come across the first business object (see https://cumulative-hypotheses.org/2011/08/30/tdd-as-if-you-meant-it/)
    • we shared similar concerns, like what does the test actually do, test the test, add assertion that content was actually deleted, multiple given when then steps, test setup, etc.
    • we didn't use a timer, pairing was fluent, frequently switched, quite natural; we both thought of addressing it but decided to give it a go and it worked well
    • I really learned a lot, curious to see how different people tackle different problems, which issues do they see, how they debug and find solutions; e.g. Amitai explored using code and the tests, would have used Postman rather as last resort to find out the behavior
    • love the hands-on approach, already improved things right now, have more pointers what to improve next
  • TODO: think about formatter, start using the plugin
  • TODO: build step includes test
  • TODO: see TODOS in the code ;)

March 12 (cont)

  • realized when summarizing the results from the coding session that pushing from my laptop revealed my work email address; and this time we pushed 3 times, so I could not only amend the last commit like I did before (see https://www.git-tower.com/learn/git/faq/change-author-name-email)
  • this time I had to rebase and edit the commits; above link showed how to do it:
    git rebase -i -p 4f72861fe2fbee02da716f3442cec263e762b4b6
    git commit --amend --author="lisihocke " --no-edit
    git rebase --continue
  • problem: I pushed and merged, and new commits had been created, but the old ones were still there!
  • rebased again and tried to drop these commits, but push did not do anything
  • learned I need to drop them and then force push to replace the remote repo with my local one, this finally did the trick and the concerned commits are gone; feeling relieved!
    git push -f
  • lesson learned, for the second time: be careful what you push..

March 18

  • pairing session with Toyer Mamoojee
  • walked him through the project, explained the reasoning behind, the targeted scope, steps taken so far, open questions
  • we agreed to review what is there for our first session and later have the option to try a different test framework and/or do performance/load testing
  • Toyer: first observation: usually we have test only one endpoint per file
  • naming conventions for tests: have to agree with the team on that, yet should be consistent; Toyer: test name should include what you are testing for, "getEmployee" feels not enough, better "getEmployeeDetails"; also, there's a mixture right now with using "get" for reading or receiving information and "create" for posting
  • Toyer: current test setup class might be sufficient for a practice project for now; would normally have the config in a separate file
  • Toyer: the smoke test looks fine; what they usually do is to additionally include a test for the structure, data types, i.e. including contract testing here as well already
  • Toyer: get first employee: are you sure this id exists? would extract it as constant; for test data setup they are using a separate database that can be queried, I could think about a catalog here; data should be built somewhere else to avoid duplication, in a different class generating the payload; building the payload might be more elegant as well, instead of adding properties I might create a map; creating it upfront to ensure independence makes sense; maybe can include randomizer here as well to detect more issues
  • Toyer: getting information out of the response becomes impossible when you have asynchronous APIs that only return a 200, then you have to query another system
  • Toyer: what else I could test for is that only 1 record is created instead of 2, checking the count of what comes back
  • maybe I could also check if the generated id is not null
  • Toyer: consider splitting tests based on risk; create itself might be crucial and working, only the details might be wrong
  • TODO: revise project based on suggestions

March 27


April 21

  • took up challenge again after a longer period of travels and conferences
  • removed superfluous semicolon (bothered me ever since I detected it and did not find the time to remove it earlier)
  • thought about running the Spring app together with the tests so you don't have to start the app in advance for the tests, like it's done for Restful Booker Platform; decided that this is out of scope for this challenge, would be interesting for a real app though
  • renamed request body to payload
  • potential for future: REST Assured can convert back to Java objects, don't need JSON
  • ran with coverage, however nothing found covered; learned I need to run the tests on the same JVM for it to work, see https://groups.google.com/forum/#!topic/rest-assured/pzBJQqtkvS0 and https://blog.jayway.com/2014/07/04/integration-testing-a-spring-boot-application/ also, need to run as JUnit not as Gradle task it seems
  • doing so I got the error "Error running 'EmployeeTests': Command line is too long. Shorten command line for EmployeeTests or also for JUnit default configuration." --> this fixed it: https://devis.cool/quick-fix/quickfix-intellij-idea-command-line-is-too-long-shorten-command-line-for/
  • still, no coverage found; assume I still need the same JVM; using the Serenity Runner cannot run in same JVM, also issues with SpringRunner
  • interesting post: https://medium.com/@manu.me/bdd-simplified-with-springboot-b56ffdcadb2b
  • did not work so far; also having bootRun as pre-step for test did not trigger tests; however: it's okay to not solve everything in this scope
  • stopped, started Test Automation University course by Bas Dijkstra that I wanted to do for so long already: "Automating your API tests with REST Assured" --> filled several knowledge gaps I had and was not aware of - awesome course!!
  • added checks for content type
  • this way found out how to test for the response content of plain text responses
  • observation: by distracting myself / getting my mind to focus on different but related things (the course) I could solve other issues I had before; was really worth it to "unstuck" myself
  • added test for updating an employee record
  • considering the challenge scope officially done; I'm up for the next challenge! :)

By the way...

First: I learned once again that others appreciate the idea of keeping coding journals as well for their own learning.
Second: I did not have to pause my code-confident challenge yet! I've now indeed continued playing a non-casual computer game at least once a week, and it feels great. Definitely worth following my passion and carving out time for it!

Third: My feeling is I have to speed up. Only two challenges of five completed, let alone my final proof of concept app.

Last but not least: I've been pretty busy the last weeks. The good thing: although I could not work on my personal challenges, I still practiced! I've attended Automation in Testing, TestBash Brighton and Mob Programming Conference. A lot was hands-on learning which I really appreciate. Also, I can't but share one of my absolute highlights with you! Thank you Angie Jones for your encouragement, you're the best!

Code-Confident at TestBash Manchester

Remember when I submitted to Test.bash(); in the last hour? Well, I did not exactly get accepted for this very technical format - yet they selected me for TestBash Manchester! Simply couldn't say no to that. So, I will have yet another challenge this year: craft a presentation out of my ongoing challenge. Already playing with some ideas in my head, curious how they will work out with an audience! :)

Monday, April 15, 2019

Mob Programming Conference 2019 - A Comeback

Remember my joy last year when I got invited to the Mob Programming Conference 2018 as a moberator for the first time? Imagine my joy when Woody Zuill invited me back again for this year's conference! Truth be told, I wholeheartedly hoped for this opportunity and booked my flights for the preceding TestBash Brighton accordingly, allowing me to fly to Boston shortly afterwards.

So, here I was, back in Boston, seeing so many lovely people again, and getting to know many more. It was a wonderful experience. Here's a glimpse into what happened.

Arriving

When I learned that Lennart Fridรฉn would be back on board, I was super happy. We met last year and had some great conversations together, already on the very first evening. This time we could continue, meeting for dinner on the evening for the conference. A wonderful way to get into conference spirit!

The Conference

The first day was kicked off by the amazing Linda Rising with her keynote "Experiments: the Good, the Bad, and the Beautiful". It's always a pleasure to listen to Linda's thoughtful and inspiring talks! She's a real master on stage, and a huge role model as well.
Afterwards it was my time to facilitate a mob session. This year I chose the topic of "Mob Exploratory Testing", evolving a workshop I gave both for another company on my last year's Testing Tour, as well as my own company just recently as a cross-team, cross-role, cross-location mob. It went well and also triggered many new ideas how to improve my mob sessions further. Mission accomplished!
After lunch it was time for a  lean coffee session. I found myself helping out as facilitator at a table full of co-workers. That really made me think how to encourage people better to spread out and learn from other people's experiences. I get why we prefer to stick together, and yet it feels like a missed opportunity at conferences. On the other hand: this experience proved again why a lean coffee session still makes total sense to have in your own company as well. People came from different teams and learned a lot about each other's challenges and solutions they had no idea about before.

For the afternoon I chose the mob session hold by Chris Lucian from Hunter Industries, where the "original" mob evolved. He introduced us to the "Mob Programming Roleplaying Game - A Powerful Learning Experience". It was developed by Willem Larsen and all material can be found on GitHub for people to give it a try themselves. What I really liked about it: the purpose is to show good behaviors in a mob and thus level up your mobbing skills.

The second day started with a great keynote by Karin Tenelius: "Learning from Self-Managing Organizations". What an impressive journey she is on for a long time now! Karin gathered lots of data why self-managing organizations area win-win for everyone. By the way: I loved the fact that both keynotes were given by strong, knowledgeable, inspiring women. True role models, again.
Next up I chose the mob session by Colin Snyder: "When The Mob Encounters 'The New'". He jumped in as replacement for Lisa Crispin and Stephen Vance who unfortunately could not make it to the conference and were dearly missed. I liked Colin's idea of learning something new together as I used this topic myself several times for mob sessions so far. Our little mob ended up in doing first steps in Pearl by doing a coding kata together. Paying nicely into my #CodeConfident challenge! ;-)

After lunch I was very tired, so I spontaneously decided to skip the open space and instead talk with Andrea Zuill and Lennart. What a wonderful, re-energizing and inspiring conversation! One thing that stuck with me after talking with Andrea, who is a children's book author and illustrator: Sometimes it takes a ton of sketches to get a character right. So draw many sketches quickly without trying to improve any of them; instead, instantly move to the next one. If sketches are too refined, they are not sketches anymore ;-) Wise advice and applicable to other areas of life as well.

The last session I chose was Scott Ford's "Mob Programming with Legacy Code". He used the Gilded Rose refactoring kata translated to many different languages by Emily Bache. A wonderful exercise I got first introduced to by Maaret Pyhรคjรคrvi's awesome talk at Selenium Conf India 2018. Alternatively, check out her blog post "Exploring Gilded Rose".

The Social Side of Conferences

I learn a lot from the content shared at conferences in talks and workshops. I learn even more when doing things hands-on together with other people. That's not everything, however. Often I take the most things away from the socializing opportunities offered by or evolving around conferences. Like the evening reception after the first day. Great conversations throughout the evening!
After the conference ended, many of us joined for dinner and the evening was full of inspiring talks as well.

That not being all, the day after the conference, Lennart accompanied me on my sightseeing tour through Boston. Loved it! By the way, in case you'd like to see photos from my conference travels, I've just recently started my own Instagram account. It's private as of now, yet feel free to request access.

To 2020!

The 2019 edition of the Mob Programming Conference came to an end. Yet there are already plans for next year being made! And we know one thing already. We need more moberators, meaning people who facilitate mob sessions, so we could offer more smaller ones to make the conference even more focused on hands-on practicing and learning with each other. If you have mob experience and would be up for facilitating, feel free to reach out to Woody! Or alternatively, Lennart. Or me, as it seems. Time will tell ;-)