51Testing软件测试论坛

标题: Jmeter 插件开发 [打印本页]

作者: CallmeJack    时间: 2018-2-8 13:40
标题: Jmeter 插件开发
一. 配置源码

下载源码包 地址
导入源码包,我这里使用的工具IntelliJ。直接File->open就行。导入后的项目目录如下图:
[attach]110752[/attach]
下载jar包。jar包下载下来的地址为:/lib
[attach]110753[/attach]
添加jar包。File->Project Structure->Libraries
install
[attach]110754[/attach]
运行 src->core->apache.jmeter->NewDriver
  1. public static void main(String[] args) {

  2.     Thread.currentThread().setContextClassLoader(loader);
  3.     if (System.getProperty("log4j.configuration") == null) {// $NON-NLS-1$ $NON-NLS-2$
  4.         File conf = new File(jmDir, "bin" + File.separator + "log4j.conf");// $NON-NLS-1$ $NON-NLS-2$
  5.         System.setProperty("log4j.configuration", "file:" + conf);
  6.     }

  7.     try {
  8.         Class<?> initialClass = loader.loadClass("org.apache.jmeter.JMeter");// $NON-NLS-1$
  9.         Object instance = initialClass.newInstance();
  10.         Method startup = initialClass.getMethod("start", new Class[] { new String[0].getClass() });// $NON-NLS-1$
  11.         startup.invoke(instance, new Object[] { args });
  12.     } catch(Throwable e){
  13.         e.printStackTrace();
  14.         System.err.println("JMeter home directory was detected as: "+jmDir);
  15.     }
  16. }
复制代码
从上述代码中我们可以看出,其实之际上调用的是src->core->apache.jmeter->Jmeter 的start() 方法。
而当我们打开Jmeter的Gui时,实际上调用的用的是src->core->apache.jmeter->Jmeter 的startGui() 方法
  1. private void startGui(String testFile) {
  2.         String jMeterLaf = LookAndFeelCommand.getJMeterLaf();
  3.         try {
  4.             UIManager.setLookAndFeel(jMeterLaf);
  5.         } catch (Exception ex) {
  6.             log.warn("Could not set LAF to:"+jMeterLaf, ex);
  7.         }

  8.         PluginManager.install(this, true);

  9.         JMeterTreeModel treeModel = new JMeterTreeModel();
  10.         JMeterTreeListener treeLis = new JMeterTreeListener(treeModel);
  11.         final ActionRouter instance = ActionRouter.getInstance();
  12.         instance.populateCommandMap();  //这个方法会去寻找<your project>/lib/ext 下所有的jar
  13.         treeLis.setActionHandler(instance);
  14.         // NOTUSED: GuiPackage guiPack =
  15.         GuiPackage.getInstance(treeLis, treeModel);
  16.         MainFrame main = new MainFrame(treeModel, treeLis);
  17.         ComponentUtil.centerComponentInWindow(main, 80);
  18.         main.setVisible(true);
  19.         instance.actionPerformed(new ActionEvent(main, 1, ActionNames.ADD_ALL));
  20.         if (testFile != null) {
  21.             try {
  22.                 File f = new File(testFile);
  23.                 log.info("Loading file: " + f);
  24.                 FileServer.getFileServer().setBaseForScript(f);

  25.                 HashTree tree = SaveService.loadTree(f);

  26.                 GuiPackage.getInstance().setTestPlanFile(f.getAbsolutePath());

  27.                 Load.insertLoadedTree(1, tree);
  28.             } catch (ConversionException e) {
  29.                 log.error("Failure loading test file", e);
  30.                 JMeterUtils.reportErrorToUser(SaveService.CEtoString(e));
  31.             } catch (Exception e) {
  32.                 log.error("Failure loading test file", e);
  33.                 JMeterUtils.reportErrorToUser(e.toString());
  34.             }
  35.         } else {
  36.             JTree jTree = GuiPackage.getInstance().getMainFrame().getTree();
  37.             TreePath path = jTree.getPathForRow(0);
  38.             jTree.setSelectionPath(path);
  39.             FocusRequester.requestFocus(jTree);
  40.         }
  41.     }
复制代码
二.开发sampler

JMeter加载插件的机制比较简单,扫描扩展下的的所有实现了JMeterGUIComponent和TestBean接口的
类,然后进行初始化。
  1. ClassFinder.findClassesThatExtend(
  2.     JMeterUtils.getSearchPaths(),
  3.     new Class[] {JMeterGUIComponent.class, TestBean.class }
复制代码
在getSearchPaths()在这个方法中,它寻找的路径是/lib/ext,所以要确保你开发的插件的jar存在与这
个路径中。
  1. public static String[] getSearchPaths() {
  2.         String p = JMeterUtils.getPropDefault("search_paths", null); // $NON-NLS-1$
  3.         String[] result = new String[1];

  4.         if (p != null) {
  5.             String[] paths = p.split(";"); // $NON-NLS-1$
  6.             result = new String[paths.length + 1];
  7.             System.arraycopy(paths, 0, result, 1, paths.length);
  8.         }
  9.         result[0] = getJMeterHome() + "/lib/ext"; // $NON-NLS-1$
  10.         return result;
  11.     }
复制代码
  1. jmeter提供了example。src/examples,所以在写之前 可以多参考一下

  2. 在src/components/sampler/gui 下新建SmaplerGui,继承AbstractSamplerGui 类。 ```java package org.apache.jmeter.sampler.gui;
  3. import com.btcc.fix.TestUser;
  4. import net.sourceforge.jdatepicker.JDateComponentFactory;
  5. import net.sourceforge.jdatepicker.JDatePanel;
  6. import net.sourceforge.jdatepicker.impl.UtilDateModel;
  7. import org.apache.jmeter.gui.util.HorizontalPanel;
  8. import org.apache.jmeter.gui.util.VerticalPanel;
  9. import org.apache.jmeter.sampler.FixSmapler;
  10. import org.apache.jmeter.sampler.MessageProvider;
  11. import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
  12. import org.apache.jmeter.testelement.TestElement;
  13. import org.apache.jorphan.logging.LoggingManager;
  14. import org.apache.log.Logger;
  15. import quickfix.btcc.Message;

  16. import javax.swing.;
  17. import java.awt.;
  18. import java.awt.event.*;
  19. import java.text.SimpleDateFormat;
  20. import java.util.Date;

  21. import static javax.swing.BorderFactory.createTitledBorder;

  22. /**

  23. Created by sara on 12/10/2016.
  24. */
  25. public class FixSmaplerGui extends AbstractSamplerGui {

  26. private static final Logger log = LoggingManager.getLoggerForClass();

  27. // 布局定义
  28. private JTextField requestNameText = null;
  29. private JTextField hostText = null;
  30. private JTextField portText = null;
  31. private JCheckBox sslCheckBox = null;

  32. public FixSmaplerGui(){
  33. super();
  34. init();
  35. }

  36. //用这个方法将fixSmapler的数据设置到你的gui中
  37. @Override
  38. public void configure(TestElement element) {

  39. super.configure(element);
  40. FixSmapler fixSmapler = (FixSmapler)element;
  41. hostText.setText(fixSmapler.getHost());
  42. portText.setText(fixSmapler.getPort());
  43. sslCheckBox.setSelected(fixSmapler.getSsl());

  44. }

  45. private void init() {
  46. setLayout(new BorderLayout(0, 5));
  47. setBorder(makeBorder());
  48. add(createDataPanel(),BorderLayout.CENTER);
  49. }

  50. // 这个方法是用来创建你自己的元素布局的
  51. private JPanel createDataPanel(){
  52. final JPanel settingPanel = new VerticalPanel(5, 0);
  53. settingPanel.setBorder(makeBorder());
  54. settingPanel.add(makeTitlePanel());

  55. // host
  56. JPanel hostPanel = new HorizontalPanel();
  57. hostPanel.setBorder(createTitledBorder("Host/port"));

  58. JLabel hostLable = new JLabel("Host:");
  59. this.hostText = new JTextField(15);
  60. hostLable.setLabelFor(hostText);
  61. hostPanel.add(hostLable);
  62. hostPanel.add(hostText);

  63. JLabel portLable = new JLabel("Port:");
  64. portText = new JTextField(15);
  65. portLable.setLabelFor(portText);
  66. hostPanel.add(portLable);
  67. hostPanel.add(portText);

  68. JLabel sslLabel = new JLabel("SSL");
  69. sslCheckBox = new JCheckBox();
  70. sslLabel.setLabelFor(sslCheckBox);
  71. hostPanel.add(sslLabel);
  72. hostPanel.add(sslCheckBox);
  73. settingPanel.add(hostPanel);
  74. return settingPanel;

  75. }

  76. // 创建新的sampler。并且将它传给你创建的modifyTestElement(TestElement)方法。
  77. @Override
  78. public TestElement createTestElement() {

  79. TestElement sampler = new FixSmapler();
  80. modifyTestElement(sampler);
  81. return sampler;
  82. }

  83. // 这个方法应该返回代表的component的title/name的名字。fix_sampler_title必须被写进jmeter 的messages.properties文件中。
  84. @Override
  85. public String getLabelResource() {
  86. // TODO Auto-generated method stub
  87. return "fix_sampler_title"; // $NON-NLS-1$
  88. }

  89. // 这个方法是用来将数据从你的gui传到TestElement.这个方法和configure()方法在逻辑上是相反的
  90. @Override
  91. public void modifyTestElement(TestElement element) {
  92. super.configureTestElement(element);
  93. FixSmapler smapler = (FixSmapler) element;
  94. smapler.setHost(hostText.getText());
  95. smapler.setPort(portText.getText());
  96. smapler.setSsl(sslCheckBox.isSelected());

  97. }

  98. // 这个方法是用来在你创建新的sampler时,清除数据的。
  99. @Override
  100. public void clearGui() {
  101. super.clearGui();
  102. hostText.setText("");
  103. portText.setText("");
  104. sslCheckBox.setSelected(false);

  105. }
  106. }
复制代码



作者: CallmeJack    时间: 2018-2-8 13:41
  1. 当是在gui上创建一个sampler,其调用的顺序是**clearGui()->createTestElement()->modifyTestElement()->configure()**

  2. 2. 在src/components/sampler 下新建Smapler,继承AbstractSampler 类。
  3. ```java
  4. import com.btcc.fix.FixClient;
  5. import com.btcc.fix.TestClient;
  6. import org.apache.jmeter.samplers.AbstractSampler;
  7. import org.apache.jmeter.samplers.Entry;
  8. import org.apache.jmeter.samplers.SampleResult;
  9. import org.apache.jmeter.testelement.property.BooleanProperty;
  10. import org.apache.jmeter.testelement.property.IntegerProperty;
  11. import org.apache.jmeter.testelement.property.StringProperty;
  12. import org.apache.jorphan.logging.LoggingManager;
  13. import org.apache.log.Logger;

  14. import java.util.concurrent.CountDownLatch;
  15. import java.util.concurrent.atomic.AtomicInteger;


  16. /**
  17. * Created by sara on 12/10/2016.
  18. */
  19. public class FixSmapler extends AbstractSampler {

  20.     private static final Logger log = LoggingManager.getLoggerForClass();


  21.     private static final String HOST = "Fix.host"; //$NON-NLS-1$
  22.     private static final String PORT = "Fix.port"; //$NON-NLS-1$
  23.     private static final String SSL = "Fix.ssl"; //$NON-NLS-1$

  24.     private static TestClient client = null;
  25.     private static Message request  = null;


  26.     private static AtomicInteger classCount = new AtomicInteger(0); // keep track of classes created

  27.     public FixSmapler() {
  28.        classCount.incrementAndGet();
  29.         trace("FixSmapler()");
  30.     }

  31.     // 这个方法主要是用来执行和收集执行后的result数据的
  32.     @Override
  33.     public SampleResult sample(Entry entry) {
  34.         trace("sample()");
  35.         SampleResult res = new SampleResult();
  36.         boolean isOK = false;

  37.         TestClient c = getClient();
  38.         // 设置结果的名称
  39.         res.setSampleLabel(getTitle());

  40.         // 设置request数据
  41.         res.setSamplerData(request.toString());
  42.         res.sampleStart();

  43.         final CountDownLatch responseLatch = new CountDownLatch(1);

  44.         StringBuffer sb = new StringBuffer();
  45.         FixClient.Callback callback = new FixClient.Callback() {
  46.             @Override
  47.             public void onMessage(quickfix.Message message) {

  48.                 String[] fds = message.toString().split("\\001");

  49.                 for(String fd:fds){
  50.                     sb.append(fd).append("\r\n");
  51.                 }

  52.                 responseLatch.countDown();
  53.             }
  54.         };

  55.         try{

  56.             int count = 0;
  57.             while (!c.connect()){
  58.                 Thread.sleep(1000);

  59.                 count++;

  60.                 if(count >=10){
  61.                     throw new Exception("Fix server can't connect");
  62.                 }
  63.             }

  64.             c.send(request,callback);
  65.             responseLatch.await();
  66.             //设置response数据
  67.             res.setResponseMessage(sb.toString());
  68.             byte[] bytes = sb.toString().getBytes();
  69.             res.setResponseData(bytes);
  70.             res.setDataType(SampleResult.TEXT);
  71.             res.setResponseCodeOK();
  72.             res.setResponseMessage("OK");
  73.             isOK = true;
  74.         }catch (Exception e){
  75.             log.error("send fail: ".concat(e.toString()));
  76.             res.setResponseCode("500");// $NON-NLS-1$
  77.             res.setResponseData(e.toString());
  78.         }finally {
  79.             c.removeCallback(callback);
  80.             c.disconnect();
  81.         }

  82.         res.sampleEnd();

  83.         res.setSuccessful(isOK);
  84.         return  res;
  85.     }
复制代码
执行 ant install
安装过后,你直接运行NewDriver 和 /bin/jmeter 都是可以的。
截图
[attach]110755[/attach]



作者: 梦想家    时间: 2018-2-28 17:13
支持分享
作者: Miss_love    时间: 2020-12-30 08:35
感谢分享




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2