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! :)

No comments:

Post a Comment