In a Nutshell
René Schwietzke, Xceptance
Just some random history facts
Why did we write our own toolchain?
Performance-Test-as-Code
This tool is for you, when...
This isn't your tool, when...
Open and Flexible
*) HtmlUnit, HttpClient, JUnit, **) either standalone or later in XTC
The High-Level Overview
Agents can be anywhere. HTTPS communication and authentication, just one open port needed
*) Optional
Makes test projects more easily manageable
XTC only supports GIT
The scaled-out workhorse
Many ways to write tests
public class ViewCart extends PageAction<ViewCart>
{
@Override
protected void doExecute() throws Exception
{
// Get mini cart link.
final HtmlElement cartLink =
GeneralPages.instance.miniCart.getViewCartLink().asserted().single();
// Click it.
loadPageByClick(cartLink);
}
@Override
protected void postValidate() throws Exception
{
// this was a page load, so validate what is important
Validator.validatePageSource();
// basic checks for the cart
CartPage.instance.validate();
}
/*
* getViewCartLink()
* Header.instance.locate().byCss("#miniCartMenu").byCss("a.goToCart");
*/
}
https://github.com/Xceptance/posters-advanced-loadtest-suite
// Send a post request which contains form data parameters.
final String lastId = Actions.get("Post Form Data Parameter", t ->
{
// let's submit some post parameter (form data)
final HttpResponse response = new HttpRequest().timerName(t)
.baseUrl("https://postman-echo.com")
.relativeUrl("/post/")
.param("id", String.valueOf(XltRandom.nextInt()))
.param("foo", "true")
.param("bar", "false")
.param("parameter", "value")
.method(HttpMethod.POST)
.fire();
response.checkStatusCode(200);
final String responseContent = response.getContentAsString();
// Response content validation, uses the jsonpath query language
final ReadContext ctx = JsonPath.parse(responseContent);
Assert.assertTrue(Boolean.valueOf(ctx.read("$.form.foo", String.class)));
Assert.assertFalse(Boolean.valueOf(ctx.read("$.form.bar", String.class)));
// Also let's return the id from the response.
final String responseId = ctx.read("$.form.id", String.class);
return responseId;
});
- Action:
Name : Homepage
Request :
Url : ${host}/posters/
Response :
Httpcode : 200
Validate:
- Title:
XPath: id('titleIndex')
Matches: "\\w out our *"
- Button:
XPath: id('btnShowLoginForm')
- MenuList :
XPath : id('login-form')/ul/li[@name='Women']
Count : 17
- Header :
XPath: id('titleIndex')
Text: "Check out our new panorama posters!"
- ShowCard-Button :
XPath : "/html/body/div[1]/div[2]/div/button[1]"
Subrequests:
- Static:
- ${host}/posters/assets/css/bootstrap-2.3.1.min.css
- ${host}/posters/assets/css/bootstrap-responsive-2.0.4.css
https://github.com/Xceptance/testsuite-nocoding
Flexible load profiles
Scale up or scale down easily by using the factor feature.
See the data transferred in detail
Most awesome when investigating load test errors
Standard Reports and Extra Features
Open data for custom analytics, modification, and reporting
R,Homepage.1,1440421580217,267,false,255,2830,200,http://localhost:8080/posters/,text/html,1,0,0,0,19,19,
R,Homepage.1.8,1440421580687,28,false,457,306680,200,http://localhost:8080/posters/img/products/XXL/XXL_4.jpg,image/jpeg,0,0,7,13,7,20,
A,SelectCategory,1440421583179,1094,false
T,TBrowse,1440421578625,8189,false,,
Perfect for searching things outside the ordinary.
Ready to use reporting
Compare two runs
See the trend
What can be added
That is not all of course.
You can do more at any time
That is not all of course.
A real browser as engine
Why real browser support helps
Lot of data.
Lot of data.
SaaS for XLT
Xceptance Test Center
More details later
The basic building blocks
Basic features
Real Scenario Monitoring
Use real test cases with full test stack
Features in a nutshell
Load and Performance Testing
A nutshell view
Things built to aid professional services
And much more.
What is next?
This is not a binding roadmap.
Tools for Load Testing
"Emails for Testing" as a Service
Not yet part of XTC.
Real-world runtime mocking
Not yet part of XTC.
@Controller("/")
public class WorldpayController
{
@Inject
LatencySimulation latency;
@Post(uri = "/jsp/merchant/xml/paymentService.jsp")
@Consumes(MediaType.TEXT_XML)
@Produces(MediaType.TEXT_XML)
public CompletableFuture<HttpResponse<String>>
payment(HttpRequest<String> request,
@Body final String body, final String version)
{
return latency.latency(request, () -> new Worldpay(body));
}
}
public class Worldpay implements ResponseInformation
{
String requestBody;
@Override
public String render() {
final var responseData = new WorldpayResponseData(requestBody);
return Freemarker.render(
"/worldpay/worldpay.ftl",
Map.of("data", responseData));
}
@Override
public ResponseTime responseTime() {
return DEFAULTDYNAMICRESPONSETIME;
}
public static final long LATENCY_MIN = 1000;
public static final long LATENCY_AVERAGE = 1300;
public static final long LATENCY_P95 = 1500;
public static final long LATENCY_MAX = 1600;
public static final int LATENCY_JITTER = 150;
private static final DynamicResponseTime DEFAULTDYNAMICRESPONSETIME =
new DynamicResponseTime(LATENCY_MIN, LATENCY_AVERAGE, LATENCY_P95,
LATENCY_MAX, LATENCY_JITTER);
}