jmeter - 如何使范围报告更容易维护groovy脚本

时间:2017-06-03 19:50:28

标签: jmeter

下面是一个帮助我为jmeter构建范围报告的脚本。它是一个JSR223 PostProcessor元素。然而,它工作得很好,问题是我在脚本中的每个HTTP请求之后都重复了它。我有几个脚本,包含100个HTTP请求,基本上需要同一个PostProcessor groovy脚本的副本。这=很难维护!

我尝试将常用部分拆分为外部groovy脚本,我尝试调用JSR223 PostProcessor。我还尝试了解块脚本并将值放入csv,以便我可以更新csv值,如果有任何更改。

我确定有更清洁/更好的方法来做到这一点,但我还在学习,所以我不确定如何让这更容易维护。这是JSR223 PostProcessor。每个http请求改变的唯一位是" //测试结果"部分

import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

//configure object for response data
def response = prev.getResponseDataAsString();    

//configure extentreports objects
ExtentReports report;
ExtentTest testLogger;

//set location for file and report config
String resultsPath = "C:/portalQA/Automation/Results/";
String configPath = "C:/portalQA/Automation/JMeter/TestReportConfig/";
String reportPath = 
resultsPath+"Login_Results_${reportDate}_${currentTime}_${testenv}.html";

File file = new File(reportPath);

if (!file.exists()) {

    //if file does not exist, create it
    report = new ExtentReports(reportPath, true);
    report.loadConfig( new File(configPath+"extent-config.xml"));
} else {
    //else append to existing report
    report = new ExtentReports(reportPath, false);
    report.loadConfig( new File(configPath+"extent-config.xml"));
}

//test result

testLogger = report.startTest("Authenticate");
testLogger.assignCategory("Initialize Session");
if (response.contains("com.blah.portal.model.User")) {
    testLogger.log(LogStatus.PASS, "Logged in with:  ${username}");
    testLogger.log(LogStatus.INFO, response);
} else {
    testLogger.log(LogStatus.FAIL, "Could not authenticate session");
    testLogger.log(LogStatus.INFO, response);
}

log.info("Authenticate");
print("Authenticate print");            

report.endTest(testLogger);
report.flush();

3 个答案:

答案 0 :(得分:0)

我看到两个选项:

  • 我建议改用JSR223 Listener。首先,这样你的脚本中只有一个侦听器,它可以解决你原来的问题,但是一般来说,这是一个更好的写入文件的选项,因为监听器只有一个实例用于所有正在运行的线程,所以你赢了写入文件时创建竞争条件。

  • 如果您更喜欢使用后处理器,您可以将其置于更高级别(不在任何特定的采样器下),这将导致它在相同范围或以下的每个请求之后运行。

    例如,配置

    Thread Group
        Post-processor
        Sampler 1
        ...
        Sampler N
    

    在每个Post-processor之后运行Sampler 1 ... Sampler N

在这两种情况下,您可能需要检查您正在处理哪个采样器,并跳过那些您不想添加到报告中的采样器(最简单的方法是为排除的采样器提供一些名称约定)< / p>

答案 1 :(得分:0)

我也遇到了同样的挑战。在我的情况下,我需要检查来自REST服务的JSON响应是否正确。我用以下方式解决了它。

enter image description here

我在脚本根目录下创建了 JSR223 PreProcessor 。它包含我的自定义类来处理JSON解析和断言。

import groovy.json.JsonSlurper
import org.apache.jmeter.assertions.AssertionResult

class CustomAssert {

    def parseResponse(json) {
        def jsonSlurper = new JsonSlurper()
        return jsonSlurper.parseText(json)
    }

    def assertResult(assertionResult, expectedResult, actualResult) {
        if (!expectedResult.equals(actualResult)) {
            assertionResult.setFailure(true);
            assertionResult.setFailureMessage("Expected ${expectedResult} but was ${actualResult}");
        }
    }
}

vars.putObject('customAssert', new CustomAssert())

注意最后一行:

vars.putObject('customAssert', new CustomAssert())

我将CustomAssert的实例添加到vars

然后根据我的HTTP请求,我添加了 JSR233断言

def a = vars.getObject('customAssert')
def response = a.parseResponse(prev.getResponseDataAsString())

a.assertResult(AssertionResult, 'DRY', response.sensorResultHolderUIs[0].result.toString())
a.assertResult(AssertionResult, 'DRY', response.sensorResultHolderUIs[1].result.toString())
a.assertResult(AssertionResult, 'DRY', response.sensorResultHolderUIs[2].result.toString())

它基本上从CustomAssert检索vars的实例并调用其方法。我可以根据需要添加尽可能多的 JSR233 Assertion 。唯一复制的代码是顶部的那两行:

def a = vars.getObject('customAssert')
def response = a.parseResponse(prev.getResponseDataAsString())

总结一下:

  1. 获取代码的公共部分(不必复制)。
  2. 将它包裹在课堂上。
  3. 将该类置于根目录下的 JSR233 PreProcessor 中,并通过vars
  4. 导出其实例
  5. 获取其余代码并将其调整为使用2中定义的类。
  6. 将该代码放入尽可能多的 JSR233 Assertion 中,以便记住从vars
  7. 检索3.中创建的实例。

答案 2 :(得分:0)

谢谢user1053510。您的建议引导我构建自己的JSR223监听器来呈现报告。下面是我的JSR223 Listener中的代码:

import com.aventstack.extentreports.*;
import com.aventstack.extentreports.reporter.*;
import com.aventstack.extentreports.markuputils.*;

ExtentHtmlReporter htmlReporter;
ExtentReports extent;
ExtentTest test;

// create the HtmlReporter
htmlReporter = new ExtentHtmlReporter("C:/AUTO_Results/Results_${testApp}_${reportDate}_${currentTime}_${testenv}.html");

//configure report
htmlReporter.config().setCreateOfflineReport(true);
htmlReporter.config().setChartVisibilityOnOpen(true);
htmlReporter.config().setDocumentTitle("${testApp} Results");
htmlReporter.config().setEncoding("utf-8");
htmlReporter.config().setReportName("${testApp} Results ${reportDate}_${currentTime}_${testenv}");
htmlReporter.setAppendExisting(true);

// create ExtentReports
extent = new ExtentReports();

// attach reporter to ExtentReports
extent.attachReporter(htmlReporter);
extent.setReportUsesManualConfiguration(true); 

// Show Env section and set data on dashboard
extent.setSystemInfo("Tool","JMeter");
extent.setSystemInfo("Test Env","${testenv}");
extent.setSystemInfo("Test Date","${reportDate}");
extent.setSystemInfo("Test Time","${currentTime}");

//stringify test info
String threadName = sampler.getThreadName();
String samplerName = sampler.getName();
String requestData = props.get("propRequestData");
String respCode = props.get("propRespCode");
String respMessage = props.get("propRespMessage");
String responseData = props.get("propResponse");


// create test
test = extent.createTest(threadName+" - "+samplerName);
//test.assignCategory("API Testing");

// analyze sampler result
if (vars.get("JMeterThread.last_sample_ok") == "false") {
   log.error("FAILED: "+samplerName);
   print("FAILED: "+samplerName);
   test.fail(MarkupHelper.createLabel("FAILED:  "+sampler.getName(),ExtentColor.RED));

} else if (vars.get("JMeterThread.last_sample_ok") == "true") {
    if(responseData.contains("@error")) {
        log.info("FAILED: "+sampler.getName());
         print("FAILED: "+sampler.getName());
        test.fail(MarkupHelper.createLabel("FAILED:   "+sampler.getName(),ExtentColor.RED));

    } else if (responseData.contains("{")) {
            log.info("Passed: "+sampler.getName());
        print("Passed: "+sampler.getName());
            test.pass(MarkupHelper.createLabel("Passed:   "+sampler.getName(),ExtentColor.GREEN));
    }

} else {
    log.error("Something is really wonky");
    print("Something is really wonky");
    test.fatal("Something is really wonky");
}

//info messages
    test.info("RequestData:   "+requestData);
    test.info("Response Code and Message:    "+respCode+"   "+respMessage);
    test.info("ResponseData:    "+responseData);



//playing around
//markupify json into code blocks
//Markup m = MarkupHelper.createCodeBlock(requestData);
//test.info(MarkupHelper.createModal("Modal text"));
//Markup mCard = MarkupHelper.createCard(requestData, ExtentColor.CYAN);
//   test.info("Request  "+m);
//  test.info(mCard);
//     test.info("Response Data:     "+MarkupHelper.createCodeBlock(props.get("propResponse")));
//   test.info("ASSERTION MESSAGE:     "+props.get("propAssertion"));


// end the reporting and save the file
extent.flush();

然后在每个线程组中,我有一个带有这些行的BeanShell断言:

//request data
String requestData = new String(prev.SamplerData);
//String requestData = new String(requestData);
props.put("propRequestData", requestData);
//response data
String respData = new String(prev.ResponseData);
//String respData = new String(prev.getResponseDataAsString());
props.put("propResponse", respData);
//response code
String respCode = new String(prev.ResponseCode);
props.put("propRespCode",respCode);
//response message
String respMessage = new String(prev.ResponseMessage);
props.put("propRespMessage",respMessage);