Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Wednesday, May 1, 2024

Interview preparation series Java: Are you not getting interview and/or coding test invites?

Are you not getting interview and/or coding test invites? 

These days it is pretty common. So, first of all, I would advice, consider reviewing your CV/Resume. Kindly do not exaggerate listing your skills, by copying from others. The technical panels are smart to judge how much truth is in it. Focus on elaborating on your role, job duties and some of the key challenges that you may have faced in the projects that you have been a part of, your professional achievements and certifications. My advice to freshers is they should put focus on their academic projects, and challenges faced in executing them and the certifications.

Now, if you get an invite for interview/coding test with a very short notice, how much prepared do you think you are? 

If you are among a small set of lucky candidates who received the interview/coding test invites, you still are in a competition.Thus, you need smart preparation to compete fairly, which includes a lot of coding practice on a regular basis. Below are my recommendations for preparing well:

Java:

1. Thoroughly study and memorize the functions under java.lang.Math package. You may ask why? Because over past 10 years, most of the coding tests ask require you to solve either a mathematical or a numerical problem. So without having a solid command over Math package, you can't solve most of the problems.

2. Focus on Java 8 onward features and coding styles. These days Java 6 style coding is old-fashioned and the industry trends follow Functional programming, including asynchronous functions (lamda), bi-functions and its use in stream() operations. In some of the online coding tests, you will be asked to only write the missing part of the code in a method. If you are not familiar with the aforementioned concepts, then you may miss an opportunity to score, because sometimes the asks will be very simple, but by the time you realize it, the opportunity will turn into a lost opportunity.

3. Thoroughly study and memorize the functions under java.util.Stream package. You may ask why? Again, most coding tests moved to Java 8 and above syntax. So, the expectation is to solve problems using stream() operations. Practice using Array, Strings, charArray, collections, (i.e. List, Set) and map. The idea is to determine whether you are familiar with the java data-structure and collections framework or not, and if you can apply it whenever appropriate in a programming context. 

4. Bitwise operations, sometimes most neglected by the students and professionals, however Bitwise operations are very important to master if you are a Java developer or going to become one. Brush up the bitwise operations and practice the number conversions including Octal, Hexadecimal and Binary numbers, bitwise shift operations, XOR operations. This topic always finds its place either in the online coding test or in the interview process.

5. You might have learned about Data-Structures: Stack, Queue, Dequeue, LinkedList, Tree etc. Do you know when to use it to solve a programming problem? Have you tried using the built-in data-structures in Java in any of your academic or professional code? Being honest with yourself, if you feel you are not comfortable with applying Data-structures, then revisit the concepts, look out for programming practice problems and set out sometime everyday to do practice for at least an hour.

6. None of the programming is complete without its File operations, and Java is not an exception. So please read through java.io.File package, memorize the functions and its parameters, and understand when to use which technique to read and write to files. The interviewers are sometimes more interested in understanding how much you know about the file operation efficiencies.

7. Without DB connection, a standalone program does not deliver value. So, you need to master JDBC connection and Spring Boot alternatives. In the interviews, you may expect questions on DB operations with respect to microservices development. So, getting yourself familiar with MySQL, Postgre, MongoDB will help a lot.

8. Exception handling and debugging is an integral part of any programming language. So, you should be able to tackle questions around efficient ways of handling errors and exceptions, including raising custom exceptions.

Friday, August 18, 2023

How to build a test automation framework using Playwright, Spring boot, Java, Cucumber and Junit5

In this article, I will be guiding you step by step in creating a test automation framework using Playwright, Spring boot, Java, Cucumber and Junit5. Additionally, I will explain about Aspect Oriented Programming (AOP) for cross-cutting features (like logging) and using Lombok annotations for simplification and enhancing readability of the code.

What do you need before starting?

I always recommend to use latest tech to explore full potentials of various software's. Its absolutely fine if someone disagrees with this approach 😃

  • A 64 bit system with at least 4GB RAM (8 GB preferred).
  • MacOS - Monterey or Windows 10 and above
  • Java 11 or above installed
  • IntelliJ Community edition (latest version preferred) installed
  • Docker Desktop installed
How to create a Spring boot project?

The simplest way, is to visit this site: https://start.spring.io/, then select from the available options, enter value for Group, remember this will become your parent package. Based on your requirement, you may decide to enter Artifact, Name, Description.

Here, I have selected Project as "Maven". If you want to
 experiment with "Gradle-Groovy" you are most welcome, do leave a comment  and let me know if you faced any issue, it will help me gain some knowledge.

For Language, I have selected Java, as our objective is to write code using java. It is recommended to use latest Spring Boot version, as it will always have new features in it.

Packaging type "Jar" is selected by default, and I don't have any objective to change it, so left it as is. Java version also I left as is.

You might have noticed, there is an option to add dependencies:

This is a useful option, through which we can add a lot of needed dependencies for spring boot , which will be automatically added to the maven pom file, once we click on the "Generate" link.

I will be adding Lombok dependency as follows:

Click the "Add Dependencies" link, then select Lombok and press enter.








Now, you can see that Lombok has been selected as a dependency:






Now you are ready to create the project. Click "Generate" button. It will automatically download the project skeleton as a zip file. The file name will be as per the "Name" parameter which you have passed.

 











This is how the project folders will look like. Until unless, you are planning to create some Micro-services for your hands on with Playwright API testing, you may remove the "main" folder from the project, before importing it as a maven project in IntelliJ.

What maven dependencies do we need to add?
  • Cucumber-java
  • Cucumber-spring
  • Cucumber-junit-platform-engine
  • Playwright
  • junit-platform-suite
  • Commons-lang3
  • aspectjweaver
You can refer to the Maven POM file: POM

Now, I will explain how to create Playwright browser using factory design pattern. The code is available in my GitHub repository:   PlaywrightTestAutomationFramework

Step 1:

Create a package (folder), called configuration and park your Cucumber and Spring configuration classes in it.

import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.test.context.ContextConfiguration;

@CucumberContextConfiguration
@ContextConfiguration(classes={TestConfig.class})
public class CucumberContextConfig {

}
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("springboot.playwright.cucumber")
public class TestConfig {

}
Step 2:

Create a package (folder) to park all interfaces and classes that are responsible for creating and supplying Playwright bean. Next, create a Java Interface, which will supply the playwright browser factory bean:


Here, I have created some method definitions. 

setPlaywrightBrowser(String browserType) method will take the browser type as input, say Chrome/Firefox etc. and will initialize the Playwright browser context (native to Playwright).

getPlaywrightBrowser() method will return the playwright bean browser context.

setPlaywrightBrowserContext(), getPlaywrightBrowserContext(), setPlaywrightPage() and getPlaywrightPage() methods are created for support purposes, in case the user need to access these from the factory bean. setTracing(Boolean) and isTracingOptionSet() are also support methods, to turn the browser tracing on/off.

Now, create a class that will implement the interface:

The first line within the class is very important:  Playwright playwright = Playwright.create();

The rest of the code is self-explanatory, carefully read and understand how it Overrides the PlaywrightBrowser interface, created in Step 1 above.

import com.microsoft.playwright.*;
import java.util.Objects;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;

@SuppressWarnings({"unused","cast"})
public class PlaywrightBrowserSupplier implements PlaywrightBrowser {
Playwright playwright = Playwright.create();
Browser browser;
BrowserContext browserContext;
Page page;
//This boolean value is used for introducing Playwright tracing
Boolean isTracingSet=false;

public PlaywrightBrowserSupplier(String BrowserType, Optional<Boolean> tracingOption){
setPlaywrightBrowser(BrowserType);
//This method checks the optional tracingOption value and accordingly turns on
// Playwright browser tracing
setTracing(tracingOption.orElse(false));
}

/** This method will initialize the PlaywrightBrowser bean (Facade design pattern)
* with appropriate browser type
* Author: Susnigdha Chatterjee
*/
@Override
public void setPlaywrightBrowser(String browserType)
{
switch(browserType.toLowerCase()) {
case "chrome":
//Below line will launch chrome browser in non-headless mode
//browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
// .setHeadless(false));
//If you wish to execute the code in Headless mode then please un comment
// below line*/
browser = playwright.chromium().launch();
break;
case "firefox":
browser = playwright.firefox().launch();
break;
}
setPlaywrightBrowserContext();
setPlaywrightPage();
}

@Override
public Browser getPlaywrightBrowser() {
return browser;
}

@Override
public void setPlaywrightBrowserContext() {
browserContext=getPlaywrightBrowser()
.newContext();
}

@Override
public BrowserContext getPlaywrightBrowserContext() {
return browserContext;}

@Override
public void setPlaywrightPage(){
page=getPlaywrightBrowserContext().waitForPage(()->getPlaywrightBrowserContext()
.newPage());
}

/**This method will help to retrieve the Playwright page from the PlaywrightBrowser bean
*/
@Override
public Page getPlaywrightPage(){
return page;
}

@Override
public void close() {
page.close();
browserContext.close();
playwright.close();
}

/**
* This method will be called from Hooks class, from cucumber After hook
* @author Susnigdha Chatterjee
* @return byte array which holds the screenshot
*/
@Override
public byte[] captureScreenshot(){
Path objPath = Paths.get("target/screenshots/Screenshot_"+ LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("ddMMyy_hhmmss"))+".png");
return page.screenshot(new Page.ScreenshotOptions().setPath(objPath)
.setFullPage(true));
}

/**
* This method will be called from Constructor to set the Playwright browser tracing on
* @author Susnigdha Chatterjee
* @return byte array which holds the screenshot
*/
@Override
public void setTracing(Boolean option){
if(option && !Objects.isNull(browserContext)){
browserContext.tracing().start(new Tracing.StartOptions()
.setSnapshots(true));
isTracingSet = true;
}
}
/**
* This method will be called from Hooks class's After annotation to decide if
* Playwright browser tracing needs to be turned off
* @author Susnigdha Chatterjee
* @return byte array which holds the screenshot
*/
@Override
public boolean isTracingOptionSet(){
return isTracingSet;
}
}

Finally. create a "Configuration" class, that will be responsible for creating the factory bean. Pay attention to the annotations used. @Configuration will inform Spring that it has Bean definitions. @Slf4j annotation comes from Lombok, which will use Spring's default Log Back mechanism to generate console logs. @SupressWarnings will suppress the listed unwanted warnings. @Bean annotation indicates that the method will create a bean and @ScenarioScope will indicate that this bean will be available across Cucumber scenarios. Rest of the code is self-explanatory, you need to read :) . Do leave a comment for any doubts.
import io.cucumber.spring.ScenarioScope;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Optional;

/**
* Using factory design pattern. The PlaywrightBrowser interface serves as the factory.
* PlaywrightBrowserSupplier implements the PlaywrightBrowser interface based on
* the browser type supplied using the browserType parameter of
* testconfigurations.properties file
*/

@Configuration
@Slf4j
@SuppressWarnings({"unused","cast"})
public class PlaywrightInitializer {
/** Using Facade design pattern to initialize Playwright page using
* custom built PlaywrightBrowser interface
* @author Susnigdha Chatterjee
*/
@Bean(name="PlaywrightBrowser", destroyMethod = "close")
@ScenarioScope
public PlaywrightBrowser init() {
//Creating the bean of type PlaywrightBrowser using its implementing
// class PlaywrightBrowserPage
log.info("Creating PlaywrightBrowser bean");
//Added new Optional parameter to the constructor method
return new PlaywrightBrowserSupplier(System.getProperty("browser"),
Optional.of(Boolean.valueOf(System.getProperty("tracing"))));
}
}
Step 3:

Create a package to park your Cucumber hooks, and place related classes in it. In this example class, I am attaching screenshots for each cucumber scenario, and also determining if we need to stop tracing.
import com.microsoft.playwright.Tracing;
import io.cucumber.java.Scenario;
import lombok.extern.slf4j.Slf4j;
import springboot.playwright.cucumber.playwright.PlaywrightBrowser;
import io.cucumber.java.After;

import java.nio.file.Paths;

@Slf4j
public class hooks {
PlaywrightBrowser playwrightBrowser;
hooks(PlaywrightBrowser browser) {
this.playwrightBrowser=browser;
}

@After
public void afterScenario(Scenario scenario)
{
//Capturing screenshot irrespective of whether the test pass or fail
//This approach will ensure there is always evidences for the tests outcome
scenario.attach(playwrightBrowser.captureScreenshot(),
"image/png","screenshot");
log.debug("Attaching full page screenshot, after the scenario");

if(playwrightBrowser.isTracingOptionSet()) {
playwrightBrowser.getPlaywrightBrowserContext().tracing()
.stop(new Tracing.StopOptions()
.setPath(Paths.get("target/traces.zip")));
}
}
}
Step 4:

Create a package to park your Cucumber Junit5 runners:
Pay attention to the annotations used. Also look into the setUp method, from this method we will set system properties, which will be used by the PlaywrightInitializer class, we created earlier.

import io.cucumber.java.Before;
import lombok.extern.slf4j.Slf4j;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;

@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("/features")
@ConfigurationParameter(key="cucumber.plugin",
value = "html:target/CucumberTestExecutionReport_Chrome.html")
@Slf4j
public class runnerChrome {
@Before
public void setUp() {
//You could pass these property values using application.properties file also.
//I am writing it in this way to make it easy to understand for those who have
// less technical knowledge
//and willing to learn and experiment more
System.setProperty("browser","chrome");
System.setProperty("tracing", String.valueOf(true));
log.info("Passing browser property to PlaywrightBrowser bean");
}
}
For cross browser execution, create another runner class and set the browser property to a different browser.

Step 5:

Create two package, one for Step Definitions and the other for PageObjects, then add the needed classes.

Step 6:

Create a package for AOP, and park related classes in it:

The @Aspect and @Component annotation makes this class as an aspect. The @Before annotation is defined with a point cut, that will attach to all the methods of pageObjects.PageObject class. The associated JoinPoint will then be used to log the method signatures. It describes how to create common logging. The @Around annotation is defined with  a point cut on Playwright's native package to capture and throw any exception, this is kept as an example to show that we can write custom exception handlers using AOP

import io.cucumber.spring.ScenarioScope;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Slf4j
@Component
@ScenarioScope
public class CommonLogger {
@Before("execution(* springboot.playwright.cucumber." +
"pageObjects.PageObject.*(..))")
public void putCommonLog(JoinPoint joinPoint) {
log.debug("Invoking this method from PageObject class instance: "
+ joinPoint.getSignature().getName());
}

@Around("execution(* com.microsoft.playwright.*.*(..))")
public Object exceptionHandlerWithReturnType(ProceedingJoinPoint joinPoint)
throws Throwable{
Object obj;
obj = joinPoint.proceed();
return obj;
}
}
If you have followed the contents so far and also checked out the associate GitHub repository, then I am sure you have learned step by step how to design a test automation framework, using Playwright, Spring boot, Java, Cucumber and Junit5.

Saturday, July 29, 2023

How do we sustain in Software Test Automation career?

I am sure that this question often strikes every test automation professional, irrespective of their experience level and skills proficiency. So, in this blog, I am going to do a deep dive with you to share the industry experience which I have gained, and that you can easily relate with your experiences.

The rise and transformation of test automation roles:

From around year 2002, Software Testing as a profession got significant acceleration in India. And within few years, the market demand for Test Automation professionals risen scrumptiously. Popular testing tools of that decade was Quick Test Pro, WinRunner, Silk Test, Rational Robot, SoapUI, Rational integration tester and Ruby on rails. I am not covering ETL test automation tools in this blog, as I do not have practical experience with any of those tools.

Nevertheless, Microsoft Excel based macros and VB Scripts were very popular those days, mostly used for some windows based repetitive tasks automation, including manipulation of Databases. PERL and Shell Scripting provides similar capabilities in more secured Unix/Linux/Solaris platforms.

Many training centres emerged across India, to utilise the opportunity to upskilling a mass and make huge profits out of it. Those days, all training centres used to conduct classroom trainings, some even offered placement assistance. Many who could afford such trainings those days, got benefitted either by switching to new role or by securing a new job. These days, the traditional training centres evolved too, offering hybrid trainings (including classroom, virtual, offline), but now they are facing direct competition from more organized Online training platforms and free training vlogs available on the internet.

In that decade, many did certifications in QTP, WinRunner, Silk Test and RFT tools. Whoever did the certifications earliest, mostly got benefitted.

So, what is challenging our sustainability in test automation roles?

In simple terms, the technological advances in electronics and semiconductor industry, coupled with substantial advances in Cloud computing, mobile platforms, AI, ML, IoT, Responsive Web, Single page/React applications, and new generations of high-speed internet, opensource tools has been destabilising our careers over the past decade, say 2013 to 2023.

Well, one might debate, that the technological advances have impacted all types of job roles, and human lives. Absolutely!!! Our lives have transformed to Digital; Quality Assurance and Test Automation are directly responsible to maintaining and raising the quality of our Digital transformation journey.

Between 2002 – 2012, many organizations used to conduct trainings on test automation tools, beside other technologies, for their employees, and it was optional to participate. They did use to conduct some skill-based exams, offering a certificate to their employees whoever scores 72% (for example) or above. Since, its optional, only people whoever was serious in building a career out of it or who want to be a future manager, were the only participants. In that decade, most roles demanded a manual tester, who can do automation if needed.

From 2012 onward, the optional training started becoming mandatory, and they started featuring in the career paths, yearly learning goals and performance appraisal discussions. From 2015 onward, many organizations revamped the role of manual testers, by upskilling that population to Automation Tester roles, who can perform manual testing if required. In this period, we mostly transformed from using Excel based test data sheets to BDD Examples, API driven data (JSON, XML, and recently GraphQL), Configuration based data (Properties files) etc. Many of us were tasked with doing complex test automation's, for example Mainframe applications, PDF files, image recognition and comparison, Big Data, running Unix batches part of integration test and reading console logs etc.

From 2020, the automation roles now demand knowledge and experience of CI/CD tools (GitLab’s, Jenkins, TeamCity, Terraform, Ansible, Ant, Docker, Kubernetes, Azure/AWS), deployment, Elasticsearch backed log server. That means, an automation tester who can perform DevOps tasks too.

Additionally, introduction and rise of new automation tools (mentioned below) started challenging the test automation professionals who spent most of their career with UFT (QTP), RFT, Selenium (IDE, 2.0 or 3.0) and Silk Test to upskill in these tools, to sustain and stay relevant in the job market.

  • Open source: Playwright, Cypress, WebdriverIO, Puppeter, Selenium Webdriver 4.0, PyTest, Robot Framework, RestAssured
  • Licensed tools (Including SaaS offerings): Copado Provar, AccelQ, Tricentis TOSCA, Test Complete, Ranorex, Katalan Studio, Karate
  • Test Infrastructure providers: BrowserStack, SauceLab, LamdaTest

Accompanied by the language antagonisms Java, C#, Python, JavaScript, and TypeScript.

For hardcore techies, who are having 12+ years of experience, there are other additional challenges to deal with in order to sustain, managing an agile or e2e test automation team, preparing and implementing test strategies, enforcing design patterns and architectural decisions, code reviews, mentoring, managing conflicts, test environments, test data, test logging (Elasticsearch, New Relic), test metrics and test reporting.

Finally, what actions would help us to sustain?

  •  Positive attitude and openness towards learning.
  • A systematic approach, balancing our life priorities and managing at least 4 hrs a week for our personal skills development and practice, with devotion.
  • Taking advantage of our organizations provided/supported learning platforms to identify, register and complete relevant training.
  • Earning digital badges
  • Keeping an eye on market relevant certifications, and earning those
  • Getting accustomed to NLP based machine learning algorithms and trying out tools like ChatGPT
  • Build skills in at least one RPA tool (UiPath, Microsoft Power Automate etc.)
  • Finally, mastering JavaScript. What??? Yes, you read it right. If you master JavaScript, all these tools will become easy for you to learn: Cypress, Playwright, WebdriverJS, WebdriverIO, Test Complete and Tricentis TOSCA.

 

Test Automation Strategy for Oracle Forms application running in Citrix servers

  Context : There are many product based applications developed using Oracle Forms and Java thick-client architecture, and most of them are ...