Skip to content

Instantly share code, notes, and snippets.

@p00j4
Last active July 4, 2016 09:46
Show Gist options
  • Save p00j4/d73c0bdae2a1dc95b6332bc856832765 to your computer and use it in GitHub Desktop.
Save p00j4/d73c0bdae2a1dc95b6332bc856832765 to your computer and use it in GitHub Desktop.
Gist for documenting elemental tips
Useful for testing of the products for which post parameters & response validation is very important at the client side itself.
The Problem
question: In general how do you do API testing?
answer: take the API from development document, hit it manually and check the response based on the post payload or may be write a automation suit around API using tools like SoapUI or Postman or some sort of API tests running in isolation from functional tests, isn't it?
what if when you can actually automate the API testing within the same functional test which ensures the user functional flow? does it sound more reliable testing!
or assume an automated way which can also give debugging metrics to figure out the Caught bug is from front-end or backend and help tracking almost all integration issues(front-edn to backend) at earlier stage. One more layer of smartness to add up in test report, sounds interesting?
A Solution
Need a mechanism which can be mixed in the existing selenium functional ui test and can give a way to capture the post data to the backend.
This tip can be handy and solve the problem with just few more lines to the proxy server which we had set up and captured the network traffic to do load testing in previous tip.( hyperlink to http://elementalselenium.com/tips/68-load-testing-revisited)
An Example
First we'll set up our requisite libraries to drive the browser (e.g., selenium-webdriver) and perform an assertion. After that, we'll create some simple setup, teardown, andrun methods fooled by proxy for networ data capture and then retrieve post payload in code to validate it.
# filename: LoginTest
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.core.har.HarEntry;
import net.lightbody.bmp.core.har.HarPostData;
import net.lightbody.bmp.core.har.HarPostDataParam;
import net.lightbody.bmp.core.har.HarRequest;
import net.lightbody.bmp.proxy.CaptureType;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
public class LoginTest {
WebDriver driver;
BrowserMobProxy proxy;
Har har ;
String uName = "tomsmith";
String pwd = "SuperSecretPassword!";
HashMap<String,String> param_map = new HashMap<String,String>();
HashMap<String,String> param_values = new HashMap<String,String>();
@Before
public void setUp() throws Exception {
proxy = new BrowserMobProxyServer();
proxy.start(0);
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
driver = new FirefoxDriver(capabilities);
HashSet<CaptureType> captureTypes = new HashSet<CaptureType>();
captureTypes.add(CaptureType.REQUEST_HEADERS);
captureTypes.add(CaptureType.REQUEST_CONTENT);
captureTypes.add(CaptureType.RESPONSE_HEADERS);
captureTypes.add(CaptureType.RESPONSE_CONTENT);
proxy.enableHarCaptureTypes(captureTypes);
{ //mocking parameters to be passed/accepted at server end
param_map.put("username",uName); //change accordingly
param_map.put("password",pwd);
}
}
@Test
public void withValidCredentials() throws IOException {
proxy.newHar();
driver.navigate().to("http://the-internet.herokuapp.com/login");
driver.findElement(By.id("username")).sendKeys(uName);
driver.findElement(By.id("password")).sendKeys(pwd);
driver.findElement(By.cssSelector("button")).click();
WebElement successMessage = driver.findElement(By.cssSelector(".flash.success"));
assertThat(successMessage.isDisplayed(), is(Boolean.TRUE));
har = proxy.getHar();
File harFile = new File(System.getProperty("user.dir") + "/test.har");
har.writeTo(harFile); // performance capture for further load testing
validatePassedPayload(har, "auth"); // post data validation
System.out.println("Passed:: Captured har for performance check \"test.har\" + validated posted parameters");
}
/**
* To sniff post payload for validating if client side parameters are being passed correctly
* useful to use with ui automation test like with webdriver to ensure if user has posted correct data to server
* @param har
* @param filterStr: to refine url
*/
public void validatePassedPayload(Har har, String filterStr){
for (HarEntry entry : har.getLog().getEntries()) {
if (entry.getRequest() != null) {
HarRequest request = entry.getRequest();
String requestUrl = entry.getRequest().getUrl();
if (requestUrl.contains(filterStr)) {
HarPostData postData = request.getPostData();
if (postData != null) {
System.out.println(requestUrl);
List<HarPostDataParam> paramsList = request
.getPostData().getParams();
if (paramsList != null) {
for (int i = 0; i < paramsList.size(); i++) {
HarPostDataParam param = paramsList.get(i);
String paramName = param.getName();
System.out.println(param.getName()+":"+param.getValue()); //to debug
assertThat(param.getValue(), is(param_map.get(paramName))); //will fail if either param doesn't exist or value doesn't match
}
}
}
}
}
}
}
@After
public void tearDown() throws Exception {
proxy.stop();
driver.quit();
}
}
Expected Behavior
1. Selenium runs the test in Firefox while connected to the proxy server
2. The HTTP Archive (HAR) is exported to a file on disk
3. Retrieve the required post data from the captured HARD and validate the same.
Outro
Alternatively, you could write the post data validation code separately by reading the exported HAR file, this will be helpful when you have multiple requests to validate
Happy Automated Testing!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment