If controller stops further execution when groovy accessed variable is used in condition check
goran237 opened this issue · 7 comments
When using if controller with "${__groovy(vars['XYZ_ID'] == null)}"
condition check, no further statements are being executed:
- not the httpSample under the if controller in case that above condition is
true
- no further httpSamples outside the if controller in case that above condition is
false
When lambda expression is applied instead s->s.vars.get("XYZ_ID")==null
execution runs as expected (for both true and false conditions).
Hello, thank you for reaching out.
Can you share the full test plan?
I tried with this test plan:
testPlan(
threadGroup(1,1,
vars()
.set("XYZ_ID", "1"),
ifController("${__groovy(vars['XYZ_ID'] == null)}",
httpSampler("in", "http://localhost")),
httpSampler("out", "http://localhost")
),
resultsTreeVisualizer()
).run();
And works as expected:
- When commenting out the vars setting, I get httpSampler in and out
- When I keep the vars setting, only httpSampler out is executed
Regards
Sure, here's the DslSimpleController that contains problematic if controller (working correctly only with Java lambda):
private DslSimpleController addVehicle(String baseUrl) {
return simpleController("Add vehicle",
ifController(
//s->s.vars.get("VEHICLE_ID")==null, <--- WORKING SOLUTION
"${__groovy(vars['VEHICLE_ID'] == null)}", <--- NOT WORKING SOLUTION
httpSampler("Add vehicle", baseUrl + "/api/customer-accounts/${CUSTOMER_ACCOUNT_ID}/vehicles")
.method(HTTPConstants.POST)
.contentType(ContentType.APPLICATION_JSON)
.body("{\n" +
"\t\"brand_and_model\": \"Jeep Wrangler JKU\", \n" +
"\t\"color\": \"black\", \n" +
"\t\"license_plate_number\": \"IS12SNW\"\n" +
"}")
.children(jsonExtractor("VEHICLE_ID", "data.vehicles[0].id"))));
}
Thank you.
Can you share more about your test plan? For instance the part that sets VEHICLE_ID, and you also mention that samplers outside the ifcontrolller are not executed either. Maybe if you share the code where this addVehicle method is being used it could clarify your scenario.
Sure, here the method:private DslSimpleController login(String baseUrl, String jdbcPoolName) throws InterruptedException {
private DslSimpleController login(String baseUrl, String jdbcPoolName) throws InterruptedException {
return simpleController("SIGN IN",
httpSampler("Passwordless request", baseUrl + "/api/customers/passwordless-request")
.method(HTTPConstants.POST)
.contentType(ContentType.APPLICATION_JSON)
.body("{\n" +
" \"email\": \"${REGISTERED_EMAIL}\"\n" +
"}"),
jdbcSampler("GetPasswordlessCodeByEmail", jdbcPoolName,
"SELECT passwordless_code FROM passwordless_requests WHERE auth_identifier=? ORDER BY updated_at DESC")
.param("${REGISTERED_EMAIL}", Types.VARCHAR)
.vars("PASSWORDLESS_CODE")
.timeout(Duration.ofSeconds(15)),
httpSampler("Passwordless authorize", baseUrl + "/api/customers/passwordless-authorize")
.method(HTTPConstants.POST)
.contentType(ContentType.APPLICATION_JSON)
.body("{\n" +
"\t\"passwordless_code\":\"${PASSWORDLESS_CODE_1}\",\n" +
"\t\"passwordless_email\":\"${REGISTERED_EMAIL}\"\n" +
"}")
.children(constantTimer(Duration.ofSeconds(12))),
httpSampler("Passwordless login", baseUrl + "/api/customers/login")
.method(HTTPConstants.POST)
.contentType(ContentType.APPLICATION_JSON)
.body("{\n" +
"\t\"passwordless_code\":\"${PASSWORDLESS_CODE_1}\",\n" +
"\t\"passwordless_email\":\"${REGISTERED_EMAIL}\"\n" +
"}")
.children(
jsonExtractor("CUSTOMER_ACCOUNT_ID", "data.customer_account.id"),
jsonExtractor("TOKEN", "data.token.value"),
jsr223PostProcessor(c -> System.out.println(c.prevMap()))),
httpSampler("Fetch all vehicles", baseUrl + "/api/customer-accounts/${CUSTOMER_ACCOUNT_ID}/vehicles")
.method(HTTPConstants.GET)
.contentType(ContentType.APPLICATION_JSON)
.children(jsonExtractor("VEHICLE_ID", "data.vehicles[0].id"))
);
}
This method is called first, and right after that method add vehicle (containing problematic code) is called, as shown below:
public void testPerformance() throws IOException, InterruptedException, URISyntaxException {
String baseUrl = "https://SOME_BASE_URL";
TestPlanStats stats = testPlan(
vars().set("SUBCATEGORY_NAME", _SUBCATEGORY_NAME),
csvDataSet("src/main/resources/CustomersAccounts_187K.csv")
.variableNames("REGISTERED_EMAIL")
.ignoreFirstLine(true)
.delimiter(",")
.stopThreadOnEOF(false),
threadGroup(1, 1,
_HTTP_HEADERS_GLOBAL,
initializeApplication(baseUrl),
login(baseUrl),
addVehicle(baseUrl),
initialCustomerChecks(baseUrl),
venueDetails(baseUrl),
getCategories(baseUrl),
getSubcategories(baseUrl)
),
resultsTreeVisualizer())
.run();
}
Hello, I don't know what you have in initialCustomerChecks, but I tried with the following simplified version of the flow:
package us.abstracta.jmeter.javadsl;
import static us.abstracta.jmeter.javadsl.JmeterDsl.dummySampler;
import static us.abstracta.jmeter.javadsl.JmeterDsl.ifController;
import static us.abstracta.jmeter.javadsl.JmeterDsl.jsr223Sampler;
import static us.abstracta.jmeter.javadsl.JmeterDsl.resultsTreeVisualizer;
import static us.abstracta.jmeter.javadsl.JmeterDsl.simpleController;
import static us.abstracta.jmeter.javadsl.JmeterDsl.testPlan;
import static us.abstracta.jmeter.javadsl.JmeterDsl.threadGroup;
import org.junit.jupiter.api.Test;
import us.abstracta.jmeter.javadsl.core.controllers.DslSimpleController;
public class PerformanceTest {
private DslSimpleController login() {
return simpleController("SIGN IN",
dummySampler("LOGIN", "OK"),
jsr223Sampler(s -> s.vars.put("VEHICLE_ID", "1"))
);
}
private DslSimpleController addVehicle() {
return simpleController("Add vehicle",
ifController(
"${__groovy(vars['VEHICLE_ID'] == null)}",
dummySampler("INNER", "OK")
)
);
}
private DslSimpleController initialCustomerChecks() {
return simpleController("Customer Checks",
dummySampler("OUTER", "OK")
);
}
@Test
public void test() throws Exception {
testPlan(
threadGroup(1, 1,
login(),
addVehicle(),
initialCustomerChecks()
),
resultsTreeVisualizer()
).run();
}
}
And is working fine:
- When variable is set, then LOGIN & OUTER are executed
- When variable is not set, then LOGIN, INNER & OUTER are executed.
Maybe you are experiencing something related to the extracted variable value?
Have you tried debugging the code? For example adding a jsr223Sampler with a groovy script logging the value of vars['VEHICLE_ID']
? Maybe the value you are expecting is not the actual one returned by the extractor?
@rabelenda As described in the initial issue and further comments, it still doesn't work.
private DslSimpleController addVehicle(String baseUrl) {
return simpleController("Add vehicle",
ifController(
//s->s.vars.get("VEHICLE_ID")==null, <--- WORKING SOLUTION
"${__groovy(vars['VEHICLE_ID'] == null)}", <--- NOT WORKING SOLUTION
httpSampler("Add vehicle", baseUrl + "/api/customer-accounts/${CUSTOMER_ACCOUNT_ID}/vehicles")
.method(HTTPConstants.POST)
.contentType(ContentType.APPLICATION_JSON)
.body("{\n" +
"\t\"brand_and_model\": \"Jeep Wrangler JKU\", \n" +
"\t\"color\": \"black\", \n" +
"\t\"license_plate_number\": \"IS12SNW\"\n" +
"}")
.children(jsonExtractor("VEHICLE_ID", "data.vehicles[0].id"))));
}
Yet the workaround with Java lambda expression solves the problem. Since you cannot replicate this problem, and there's a workaround - I'll close this issue.