| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| Making a TestBean Plugin For JMeter |
| |
| This component will be a CSV file reading element that will let users easily vary their input |
| data using csv files. |
| |
| 1. Pick a package and make three files: |
| - [ComponentName].java (org.apache.jmeter.config.CSVDataSet.java) |
| - [ComponentName]BeanInfo.java (org.apache.jmeter.config.CSVDataSetBeanInfo.java) |
| - [ComponentName]Resources.properties (org.apache.jmeter.config.CSVDataSetResources.properties) |
| |
| 2. CSVDataSet.java must implement the TestBean interface. In addition, it will extend |
| ConfigTestElement, and implement LoopIterationListener. |
| - TestBean is a marker interface, so there are no methods to implement. |
| - Extending ConfigTestElement will make our component a Config element in a test plan. By |
| extending different abstract classes, you can control the type of element your component will |
| be (ie AbstractSampler, AbstractVisualizer, GenericController, etc - though you can also make |
| different types of elements just by instantiating the right interfaces, the abstract classes can |
| make your life easier). |
| |
| 3. CSVDataSetBeanInfo.java should extend org.apache.jmeter.testbeans.BeanInfoSupport |
| - create a zero-parameter constructor in which we call super(CSVDataSet.class); |
| - we'll come back to this. |
| |
| 4. CSVDataSetResources.properties - blank for now |
| |
| 5. Implement your special logic for you plugin class. |
| - The CSVDataSet will read a single CSV file and will store the values it finds into |
| JMeter's running context. The user will define the file, define the variable names for |
| each "column". The CSVDataSet will open the file when the test starts, and close it |
| when the test ends (thus we implement TestListener). The CSVDataSet will update the |
| contents of the variables for every test thread, and for each iteration through its |
| parent controller, by reading new lines in the file. When we reach the end of the file, |
| we'll start again at the beginning. |
| |
| - When implementing a TestBean, pay careful attention to your properties. These |
| properties will become the basis of a gui form by which users will configure the CSVDataSet |
| element. |
| |
| - Your element will be cloned by JMeter when the test starts. Each thread will get it's own instance. However, you will |
| have a chance to control how the cloning is done - we'll be taking advantage of this for CSVDataSet (since we don't want to open the file X number of times from X number of threads). |
| |
| a. Properties: filename, variableNames. With public getters and setters. |
| - filename is self-explanatory, it will hold the name of the CSV file we'll read |
| - variableNames is a String which will allow a user to enter the names of |
| the variables we'll assign values to. Why a String? Why not a Collection - surely |
| users will need to enter multiple (and unknown number) variable names? True, but |
| if we used a List or Collection, we'd have to write a gui component to handle |
| collections, and I just want to do this quickly. Instead, we'll let users input |
| comma-delimited list of variable names. |
| |
| b. I then implemented the IterationStart method of the LoopIterationListener interface. The point |
| of this "event" is that your component is notified of when the test has entered it's parent |
| controller. For our purposes, every time the CSVDataSet's parent controller is entered, we will |
| read a new line of the data file and set the variables. Thus, for a regular controller, each |
| loop through the test will result in a new set of values being read. For a loop controller, each |
| iteration will do likewise. Every test thread will get different values as well. |
| |
| 6. Setting up your gui elements in CSVDataSetBeanInfo: |
| - You can create groupings for your component's properties. Each grouping you create needs |
| a label and a list of property names to include in that grouping. Ie: |
| |
| createPropertyGroup("csv_data",new String[]{"filename","variableNames"}); |
| |
| Creates a grouping called "csv_data" that will include gui input elements for the |
| "filename" and "variableNames" properties of CSVDataSet. Then, we need to define what kind of |
| properties we want these to be: |
| |
| p = property("filename"); |
| p.setValue(NOT_UNDEFINED, Boolean.TRUE); |
| p.setValue(DEFAULT, ""); |
| p.setValue(NOT_EXPRESSION,Boolean.TRUE); |
| p = property("variableNames"); |
| p.setValue(NOT_UNDEFINED, Boolean.TRUE); |
| p.setValue(DEFAULT, ""); |
| p.setValue(NOT_EXPRESSION,Boolean.TRUE); |
| |
| This essentially creates two properties whose value is not allowed to be null, and whose default |
| values are "". There are several such attributes that can be set for each property. Here is a |
| rundown: |
| |
| NOT_UNDEFINED : The property will not be left null. |
| DEFAULT : A default values must be given if NOT_UNDEFINED is true. |
| NOT_EXPRESSION : The value will not be parsed for functions if this is true. |
| NOT_OTHER : This is not a free form entry field - a list of values has to be provided. |
| TAGS : with a String[] as the value, this sets up a predefined list of acceptable values, and JMeter will create a dropdown select. |
| |
| Additionally, a custom property editor can be specified for a property: |
| |
| p.setPropertyEditorClass(FileEditor.class); |
| |
| This will create a text input plus browse button that opens a dialog for finding a file. |
| |
| Usually, complex property settings are not needed, as now. For a more complex example, look |
| at org.apache.jmeter.protocol.http.sampler.AccessLogSamplerBeanInfo |
| |
| 7. Defining your resource strings. In CSVDataSetResources.properties we have to define all our string |
| resources. To provide translations, one would create additional files such as CSVDataSetResources_ja.properties, and |
| CSVDataSetResources_de.properties. For our component, we must define the following resources: |
| |
| displayName - This will provide a name for the element that will appear in menus. |
| csv_data.displayName - we create a property grouping called "csv_data", so we have to provide a label for the grouping |
| filename.displayName - a label for the filename input element. |
| filename.shortDescription - a tool-tip-like help text blurb. |
| variableNames.displayName - a label for the variable name input element. |
| variableNames.shortDescription - tool tip for the variableNames input element. |
| |
| 8. Debug your component. |