Search by labels

Tuesday, April 15, 2025

Test Management Without Bureaucracy

 🧭 Test Management: Transparency Without Bureaucracy


The goal of test management isn’t paperwork — it’s transparency.

A good process should make the QA effort visible, showcase product quality at any moment, and help the team share knowledge efficiently.

But when it turns into bureaucracy, it fails its purpose.


🎯 The Real Value of Test Management


Done right, test management helps the team:

• See where quality stands — instantly.

• Understand testing progress and risk.

• Reuse knowledge and learn from the past.

It’s about visibility and collaboration, not about filling out endless fields or updating spreadsheets.


⚙️ Keep It Lean


• Don’t overdo documentation. You don’t need a test case for every ticket. Thousands of unmaintained tests become noise.

• Pick the right tool. Integrate QA into the same system developers use. Avoid silos.

• Automate updates. Connect your pipelines and test suites so reporting happens automatically.


🚀 The Outcome


When test management is lightweight, integrated, and automated, it enables:

• Faster, more confident releases

• Clear insight into product quality

• A shared understanding of risk and coverage

If it feels like bureaucracy, simplify it.

Because the real job of test management isn’t to manage tests — it’s to enable quality at speed.




Monday, December 9, 2024

QA Misconceptions

 🚀 QA is not the boogeyman of software development


Too often, Quality Assurance is misunderstood as the gatekeeper that blocks releases, the “bad guys” who say no until they stamp an approval. But that’s not what QA is about.


✅ QA is not bureaucracy


It’s not about maintaining endless checklists or executing test cases mechanically. It’s about delivering working software to the customer with just the right balance of coverage and traceability.


⚙️ QA is not a silo


Think of QA as one of the gear wheels in the complex system of software delivery. If developers don’t finish their work, the team fails. If QA doesn’t finish testing, the team also fails. Success or failure is shared — and that’s why collaboration matters more than handoffs.


🔍 Testability matters


If a task that should take hours turns into days because the product is hard to test, that’s not just QA’s problem — it’s a recipe for failure for the entire team. Testability must be considered from day one, just like scalability, usability, or security.


⚖️ QA is about risk, not perfection


Quality Assurance is about constantly weighing risks, not chasing an impossible bug-free ideal.

- Is it worth delaying a million-dollar feature because of a minor bug?

- Should we block a release to do performance testing for an app with only 10 beta users?

Sometimes, the smart move is to release and hotfix later. Other times, the risk is too high. QA’s role is to help the team make those decisions consciously and responsibly.


🤝 In the end, QA is not here to block. QA is here to enable delivery with confidence.




Friday, July 21, 2023

Spotless Code Formatter

Clean and formatted code is maintainable code.

Spotless is a popular tool that can format code in any programming language out there (Java, JavaScript, Python, C#, TypeScript, etc.) using any build tools. (Gradle, Maven, etc.)

In this tutorial we will look into integrating it in a Java project built with Gradle. In order to do this, we just need to add and configure Spotless in the build.gradle file in 3 easy steps:

1. Add the Spotless plugin:

plugins {

    id "com.diffplug.spotless" version "6.19.0"

}


2. Configure the formatting jobs:


spotless {

    java {

        googleJavaFormat() // format the code in Google Java format

        importOrder() // order the imports

        removeUnusedImports() // remove the unused imports

        formatAnnotations() // format the annotations

    }

}


3. Trigger Spotless automatically when the project is compiled:


tasks.withType(SourceTask) {

    finalizedBy 'spotlessApply'

}


Worth mentioning is that Spotless also offers additional features like automatic refactoring of the Java code using cleanthat().


Thursday, September 15, 2022

The Penny Game

Or why when embracing Agile, individual productivity decreases, but the team's productivity greatly increases.



Monday, June 27, 2022

Automating E-Mail Test Cases When Using Twilio SendGrid

   SendGrid is a customer communication platform for transactional and marketing email, which boasts an impressive client portfolio with big names like Uber, Spotify or Booking.com.

   Let's look into automating a simple test scenario that will check if new users that sign-up for a test application will also receive their welcome e-mails. 

   The presented small test suite only details the e-mail verification part, as the sign-up part can be done in multiple ways - UI action, API call, etc. and is application specific. 

   The test case uses the RestAssured Java library with a previously created API key to call the SendGrid API and check for the e-mail event of interest.

@Test

@Order(0)

void signUp(){

// perform user sign-up

}


@Test

@Order(1)

void verifySendGridEmailEvent() {

    sleep(asyncWaitingTime); //it is an async process so waiting time has to be allowed


    given().log().method().log().uri().header("Authorization", "Bearer " + sendgridApiKey)

            .when().get("https://api.sendgrid.com/v3/messages?limit=1&query=to_email=\"" + emailAddress + "\"")

            .then().statusCode(200)

            .body("messages[0].subject", equalTo("Welcome to Going T-Shaped!"),

                    "messages[0].from_email", equalTo("no-reply@goingtshaped.blogspot.com"),

                    "messages[0].to_email", equalTo(emailAddress), // the e-mail address from the previous sign-up test

                    "messages[0].status", equalTo("delivered")); // e-mail accepted at the receiving server


    System.out.println("Welcome E-mail event correctly retrieved from Sendgrid for user " + emailAddress);

}


   So a quick and simple way of making sure that users are not missing any important e-mail communications due to unforeseen bugs. The above test case can be easily adjusted for any types of e-mails just by switching the verified attributes, e.g. e-mail subject from "Welcome to Going T-Shaped!" to "Forgot Your Password".

Friday, March 19, 2021

How To Begin Your Presentation with Simon Sinek

  • Start with a story - let the audience know why and what are you presenting.
  • Present with the desire to give, not to sell - engage your audience by sharing your ideas without making it transactional.
  • Leave the credentials, facts and figures for the latter part of the presentation - this information goes to the Neocortex which has little to no influence in motivating your audience to be fully engaged with your presentation.
 

Monday, February 15, 2021

Test Automation for REST & GraphQL APIs

Backend test automation, the middle layer of the Testing Pyramid, is an area that no efficient test automation strategy should overlook. It's quick, it's stable and luckily with the use of specific Java libraries, it's also easy to implement.

This article will present a Backend test automation framework built with JUnit 5, REST Assured and a specific library for GraphQL file manipulation.

Project structure and setup

As it is a Maven project, all the needed libraries can be easily imported through the POM file.

Two helper classes are also needed:

  •  one for preparing the GraphQL payload, that can be checked here and is shown below:

public static String prepareGraphqlPayload(Map<String, String> variables, String queryFileLocation) {
        File file = new File(queryFileLocation);
        ObjectNode objectNode = new ObjectMapper().createObjectNode();
        for (Map.Entry<String, String> entry : variables.entrySet()) {
            objectNode.put(entry.getKey(), entry.getValue());
        }
        String graphqlPayload = null;
        try {
            graphqlPayload = GraphqlTemplate.parseGraphql(file, objectNode);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return graphqlPayload;
    }

  • one for preparing the JSON object that can be checked here and is shown below:

public static JSONObject buildJsonObject(String location) {
        JSONParser parser = new JSONParser();
        JSONObject jsonObject = null;
        try {
            jsonObject = (JSONObject) parser.parse(new FileReader(location));
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

Specifying the APIs and test data

The APIs under test will be:

As test data, we need:

  • for the GraphQL API:
  1. the Pokemon GraphQL query file
  2. the list of Pokemon and their attributes as a .csv file


Writing the test scenarios

  • The GraphQL test class can be checked here and the main test is detailed below:

@ParameterizedTest
@CsvFileSource(resources = "/graphql/pokemons.csv", numLinesToSkip = 1)
void testGraphQL(String id, String pokemonName, String weight, String height) {
        RestAssured.baseURI = "https://pokeapi-graphiql.herokuapp.com";
        Map<String, String> variables = new HashMap<>();
        variables.put("number", id);
        String graphqlPayload = GraphqlUtil.prepareGraphqlPayload(variables, "src/test/resources/graphql/pokemon.graphql");
        given().log().body()
                .contentType(ContentType.JSON)
                .body(graphqlPayload)
                .post("/graphql")
                .then()
                .statusCode(200)
                .body("data.pokemon.name", equalTo(pokemonName))
                .body("data.pokemon.weight", equalTo(weight))
                .body("data.pokemon.height", equalTo(height));
        logger.info("GraphQL request successful for " + pokemonName);
    }

Although a test scenario for a GraphQL API, the REST Assured library can be easily used and we can take advantage of its straightforward features for making the initial setup, executing the request and verifying the returned data.

  • The REST test class can be checked here and the initialisation step and first test case are detailed below:

    @BeforeAll
    static void initialize() {
        RestAssured.baseURI = "https://petstore.swagger.io/v2";
        petCreatedJson = buildJsonObject("src/test/resources/rest/pet_created.json");
        petUpdatedJson = buildJsonObject("src/test/resources/rest/pet_updated.json");
    }

    @Test
    @Order(1)
    void testPetCreation() {
        given().log().uri()
                .contentType(ContentType.JSON)
                .body(petCreatedJson)
                .post("/pet")
                .then()
                .statusCode(200).extract().response()
                .then().body("name", equalTo(petCreatedJson.get("name")));
        logger.info("Pet entry with id " + petCreatedJson.get("id") + " and name " + petCreatedJson.get("name") + " successfully CREATED");
    }

The @BeforeAll step handles the initial setup, setting the baseURI and building the two JSON objects that will be used in testing.

Because this test class was designed to verify the entire flow, with @Order used to guarantee the correct timing of the test scenarios, the execution flow will be the following:

  1. Create the pet entry
  2. Verify the entry with correct info was created
  3. Update the pet entry
  4. Verify the entry was updated with the correct info
  5. Delete the pet entry
  6. Verify the entry was deleted
Thus, this test suite can run independently each time and does not rely on previously available data, nor does it spam the database after each execution.

Sunday, February 7, 2021

Fast-Forward Frontend Test Automation with Selenide

Tired of having to write a lot of code (the Gherkin feature file, the Runner class, the Steps and the Page Object classes) just for a single Frontend test?

Also, you don't need the detailed and verbose reports offered by automation libraries like Cucumber or Serenity?

Then maybe Selenide is the solution you are looking for.

Selenide is a Selenium WebDriver wrapper, it builds on this time-tested library and comes with new and powerful methods that can be checked here.

This article will present a sample frontend test automation framework built with Selenide and JUnit 5. It can be checked here and let's go step by step into its' structure.

1. Setting up Selenide and JUnit 5

As it is a Maven project, simply add the needed dependencies in the pom file:

<dependency>

<groupId>com.codeborne</groupId>

<artifactId>selenide</artifactId>

<version>${selenide.version}</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.junit.jupiter</groupId>

<artifactId>junit-jupiter</artifactId>

<version>${junit.version}</version>

<scope>test</scope>

</dependency>

2. Define the test data

The showcased test is for a demo contact form so the test data can be easily centralised in a .csv file, thus taking advantage of the very useful @ParametrizedTest feature from JUnit 5.

3. Implement the test

Having JUnit in place, we can use its' annotations to best structure the test for the above contact form, thus:

  • We will open the webpage in the @BeforeEach step:
@BeforeEach 
public void loadWebpage() { 
 open("http://automationpractice.com/index.php?controller=contact"); 
     }
  • Implement the actual test steps in a @ParametrizedTest using as test data the above .csv file:
@ParameterizedTest
@CsvFileSource(resources = "/contactForm.csv", numLinesToSkip = 1)
public void testContactForm(String subjectHeading, String emailAddress, String orderReference, String message, String uploadFile) {
        $(By.id("id_contact")).selectOption(subjectHeading);
        $(By.id("email")).setValue(emailAddress);
        $(By.id("id_order")).setValue(orderReference);
        $(By.id("message")).setValue(readTextFileAsString(message));
        $(By.id("fileUpload")).uploadFile(new File(uploadFile));
        $(By.id("submitMessage")).click();
        $(By.className("alert-success")).shouldHave(Condition.text("Your message has been successfully sent to our team"));
    }

A special mention here for the UploadFile feature from Selenide that can save you from the dreadful workarounds of trying to interact with the native OS file select window.

  • Do the clean-up in the @AfterEach step:

@AfterEach
public void closeBrowser() {
        closeWebDriver();
    }

So, as seen, the main test case for this webpage can be written in a concise manner and in under 30 lines of code. Whereas going with the Gherkin approach would have implied exponentially more code and effort to structure it.

Thursday, January 28, 2021

The "Gut Feeling"

When information is incomplete and maybe even contradictory, but taking a decision is of the utmost urgency, you can ultimately rely on your gut feeling. Trust it, you might even save the world!