Showing posts with label test automation. Show all posts
Showing posts with label test automation. Show all posts

Friday, 4 March 2022

How to Deploy Selenium grid on AWS / Amazon EKS

  


                                    Selenium Grid is good for parallel execution but maintenance is a nightmare in an era where you see a frequent upgrades to browsers and corresponding drivers. No sooner the usage of automation framework / selenium grid increases, scalability and maintenance becomes a challenge. To address such issues, we do have solutions based on dockers, docker swarm etc. Having said that, there are some caveats in scaling, managing container health etc.

Below solution would try to address most of them. Major chunks of the solution include Selenium, Zalenium, Docker, Kubernetes and Amazon EKS.

This article would outline the process of deploying Selenium grid(Zalenium) on AWS (Amazon EKS) using Kubernetes and Helm.

What do we achieve with this setup..?

  • Scalability: EKS can scale the nodes and pods as per the given configuration.
  • Visibility: Zalenium provides a feature to view the live executions on the containers.
  • Availability: Amazon EKS cluster makes selenium grid available all the time.
  • Maintenance: Low maintenance as the containers are destroyed after each execution.

Pre-requisites:

  • An active Amazon AWS account.
  • IAM user is created in AWS account
  • AWS CLI is connected to AWS account providing the user credentials using local powershell or any terminal
                                                                OR
  • Use AWS cloudshell which is automatically connected to logged in account.
  • Install AWS CLI (for local terminal), kubectl, helm in the given order.

Lets Get Started!

Once the above pre-requisites are met, next task to deploy any application on kubernetes is to create a kubernetes cluster. There are different ways to create a cluster on AWS, I'll brief couple of ways to achieve the same.

First, Create cluster from AWS GUI.

1. Create master node or cluster 
  • Open Amazon EKS console
  • Choose Create Cluster
  • Provide details like cluster name, k8s version, role
  • Select VPC, security groups, endpoint access
  • Further steps as shown on GUI which will make 'master' ready.
2. Create worker nodes and connect to the above created cluster.
  • Create Node Group (Amazon EC2) instances.
  • Choose the cluster, to which the above node group should get attached.
  • Select security group, resources etc.,
  • Define min and max number no. of nodes.
Sounds complex?. No issues, there is another simple and efficient way to make the whole process look simple.

Second, Create cluster using eksctl (The official CLI for Amazon EKS)

The above complex task can be achieved with a single command.

Thursday, 23 September 2021

Dockers and Kubernetes Cheat sheet

Below are list of frequently used commands. This would come very handy while working with docker & kubernetes.

Docker & Kubernetes Commands 



Thursday, 12 August 2021

How to create and execute Jmeter script using Java


Performance Test!. When we say this term, one of the first things that gets into our mind is 'Jmeter'.

           Jmeter is the go-to tool for the performance testing needs in open source community. It is built completely using Java, designed to perform load test and measure performance. It can simulate load on a server, group of servers, network to check the threshold limit and analyze performance under different types of loads. Vast list of plug-ins which extends jmeter capabilities and making it handle most of the performance test requirements.

Mostly the Jmeter GUI is used to create the scripts, configure the users, capture other details and execute the scripts. But, when it comes to integrate the performance tests to code driven automation frameworks, one has to switch to Jmeter GUI to create scripts & fallback to framework to execute the jmeter scripts. In order to make the integration seamless, Jmeter scripts can be created & executed during runtime using code driven framework. Below code snippet would lead you to achieve the same.

Below snippet will let you create a jmeter script (jmx) for a webservice by adding minimal elements to test plan. Typical hierarchy of a web request in a jmx would be as below:

 Test Plan 
à Thread Group à Sampler à Assertions à Listeners 

Steps:

  • Create a maven project through eclipse or any IDE.
  • Add the below Jmeter dependencies in your POM file:
    • ApacheJMeter_core
    • ApacheJMeter_components
    • ApacheJMeter_http
    • jorphan
    • ApacheJMeter_java
  • Create a class named "APITest" and copy the below code snippet
  • Change the service details & file locations accordingly.
  • DONE..! You are all set to create and run the jmeter script from java.

import java.io.File;
import java.io.FileOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.gui.ArgumentsPanel;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.gui.LoopControlPanel;
import org.apache.jmeter.control.gui.TestPlanGui;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.report.config.ConfigurationException;
import org.apache.jmeter.report.dashboard.ReportGenerator;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.threads.gui.ThreadGroupGui;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;

public class APITest {
	
    public void createAndExecute() {
		File jmeterHome = new File("C:/apache-jmeter");
		try {
			if (jmeterHome.exists()) {
				// JMeter Engine
				StandardJMeterEngine jmeter = new StandardJMeterEngine();
				setconfig(jmeterHome, "./htmlreportsdir");

				// JMeter Test Plan, basic all u JOrphan HashTree
				HashTree testPlanTree = new HashTree();
				// HTTP Sampler
				HTTPSamplerProxy httpSampler = new HTTPSamplerProxy();
				httpSampler.setName("HTTP Sampler");
				httpSampler.setProtocol("https");
		        httpSampler.setDomain("testjmeter.com");
		        httpSampler.setPort(8080);
		        httpSampler.setPath("/getservicepath");
		        httpSampler.setMethod("GET");
		        httpSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
		        httpSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
		        httpSampler.setEnabled(true);
		        
		        httpSampler.addArgument("Arg1","val1");//Arguments
		        httpSampler.addArgument("Arg1","val1");//Arguments
		        
		        httpSampler.addNonEncodedArgument("", "serviceBody", "=");//payload
	        	httpSampler.setPostBodyRaw(true);
	        	
				//Loop Controller
				LoopController loopController = new LoopController();
		        loopController.setLoops(1);
		        loopController.setFirst(true);
		        loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
		        loopController.setProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName());
		        loopController.initialize();
		        
				//Thread Group
				ThreadGroup threadGroup = new ThreadGroup();
		        threadGroup.setName("API Thread Group");
				threadGroup.setNumThreads(20); //Users
		        threadGroup.setRampUp(10); //Seconds
		        threadGroup.setSamplerController(loopController);
		        threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
		        threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());
		        
		        threadGroup.setIsSameUserOnNextIteration(true);
		        threadGroup.setScheduler(false);
				
				//Test Plan
				TestPlan testPlan = new TestPlan("JMeter Script From Java Code");
		        testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
		        testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
		        testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());
				
				//Construct Test Plan from previously initialized elements
				testPlanTree.add(testPlan);
				HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup);
				threadGroupHashTree.add(httpSampler);

				// save generated test plan to JMeter's .jmx file format
				String jmxFilePath = "./jmxfiles/TestAPI.jmx";
				SaveService.saveTree(testPlanTree, new FileOutputStream(jmxFilePath));

				// add Summarizer output to get test progress in stdout like:
				String jtlFilePath = ".jtlFiles/TestAPI.jtl";
				ReportGenerator reportGenerator = setReportInfo(testPlanTree, jtlFilePath);
				
				//Run Test Plan
				jmeter.configure(testPlanTree);
		        jmeter.run();
		        
				// Report Generator
				FileUtils.deleteDirectory(new File("./htmlreportsdir"));// delete old report
				FileUtils.deleteDirectory(new File("./reportsdir"));// delete old report
				reportGenerator.generate();

				System.out.println("Test completed. See " + jtlFilePath + " file for results");
				System.out.println("JMeter .jmx script is available at " + jmxFilePath);
				
			} else {
				System.out.println("Jmeter Home not found..");
			}

		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
    
	public void setconfig(File jmeterHome,String htmlrepDir){
		File jmeterProperties = new File(jmeterHome.getPath() +"/bin/jmeter.properties");
        //JMeter initialization (properties, log levels, locale, etc)
        JMeterUtils.setJMeterHome(jmeterHome.getPath());
        JMeterUtils.loadJMeterProperties(jmeterProperties.getPath());
        JMeterUtils.initLocale();
        
        //Set directory for HTML report
        JMeterUtils.setProperty("jmeter.reportgenerator.exporter.html.property.output_dir",htmlrepDir);
	}
	
	
	public ReportGenerator setReportInfo(HashTree testPlanTree,String jtlFilePath) throws ConfigurationException{
		Summariser summer = null;
        String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
        if (summariserName.length() > 0) {
            summer = new Summariser(summariserName);
        }
        
        // Store execution results into a .jtl file
        File logFile = new File(jtlFilePath);
        //delete log file if exists
        if (logFile.exists()){
            boolean delete = logFile.delete();
            System.out.println("Jtl deleted: " + delete);
        }
        
        //Summary Report
        ResultCollector logger = new ResultCollector(summer);
        logger.setEnabled(true);
        logger.setFilename(logFile.getPath());
        //creating ReportGenerator for creating HTML report
        ReportGenerator reportGenerator = new ReportGenerator(jtlFilePath, logger); 
        testPlanTree.add(testPlanTree.getArray()[0], logger);
         
	return reportGenerator;
	}
		
}