#ProductCon – Product Management Conference

This article was originally published by Rosa Acri on LinkedIn.

I attended the Product Management Conference hosted in London by the well-known Product School. I bet you’re wondering why I would even join such a conference. As a Scrum Master, I don’t need to know everything that happens in Product Management, right? Not really. I was curious. I wanted to understand more about how Product Lead Growth works. Thanks to my amazing colleagues, I got the opportunity to follow the whole conference online, despite it taking time out of my regular product work. I’d like to share my key takeaways with you and just in case you are wondering, I did not want to note down everything, but there were two talks that, for me personally, really stood out.

Yi-Wei Ang | Have Courage: How to Do the right thing as a (Product) Leader

Yi-Wei Ang – talabat (Chief Product Officer)

Yi-Wei Ang opens his talk with a quote: 

Best products come from teams that make courageous bets.” – Brené Brown

His words resonated with me because he shows that there is a way to be a great leader without falling into the conventional pit of the classic product manager.

Product Leaders are expected to have clarity and conviction even in the face of deep unknowns, but the answer always depends on way too many factors around the product.

Bad Habit: Fake it, till you make it. This often leads to giving answers you do not have.

Realizing how much power lies behind sharing uncertainty and having the courage to say “I do not have the answer” is a process and there are specific steps to achieve before that can happen:

#1 Be courageous

  • courage to not know the answer
  • courage to do the customer-centric thing
  • courage to be wrong (the best Product Leaders are willing to be wrong!)
  • courage to do something unconventional
  • courage to put the plug, be able to look at the product and the organization in the face and say this is not going anywhere
  • courage to not take shortcuts
  • courage to speak up and also say the ugly things that need to be said

All change that is so personal has to start from an individual. It’s a long journey, it starts with you and goes into the company’s culture.


#2 Work on yourself

  • check on your ego
  • be curious (” Curiosity kills cynicism” —> if you ask questions, it fights your need to be always right!)
  • build up your vulnerability muscle (the more you are vulnerable, the more it comes naturally to you)

#3 Work on your organization

  • it’s okay to be imperfect
  • encourage each other to jump (don’t be scared to open up possibilities)
  • be a role model for vulnerability (be open about your struggles, unpack them together with your team, and build trust)
  • never leave things unsaid

Repetition matters, when all of this becomes a norm, a learning culture that everyone enjoys working with will be the result of it.

There is no fake it till you make it. What kills vulnerability, is inauthenticity. Lean into the things that make you uncomfortable. That is what makes the journey worthwhile.


If you made it this far, thank you – but I am not done yet. There was another person, who inspired me even more, and let me tell you: I am always amazed by how much a woman can achieve, especially in a world, where we are still not 100% recognized for what we are capable of. Even more so when it comes to talking about inclusion and diversity in our work life.

Jessica Hall – Unleashing the Power of Inclusion: Empowering Teams and Building Products for all

Jessica Hall

The talk opens up with “There is far more power in diversity and inclusion than there is in risk”. It is a key part of driving innovation and a crucial part of business success.

  • at the heart of inclusion is a sense of belonging
  • the heart of belonging is a connection
  • inclusion takes practice, connection is a constant

“to feel like you are talking in one voice”

How do you start empowering your Teams?

Empathy reduces as rank increases

  1. It makes business sense, prioritize it

There is a consensus that diversity and inclusion improve innovation and financial results. We all know that innovation is what we want to achieve. It is also opening up to a wider customer base. You are opening yourself up to other perspectives. Implementing Closed Captions is an example. It is about all the people you can reach that you are not reaching today.

  1. It has to be lived to succeed

You can get all sorts of people to the company, but if you do not build a culture that includes all the voices, it won’t succeed. We need to open our eyes, get uncomfortable and experience other perspectives. We’ve got to challenge common societal stereotypes and question them. Challenge your perceptions.

  1. It has to be recognized

If we want to effect a change in the culture, if we want inclusion to just happen, to become a habit, we need to recognize it. Trying to build something that is part of what we do. If it is not part of our culture, we don’t have the engagement we want, and we do not have different voices that are heard.

And my favorite quote of the whole conference:

The world is becoming more diverse, and so must we.

Personally, I try to be the best Ally I can possibly be. At Mercedes-Benz.io I am part of the Diversity & Inclusion Team. We are always challenging current standards and ways to be more inclusive on many different levels.

I hope you enjoyed the insights, and I’d like to hear your thoughts and your opinions on how the culture around your company is handled and if there is any leader you work with that inspires you.

If you like to follow up on the whole keynotes, make sure to check out the Product School YouTube Channel. Here you can find Yi-Wei Ang’s talk and also Jessica Hall’s.

Source: Everything here is based on the two keynotes I followed during the ProductCon London on 20th February 2023.

Unsplash picture by Product School.

ASKING DEVELOPERS

Can you recommend INSPIRING books for software engineers?

“One of my favorite books is “The Phoenix Project“. It is not a technical book (so not really a programming book), but it’s rather about IT culture and DevOps. I liked it a lot because you can read it as you read any other kind of novel, and it shows you how IT can be compared to traditional processes in manufacturing. It also introduces you to “The Three Ways” of DevOps. On top, I would also include “Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations“. For more recommendations, you can check out this reading list: https://octopus.com/blog/devops-reading-list.  

Clean Code. It’s a bit older but a classic that shows how you easily write, read, understand, and change code. A lot of times people like to write complex code that only one person understands. Then other members of the team have to spend hours to understand it. In my opinion, it’s a mandatory book for any FE or BE developer.”

“I find “The Programmer’s Brain” very interesting. It’s basically about how our brain works and how we think about code.”

“If you’re a fan of “The Phoenix Project“, you should also read “The Unicorn Project” and of course “The DevOps Handbook“. I can also recommend “The C++ Programming Language” book.

“It’s not a programming book, but the concepts apply to broad system architecture: The 5th Discipline. A good one is also Gayle Laakmann McDowell’s “Cracking the Coding Interview“, for process it’s “Peopleware: Productive Projects and Teams” by Tom DeMarco, and if you want to learn about the Liveness in Jira, it’s “Java Concurrency in Practice“. My favorite chapter about programming is in the “Clean Code: A Handbook of Agile Software Craftsmanship” book. And let’s not forget the classics “Thinking in Java” and “Effective C++: 55 Specific Ways to Improve Your Programs and Designs“.

Picture from Unsplash by Fang-Wei Lin

6 Reasons Why You Should Enjoy Reviewing Pull Requests

This article was originally published by Raphael Marques on Medium.

Reviewing Pull Requests (PRs) can be a tedious and dull task, especially when you have other tasks on your to-do list. However, it’s also one of the most efficient ways to maintain the quality of your codebase, improve your knowledge, and help your colleagues.

Photo by Christin Hume on Unsplash

The key to making tedious tasks interesting is to have a good reason for doing them. That’s why I’ll give you six reasons why you should enjoy reviewing PRs:

1 — Help new joiners and junior members

Showing new team members how you maintain your codebase by reviewing their PRs can help them understand your practices and standards, the same happens for junior colleagues.

2 — There’s more than one way to solve a problem

Reviewing your colleagues’ PRs can provide you with new perspectives on how to solve problems. Even if their approach is not what you would have done, it can still be a valuable addition to your toolbox. Keep an open mind and be pragmatic.

3 — Avoid the “Looks good to me” (LGTM) mentality

Instead of just giving a quick LGTM comment, take the time to provide good feedback. Even if you think there’s nothing to improve, try to find something interesting to highlight about their code. If you find something wrong, be kind and straightforward, explaining why you think it’s wrong and offering potential solutions.

4 — Keep your Pull Requests small

Breaking down your code changes into smaller chunks will make it easier for your peers to review them. This approach will help you catch any potential bugs, code smells, or duplication. It’s collaborative work, so making it easier for everyone involved will benefit the team in the long run.

At first glance, it doesn’t make much sense, since “more code, more issues, right?” However, when we’re faced with a large amount of code to review, we tend to overlook important details, such as potential bugs, code smells, and duplication, which can make our PR reviews less effective.

5 — Review your own Pull Requests

Before asking for others to review your code, review it yourself. Take a break and come back to it with fresh eyes. Check for any unnecessary code, such as console.log or forgotten commented code. Highlight any decisions you’re unsure about, so the reviewer knows to pay extra attention.

6 — Take your time

Reviewing PRs requires careful attention to detail. Take it slow and read every line of code. Don’t hesitate to ask questions if you’re unsure about something. Remember, there are no stupid questions. The most important thing is to keep the codebase and the team sharp.

Conclusion

In conclusion, as mentioned before, reviewing PRs may seem like a tedious and dull task, but it is an essential part of maintaining the quality of your codebase and building a stronger team. By taking the time to review PRs thoroughly, you can help new team members, gain new perspectives, provide valuable feedback, and improve the overall code quality. This collaborative effort not only benefits the team but also contributes to personal growth by developing a deeper understanding of best practices and standards. Therefore, reviewing PRs should be an enjoyable and fulfilling task that is worth the investment of time and effort.

This article is written by Raphael Marques.

ASKING FRONTEND DEVELOPERS

What is your favorite tool / framework / language to work with as a Frontend Developer? 




I have to give credit to Visual Studio Code as my buddy tool to code, it’s easy to set up, fast, and has a bunch of cool extensions to work with. But of course, if we want something more robust I’d go to WebStorm.

With a vast range of programming languages is quite difficult to pick one, but I choose Javascript. Even though I code in Vue.js, my favorite framework is React.js, sorry Team 🫣.

Francisco Fialho

I’m going to go with Vue as my current favorite framework. I say “current” because in this fast-paced and always-evolving world, we never know what tomorrow brings, and I honestly believe we should always be open to change if we aspire to be good professionals. 

Vue is a front-end framework that is not only easy to learn but also extremely versatile. With recent versions, it is also very optimized for performance and DX (developer experience). The community is booming, and the ecosystem around it is expanding at light speed with Vite as the default bundler for Vue3 in the center of attention right now – and for good reason! Even more exciting changes are coming this year to Vue and I can’t wait to try them out.

Rodrigo Lima

Right now, it’s almost impossible to think of a way to code without VS Code and my extensions, especially the Source Control – which made me lazy and less fluent in GIT commands, but it is what it is. In terms of language, I live between JavaScript and TypeScript. When it comes to frameworks I would say Vue and React, but Vue is slowly getting my heart fully.

Raphael Marques

Absent: a Journey through Confidence in the workplace

It was 8 am, and I was getting all dressed up to go nowhere in particular. For the monitors of people, I don’t even know.  
How should I smile? How many teeth should I show?  
Lick my lips, and I’m creating a new story. I’m faking some kind of glory. 

All my professional experiences had different backgrounds and I expressed my artistic point of view in all projects I was involved in. Until I worked in a modeling agency as a photographer and videographer.I was so afraid of not having the space to be creative. Of course, this job came with the inherent package of being able to express my ideas, share new views and communicate all dissatisfactions by giving them a new solution. But I was hurt. 

I had been at the modeling agency for 3 years, and, over time, my confidence was broken. I started to feel more fragile, and more unprotected. I felt all my ideas and approaches were manipulated and compared to others. I felt they put a lot of trust in me, but then didn’t value my work. I felt like I was just another person capable of taking pictures. 

This lack of confidence consumed my body, brain, and words. 

My past was different from all this, and that is why I was always so nervous. I didn’t understand what they were talking about, so I just smiled to let them know I was comfortable in some way. 

Outside of the agency, my work was amplified. It was recognized and valued. But inside, there was a negative bubble that consumed me. I couldn’t be the creative and artistic David. I was just David – the machine. 

I fell out of love with photography and video. I didn’t want to do this anymore. I thought about going back to working in a supermarket because it was an amazing experience and I felt valued there. But now, I didn’t know how to do anything else. I was unhappy. The change was imperative.  

Once in thought, I was nonexistent, everything was normal without me. Just the way it was meant to be. I used to have some comfort and reward in being sad. My boat liked to drown.   

After a year of looking for alternatives, the opportunity arose to work at Mercedes-Benz.io, so I grabbed it with what little strength I had. I came in very damaged. I didn’t have confidence, so it was difficult to mark my position. My voice was still hoarse to speak, especially in a completely different area, in a much larger company. Before I had 12 colleagues, and now I have more than 500. My first thoughts were: I don’t have room to be vulnerable here. 


I have been here for more than one year now.  

David- you are part of the past, but now you are the future. 

Every expectation sits on all ten fingertips. How do you even grab one? 

I’m still learning, and above all, relearning. I’m not in a hurry. Every week has been different, and I have one of the most fun roles in the company. I have the opportunity to meet all the MB.ioneers, record them, and know them. It’s been the most incredible professional experience I’ve had. In addition to the confidence that I am developing (honestly, it suits me very well), I trust my team. We all flow very well, I can express my ideas and they respect them. Sometimes they don’t see them, but it’s fine. I’m an artist (hey- don’t judge me, I see myself that way), and artists don’t usually know how to express their ideas through words. 

I feel harmony working here. It’s great getting to know people that are the opposite of me. It creates the space for me to know other things outside of my bubble. There is a general empathy that contaminates me. We all realize that we are very different, and, at the same time, there is room for that difference.  

I’ve wasted too much breath on the pain that sometimes is difficult to breathe. Even when it’s all okay, even when all my colleagues tell me that I am doing a great job, even when I feel proud of everything that I am doing, and I created solid, healthy, and strong work relationships. I feel that right now, I belong here and I’m happy to feel alive.  

Now my boat wants to float on top. There is no more sense in suffering. 

It’s 8 am, and I’m getting all dressed up to go to the office, confronting my emotions on my way there.  
That’s why I wrote this. I’m glorious now.

Photo by Ruvim Noga on Unsplash

Improving an Existing Documentation Project (2 of 3)

Now that we know the current status of our documentation better (See Part 1), it is time to talk about our users. Why? Because we have created the documentation for them to be able to use our products, platforms, or tools.

But what do we know about our users’ needs? Who are they? We may all have assumptions about them. But in fact, we know nothing most of the time. A user survey is an excellent method to discover what our users perceive and use our docs, understand their current needs, and decide what to improve first. Read the following steps and learn how to prepare your user survey.


Step 1 – Design a User Survey

To design a user survey we need to know what to ask. But language is tricky so even if we are technical writers, we should double-check the survey’s questions with another colleague (and a UX designer, if possible).

About the following questions take them as a reference to create your own survey:

  1. In which team/product do you work?
  2. What is your role?
  3. How (un)familiar are you with the [Write your documentation name here] documentation?
  • Not at all familiar.
  • Slightly familiar.
  • Somewhat familiar.
  • Moderately familiar.
  • Extremely familiar.
  1. How often do you read the [Write your documentation name here] documentation?
  • Never.
  • From time to time.
  • A few times a month.
  • Monthly.
  • Weekly.
  • I don’t even close that tab.
  1. Which topics are you looking for in the [Write your documentation name here]?
  2. How (un)satisfied are you with the [Write your documentation name here] documentation?
  • Very unsatisfied.
  • Unsatisfied.
  • Neutral.
  • Satisfied.
  • Very satisfied.
  1. Please explain briefly why you are (un)satisfied with the [Write your documentation name here] documentation.
  2. How (un)useful do you find the [Write your documentation name here] documentation?
  • Not useful at all.
  • Not useful.
  • Neutral.
  • Useful.
  • Very useful.
  1. Explain briefly why you consider the [Write your documentation name here] documentation (un)useful.
  2. Do you bookmark the [Write your documentation name here] pages you need?
  • Never.
  • I only bookmark the topics I need.
  • I bookmark [Write your documentation name here] main topics only.
  • I bookmark the [Write your documentation name here] home page only.
  • Always.
  1. Please let us know to what extent the following statements apply to you personally:
  • When I need to find some information on a page, I make CTRL+F:
  • Never.
  • Rarely.
  • Sometimes.
  • Often.
  • Always.
  • When I need to find some information on the [Write your documentation name here] pages, I scroll:
  • Never.
  • Rarely.
  • Sometimes.
  • Often.
  • Always.
  1. How often do you use the [Write your documentation name here] page Search box:
  • Never.
  • Rarely.
  • Sometimes.
  • Often.
  • Always.
  1. Regarding the content of a page, what do you prefer?
  • A plain content structure – No tabs, no accordions. All the information is shown at once.
  • A plain content structure containing some visual elements and disclosing content progressively. 
  1. Which topics would like to find in the [Write your documentation name here]?
  2. If you were to make one suggestion for improving the [Write your documentation name here] pages, what would it be?
  • Better visual design.
  • Content should be more comprehensible.
  • Content should be easier to find.
  • Others (Develop your answer).

Acknowledgement: Thanks to Daniela Diener and Roksana Skryzcka for reviewing the initial survey.

Why These Questions?

Design your questions according to the topic you want feedback about for example: _user browsing behavior, page layout preferencesmissing topics, etc.

To know which type of feedback we are addressing with the sample survey of this page, read the following table:

Type of feedbackQuestion
Number
Explanation
Your users (role, team/product)1, 2Knowing the role, team or product of our users, helps us to identify:Our audience.Which role/teams are reading our docs the most
This information can lead us to develop role or team/product focused documentation, or address specific issues or lack of interest impacting the documentation.
Awareness by role, and team/product3, 4If our platform, toolset. product or project has a lot of people using it, checking the awareness level is a must to double check that our people know where to find the documentation they need, and that we have prepared for them.
Frequent of use3Anwers to this question will tell us if our documentation are being use and how much. Knowing this, we can take further actions to deepen the engagement, or reinforce it if the docs are not being checked frequently.
Topics of interest4Too many times we create the docs that we think would be of use for our users. This question will tell us if we are right, and which topics need to be revamped (or removed).
Level of (un)satisfaction5, 6A satisfied user is another word for useful docs (and product!). A low level of satisfaction gives us the chance to ask Why?, and find the source of that unsatisfaction.
Usefulness perception7, 8We can think that our documentation is useful but, again, our users will either confirm it or deny it. Another opportunity to improve.
Access point to our documentation9Sometimes we think that our users access directly our documentation typing the url in the browser. This question will tell us about the bookmarking habits of our users bookmark. With that in mind, we will have a better idea of the impacts of changing any page or section name taht could probably be bookmarked. Here, an effective and reliable communication strategy for changes is key.
Browsing and searching behaviors10, 11Browsing and searching behavior have a decisive impact on how we will design our pages, and which visual elements can be used.

For example, using collapsible elements may cause troubles to CTRL+F users that, for example, work with Chrome.
Reading behaviors10, 11, 12Same as previous topic.
Direct Improvements13, 14This is the open-air gold mine. Users will you what they want and see as a positive impact for the docs.

MS Forms

Use any survey creation tool that fits your needs. I used MS Forms because it was available and provided an easy way to:

  • Visualize the number of participants.
  • Provide different kind of diagrams to visualize the results of the questions.
  • Download the results in a consumable Excel format.
  • Easily share the survey.

Step 2 – Schedule the Survey

Scheduling the survey at the right time is as important as the survey itself. We are all focused on providing value to our projects and don’t want to get distracted.

So check in advance with the required roles (POs normally), the best date and time to run the survey.

If your users are not your teammates, Customer Support or an equivalent department may be the ones to seek.

When discussing the time for the survey, remember to:

  1. Share the objectives of the survey.
  2. Set the time available to complete the survey.
  3. Explain the importance and benefits of their collaboration.
  4. Ask them to request all team members to attend the meeting.
  5. Try to not interrupt their workflow.

Tip: For agile product development teams, including the survey during the daily or retrospective meeting seems the right time.

Step 3 – Survey Time

Don’t forget to introduce yourself during the interview and:

  1. Present the documentation improvement project: WhatWhy, and How.
  2. Explain the importance of improving the docs.
  3. Explain the structure of the survey.
  4. Release the survey!

To Be Continued…

What`s Next?

In the next article, we will analyze the results of the survey and highlight the most important of them. Are you ready?

API Testing with Java and Spring Boot Test – Part 2: Improving the solution

In the last part of this step-by-step, we created the project, set up the test framework, and also did all the configurations needed to run our API tests.

You can see the first part of the series here:

Let’s continue to grow our test framework, but first, we need to do some improvements to the existing code. In this guide, we’ll:

  • Refactor the object mapping (to be easier to handle with the JSON files)
  • Improve the response validations
  • Handle multiple environments inside our tests.

These changes will make our code base cleaner and easier to maintain for us to create a scalable framework of API tests.

Let’s do it.

Refactoring the Object mapping

We’ll take advantage of using the Spring boot Repository to separate the responsibility of mapping the objects (JSON) we’re going to use inside our tests. That way, we can do another step forward in our code cleanup.

So, first of all, we’re going to:

  • Create a new package called repositories
  • Then we create a new Class inside this package called FileUtils.

We’ll also take the opportunity to change the way we map the object to not be hard-coded but be in a proper resource file. That way when we need to change the test data, we don’t have to change the test but only the correspondent resource file.

package org.example.repositories;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.net.URL;

@Repository
public class FileUtils {

    /**
     * Read File and return JsonNode
     *
     * @param filePath
     * @return
     * @throws IOException
     */
    public static JsonNode readJsonFromFile(String filePath) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        URL res = FileUtils.class.getClassLoader().getResource(filePath);
        if (res == null) {
            throw new IllegalArgumentException(String.format("File not found! - %s", filePath));
        }
        return mapper.readTree(res);
    }
}

Show code in Github Gist

As you can see in the file above, we created a function to read a JSON file and then return the object already mapped – similar to the approach we had before in the test file.

Now, we’ll structure the resources folder to accommodate the JSON files.

In the resources folder, let’s create a new directory called user and then create a file to store the request body of the operation we’ll do.

{
  "name": "Luiz Eduardo",
  "job": "Senior QA Engineer"
}

Show code in Github Gist

After that, we need to update our test. Now we want to get the file data by using the new function we created for that purpose. The updated test will look like that:

package api.test.java.tests;

import com.fasterxml.jackson.databind.JsonNode;
import io.restassured.response.Response;
import org.example.repositories.FileUtils;
import org.example.services.YourApiService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.io.IOException;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

@ExtendWith(SpringExtension.class)
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class ApiTest {

    private final YourApiService yourApiService;

    public ApiTest(YourApiService yourApiService) {

        this.yourApiService = yourApiService;
    }

    @Test
    public void testCreateUser() throws IOException {

        JsonNode requestBody = FileUtils.readJsonFromFile("user/createUser.json");

        Response res = yourApiService.postRequest("/users", requestBody);
        assertThat(res.statusCode(), is(equalTo(201)));
    }
}

Show code in Github Gist

Much better! By keeping the code cleaner we are helping our future selves with its maintenance – trust me, you’ll be very glad to see this.

Improving the response validation

Great! Now, let’s have a look at the response validation.

In some cases, we want to check the full response body – or at least some parts of it – to fulfill the test requirements.

To do that, we’ll create:

  • A new Repository to abstract the responsibility and help us check the full JSON response body
  • A function to handle the check of the JSON response.

We’ll also add the “jsonassert” dependency to assert the JSON.

The pom.xml file will look like that:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>api.test.java</groupId>
    <artifactId>apitest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>api-test-java</name>
    <description>Api Tests</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>1.10.0</version>
        </dependency>

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>5.3.0</version>
            <exclusions><!-- https://www.baeldung.com/maven-version-collision -->
                <exclusion>
                    <groupId>org.apache.groovy</groupId>
                    <artifactId>groovy</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.groovy</groupId>
                    <artifactId>groovy-xml</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-schema-validator</artifactId>
            <version>5.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.skyscreamer</groupId>
            <artifactId>jsonassert</artifactId>
            <version>1.5.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.9.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.9.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Show code in Github Gist

The newly created ResponseUtils class will be something like this:

package org.example.repositories;

import com.fasterxml.jackson.databind.JsonNode;
import io.restassured.response.Response;
import org.json.JSONException;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;
import org.springframework.stereotype.Repository;

@Repository
public class ResponseUtils {

    public static void assertJson(String actualJson, String expectedJson, JSONCompareMode mode) throws JSONException {
        JSONAssert.assertEquals(expectedJson, actualJson, mode);
    }

    public static void assertJson(Response response, JsonNode expectedJson) throws JSONException {
        assertJson(response.getBody().asString(), expectedJson.toString(), JSONCompareMode.LENIENT);
    }
}

Show code in Github Gist

The next step should be to use this new function and improve our test. To do that, we’ll configure a GET request on YourApiService and return the full Response object. Then we should be able to check the response body.

public Response getRequest(String endpoint) {

    return RestAssured.given(spec)
        .contentType(ContentType.JSON)
    .when()
        .get(endpoint);
}

Now, it’s just a matter of adding the test case to the ApiTest test class and using the same strategy of letting the JSON response file be in its proper directory. Finally, we’ll have something like this:

@Test
public void testGetUser() throws IOException, JSONException {

    Response res = yourApiService.getRequest("/users/2");

    JsonNode expectedResponse = FileUtils.readJsonFromFile("responses/user/specific.json");
    
    assertThat(res.statusCode(), is(equalTo(200)));
    ResponseUtils.assertJson(res, expectedResponse);
}

Quite easy to understand if you just look at the test case 🙂

Executing the tests over multiple environments

Now we have the tests properly set, and everything is in the right place. One thing that could be in your mind right now is: “Ok, but I have a scenario in my product, in which I need to run my test suit over multiple environments. How do I do that?”.

And the answer is – property files.

The property files are used to store specific data which we can use along our test suit, like the application host, port, and path to the API. You can also store environment variables to use within your test framework. However, be careful, since we don’t want to make this information public. You can see an example in the lines below.

With Spring boot, we take advantage of using the “profiles” to set the specifics of the environments our application has, and make them available as spring boot profiles.

So, let’s do that. Inside the resources folder, we’ll create a new file called application-prod.properties to store the values of the production cluster of the test application. The file will store something like this:

apitest.base.uri=https://reqres.in
apitest.base.path=/api
apitest.token=${TOKEN}

Now, the only thing missing is to change our service to get the values stored in the property file.

To get the values from the property files, we’ll use the annotation @Value. This annotation will provide the values from the properties we set in the application-prod.properties file.

**Bear in mind: ** You’ll need to set the environment variable before using it here. The @Value annotation will grab this value from the environment variables you have set.

The updated version of YourApiService class will look like this:

package org.example.services;

import com.fasterxml.jackson.databind.JsonNode;
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Slf4j
@Service
public class YourApiService {

    @Value("${apitest.base.uri}")
    private String baseURI;

    @Value("${apitest.base.path}")
    private String basePath;

    @Value("${apitest.token}")
    private String myToken;

    private RequestSpecification spec;

    @PostConstruct
    protected void init() {

        RestAssured.useRelaxedHTTPSValidation();

        spec = new RequestSpecBuilder().setBaseUri(baseURI).setBasePath(basePath).build();
    }

    public Response postRequest(String endpoint, JsonNode requestBody) {

        return RestAssured.given(spec)
            .contentType(ContentType.JSON)
            .body(requestBody)
        .when()
            .post(endpoint);
    }

    public Response getRequest(String endpoint) {

        return RestAssured.given(spec)
            // In our case, we won't use the "token" variable, as the API doesn't require so.
            // But if your API require, here you can use the token like this:
            // .auth().basic("token", myToken)
            .contentType(ContentType.JSON)
        .when()
            .get(endpoint);
    }
}

Show code in Github Gist

That’s a great step up. This way, if you have multiple environments in your setup, you just need to create another application-YOUR_PROFILE_NAME.properties.

Executing the test suit

You must be wondering: How do I run the test suit with this newly created profile?

The answer is simple, just execute mvn clean test -Dspring.profiles.active=prod.

By default, if you just run the mvn clean test command, Spring Boot will try to find a file called application.properties and automatically activate it.

Now we have significantly improved the test setup of our application by:

  • The refactoring of the Object mapping to clean up our code and apply some best practices
  • Improving the response validation by adding a new dependency and using it to simplify the check
  • Learning how to handle multiple test environments. This should be useful when it comes to companies that have layers of environments before the code reach production

Are you curious about the article? Building a Java API test framework part 3 will further improve our application. We will then go deeper into the following topics:

  • Test reporting with Allure reports
  • Configure a CI pipeline with GitHub actions
  • Publish the test report on GitHub pages

(Image by Mohammad Rahmani on Unsplash).

Inspiration and topics discussed in our MB.io tech community in January

Also in 2023, we would like to share with you the news that is being discussed in our tech communities. You will surely find some inspiring topics.

Framework or not

Write reactive components without frontend frameworks. Should you be using a framework or not? Here at MB.io, we’re always taking a serious look at this topic. Let’s put the hype aside for a moment. You can write reactive components without relying on a frontend framework. Frameworks provide a more straightforward way to write web apps. React, SolidJS, Svelte, and Lit all offer this. The article explains the features and how the various frameworks works, as well as the associated costs.

Get rid of Pre-commit hooks

This video has met with much agreement from our developers. Pre-commit hooks block frequent code commits of intermediate work. This blocks productivity on the developer’s machine. It is better to run tasks on the server where you check for general linting rules or similar. The pull request serves as your final quality gate.

CSS pseudo-classes

The browser support for the new CSS pseudo-classes has risen sharply in the year 2022. It’s time to look at their benefits. Kevin Powell explains them in an insightful way in his video. Covered are :is(), :where() and :has(). Using these makes writing rules easier, and more manageable. It also changes how specificity behaves.


Chrome DevRel Team top Core Web Vitals recommendations for 2023 In the new year, have the resolution to make your websites more pleasant to use for your users and work on the performance. The Chrome DevRel team answers this question in the article: “what are the most important recommendations we can give to developers to help them improve performance for their users? They name the most important levers with explanations and suggestions for implementation.


SVG Reference

If you want to learn more about SVGs and their possibilities, have a look at this Interactive SVG Reference. You can learn what and how to implement it. After going through it, take a look at the collection of color tools and free SVG generators.


input type=”number”

This article follows an interesting discussion of the input type=”number”. In a detailed explanation of the problems, which the use of the input type number brings with itself, you learn which things you must pay attention to.


Just

Just, a Command Line toolkit for developing Spring Boot applications With features like Live Reload, Docker support, and with a single command, you can run anything. It’s worth a look.


Articles from Mb.ioneers

Our colleagues have also been active in writing articles recently.

Javier shares with us the first part of his article series on improving documentation. Read it, get inspired, and improve your product documentation in a structured way.

Miroslav shares his experience of switching to Raycast and how it boosted his productivity.

In addition, Vladimir has written an article about Microfrontends with Import Maps.

Thanks to all who share their knowledge in our company in this way and use our communities to exchange ideas. Stay curious!

(Image by Theo Eilertsen Photography on Unsplash).

Improving Your Development Documentation Project (1 of 3)

What this article covers
First steps on how to improve an existing documentation project.

Tools
Confluence, GitHub web and desktop versions, and MarkdownPad2.


Introduction

Developer Documentation is a curated set of files describing all the active workflowssetupstoolsconventionsbest practices, and How-tos of your software development product. Through this article, I will refer to it as “documentation” or “docs”.

Documentation supports your team members in their daily and future developments. It also helps new joiners to reach cruise speed during the onboarding period. But to do so, your documentation must be up-to-date and well-structured.

Keeping the docs up-to-date and in good shape requires resources and dedicated time. Yet often our project time or budget constraints prevent us from taking care of our docs properly.

This series of articles aims to serve as a documentation improvement guide.

Know Your Ground

Step 1 – Organize Your Improvement Project

Developer documentation has to be visible to increase the chances of success, and to find collaborators (to improve it). To do so, keeping a space to visualize, describe and track your improvement project is a useful idea.

Use your teams/company collaboration tool for that purpose. For this article, we’ll be using Confluence.

Space Structure

The structure of an improvement project may differ from one project to another. Take the following space structure as a reference that you can adapt to your needs (then iterate!):

Space NamePage NameChild PageDescription
[Your Documentation Project´s Name]Name of your documentation project.
OverviewExplain briefly the What, Why and How of the documentation.
DashboardCentralized page to easily access all project pages.
AnalysisMedia and results of documentation analysis.
RoadmapVisualization of the estimated dates to implement each improvement.
Improvement ProjectCommunication GridContact person by topic.
Improvement PlanImplementation phases and items.
Coordination MeetingsGrid to align with your manager or collaborators (Optional).

Once your improvement project space is set up, you are ready to:

• Present it to all your team members, including Product Owners and Scrum Masters.
• Track and show your progress.
• Visualize documentation issues/blocking points.
• Access all your project resources.

Tip: Explain how documentation issues negatively impact teams´ performance. It will help Product Owners and Scrum Masters to understand and provide your project with the resources you need.

Step 2 – Identify Your Documentation Issues

Identifying your documentation issues means spotting all the types of issues living among your docs. Some documentation issues are:

• Grammar, spelling and syntax errors.
• Confusing/Not logical page structure.
• Unclear/Verbose text.

In the following table, you can learn a little more about the main documentation issues:

Documentation IssueFix strategy
Grammar, spelling, syntaxUse a text checker to support your writing. Some good options are GrammarlyHemingway or QuillBot.
Page structureReview your page structure. It shows the logical flow of the information contained according to the objective of the page, for example: IntroductionPrerequisitesFirst StepWorking with…/Available Features.
NamingDefine a naming strategy for page titles, sections and subsections.
Page elementsStandardize the use of the following elements: lists, tables, tabs, notes, collapsible elements and images.
Text unclear or too verboseBe concise.
Random text formattingStandardize the use of bold and italics for files, folder names, code snippets and code elements (functions, objects, methods, parameters, API names, etc.).
Too many topics on a single pageStick to “One topic per page”.
Unnecessary screenshotsUse screenshots or images ONLY when strictly necessary. If you can explain it briefly, do not use screenshots.
Type of notesStandardize each type of use case for notes (Info, Help, Warning, etc.).

Now we can start to target and record the issues of our documentation. The following table will help you to perform that task:

Nav OptionPageSectionSubsectionIssueLink
Add nav. option namePage numberSection nameSubsection nameIssue name

Depending on the size and complexity of your documentation, targeting these basic issues may take a while. Take the chance and join me on the journey to better documentation and improve your documentation project now.


To Be Continued…

What’s Next?
In the second article (2 of 3 article), we describe how to run a user survey to gather useful feedback from your users/readers. This invaluable feedback will help us prioritize the documentation issues to fix first.

Productivity series: Spotlight replacement

Introduction

Continuing with the theme of my previous article (sharing my MacOS menubar setup), I’d like to show you how I used Spotlight and why I replaced it with another tool. The app is called Raycast and it’s a real productivity swiss army knife.

It does everything Spotlight does plus some built-in features like Clipboard History, Snippets with text expansion, bookmarks search, calendar agenda, timers, reminders, convert units, math, etc. But it also has an Extension Store, where you can download community-contributed extensions/integrations. At the end of the article, I will share a few that I’m using.

If you are new to macOS or don’t use Spotlight, let’s see why the omnipresent search bar is powerful.


Why Spotlight is great

Spotlight is a system-wide desktop search feature of Apple’s macOS and iOS operating systems

You can open it via CMD + Space shortcut keys.

I used Spotlight mostly for opening and switching between apps. There are many ways to do just that, but I don’t know any faster way than hitting Cmd + Space and typing in the first letter of the app and hitting Enter.

My macOS dock is always set to hide, not to take that precious screen real estate on small laptop screens. And when you train (by using) Spotlight what each search letter opens, I don’t see why anybody would use Dock, or Mission Control to switch apps.


Moving away from Spotlight to Alfred

I felt one could do even more from this powerful input box so I stumbled into Alfred.

Alfred comes with a Clipboard manager, bookmark search, custom web search, etc. However, those are premium features, and it costs ~40€ to get those.

Next to that, as powerful as it is, Alfred looks like outdated software.


Here comes Raycast

After some searching, I found out about Raycast, and for a shortcut person like myself, it blew me away 🤯.

Out of the box, it does everything mentioned tools do and then some. But unlike them, it has a built in Extension Store, where you can install various community-contributed extensions.

You get all that completely free for personal use. See more about pricing plans on their website.


Features I use the most

I will go over some of the built-in features I use the most and will end it with a couple of extensions I installed myself.

Open or switch to any app quickly

When you type in the Raycast input box, it will remember which result you used with that query. This is how you train Raycast to be more relevant to you.

For example, I use one-letter shortcuts to open many apps. To open Outlook, I press o, to open Chrome, I press c, to open Visual Studio Code, I press vs… When your result is highlighted, press Enter and the app will open/focus.

Clipboard history

Remember how many times you copy something, and you need to paste it again, but now your clipboard contains different content, so you can’t paste.

Clipboard History saves what you have copied and if you need to paste it again, you press a shortcut key to open Clipboard history and search what you want to paste or use your keyboard/mouse to navigate to an item and paste it directly.

It's a screenshot from the clipboard history of the author of this article on Raycast.

In this extension settings, you can configure a custom keyboard shortcut to show the Clipboard History window at any time. I use CMD + Shift + V. Notice how the usual paste with CMD + V still works like before.

To configure a global hotkey for an extension, open Raycast and then CMD + ,to navigate to Raycast Preferences. Follow the steps from the screenshot to get an overview of extension settings and change them to your liking.

As a software developer, I use Jira a lot. With that comes a lot of copying and pasting of Jira issue numbers. Some nice people share links to tickets, and some others, just use ticket numbers as plain text. To be able to navigate to that ticket in Jira quickly, you can use Quick Links.

You do this by defining a custom URL and the dynamic part of it. So when you paste something in that dynamic part, it will open that link in your browser. Optionally, you can give an alias to your Quick Link for easy and quick access.

In the end, this looks like this:

• Copy issue number
• Press CMD + Space to open Raycast
• Press j (for Jira)
• Press space to focus on the dynamic part of the URL
• Paste the issue number
• Press Return key to open it in a new browser tab

Make sure to check out extension settings and adjust them to your needs.

Opening bookmarks

On any given day, I open vast amounts of the same websites, eg. Jenkins jobs for builds and deployments, production Jenkins jobs, specific pages in Confluence, GitHub, team calendar in Confluence, and the list goes on and on.

Sure, one could use the browser bookmarks bar, but that requires using the mouse and clicking more than a few times just to open one page.

When you use the Search browser bookmarks extension (to which you assign a nice alias eg. b), then all you need to do is:

• Open Raycast prompt (CMD + space)
• Press b (alias for browser bookmarks extension)
• Press space and start typing
• Press Return key when your result is highlighted

Notice how you can bookmark any different page in Jenkins, so you have very quick access to those pages, without the need to navigate using the mouse or manipulating URLs. Once you give meaningful names to your bookmarks, opening them is super fast.

Snippets

If you find yourself needing to type something repeatedly, eg. some code snippet, URL, greeting, full name, date, etc. this one is a true time-saver. I started using a global text replacement tool called Espanso some time ago, but I didn’t find it working reliably. What was cool about it, it would replace predefined shortcut text eg. :br with Best Regards as you type.

But since Raycast can do the same, I just uninstalled it and configured my shortcuts using Raycast snippets.

For example, to open our INT environment, I type in the URL bar :int and this expands to a snippet I have defied in the snippets collection.

I am pretty sure you type in your email at least once a day. If you have a long name, you can configure a snippet for your email. By giving it a shortcut it is easy as:

• Focus on any input field or text editor
• Type :mail
• Raycast will automatically expand that to your email.

Snippets are even more powerful than that. You can even configure parts of the snippet to be dynamic, eg. dates and time, and even where to place the cursor.

One snippet I use a lot is to access a deep object in the Redux store. For that, I have shortcuts eg: :pal and this expands to someStore.store.store.getState()['SOME_OBJECT'].

Notice how much typing that saves.

Rest of the extensions

There are many more extensions to be discovered and used in the Raycast extension store.

With Raycast prompt open, type Store and install the ones you find useful. Or just navigate to the website and browse over there.

I can recommend: Reminders, Timers, Window management, One ThingDepcast, Brew, Kill process, etc… or just doing a prompt like: 1m to in, or 34usd to eur.

In conclusion

I can not possibly cover all the features of Raycast in one blog post. However, I hope I have shown you a new tool to be added to your arsenal should you like it.

For me, it makes mundane daily tasks a bit more fun and quicker to do. And since Raycast can do so much, it made me uninstall many other apps and simplify my setup.

I hope you had fun reading. Now go explore Raycast and let me know which are your favorite features.

Don’t forget you can type raycast in Raycast prompt. There is a handy Walkthrough feature 😉