--- xdocs/changes.xml (date 1510611537000) +++ xdocs/changes.xml (date 1510663205000) @@ -155,6 +155,7 @@
  • 61697Introduce Darcula Look And Feel to make JMeter UI more attractive
  • 61704Toolbar : Improve a bit the right part
  • 61731Enhance Test plan Backup with option to save before run. Based on a contribution by orimarko at gmail.com
  • +
  • Drop Workbench from test tree. Implemented by Artem Fedorov (artem at blazemeter.com) and contributed by BlazeMeter Ltd.
  • Non-functional changes --- docs/usermanual/build-test-plan.html (date 1510611537000) +++ docs/usermanual/build-test-plan.html (date 1510663205000) @@ -229,10 +229,6 @@ you can save test tree fragments and individual elements for later use.

    -
    -
    By default, the workbench is not automatically saved with the test plan, but it can be saved by checking "Save Workbench" option on Workbench element.
    -
    - --- xdocs/usermanual/build-test-plan.xml (date 1510611537000) +++ xdocs/usermanual/build-test-plan.xml (date 1510663205000) @@ -53,7 +53,6 @@ JMeter will save the element selected, plus all child elements beneath it. In this way, you can save test tree fragments and individual elements for later use.

    -By default, the workbench is not automatically saved with the test plan, but it can be saved by checking "Save Workbench" option on Workbench element. --- docs/usermanual/component_reference.html (date 1510611537000) +++ docs/usermanual/component_reference.html (date 1510663205000) @@ -591,9 +591,6 @@ Thread Group
  • -WorkBench -
  • -
  • SSL Manager
  • @@ -6556,9 +6553,6 @@
    Screenshot of Control-Panel of Module Controller
    -
    -
    The Module Controller should not be used with remote testing or non-gui testing in conjunction with Workbench components since the Workbench test elements are not part of test plan .jmx files. Any such test will fail.
    -

    Parameters @@ -16026,66 +16020,6 @@
    No

    - -
    -^ -
    - - - -
    -

    WorkBench -

    -
    - -

    The WorkBench simply provides a place to temporarily store test elements while not in use, for copy/paste purposes, or any other purpose you desire. -When you save your test plan, WorkBench items are not saved with it by default unless you check "Save Workbench" option. -Your WorkBench can be saved independently, if you like (right-click on WorkBench and choose Save).

    - -

    Certain test elements are only available on the WorkBench:

    - - - -
    -

    - Parameters -

    -
    -
    Attribute
    -
    Description
    -
    Required
    -
    - -
    -
    Save WorkBench
    -
    - Allow to save the WorkBench's elements into the JMX file. -
    -
    No
    -
    - -
    - -
    -
    -
    -Screenshot for Control-Panel of WorkBench -
    Screenshot of Control-Panel of WorkBench
    -
    ^ --- xdocs/usermanual/component_reference.xml (date 1510611537000) +++ xdocs/usermanual/component_reference.xml (date 1510663205000) @@ -2482,7 +2482,6 @@ otherwise a duplicate may be accidentally created when new elements are added to the test plan.

    -The Module Controller should not be used with remote testing or non-gui testing in conjunction with Workbench components since the Workbench test elements are not part of test plan .jmx files. Any such test will fail. Descriptive name for this controller that is shown in the tree. The module controller provides a list of all controllers loaded into the gui. Select @@ -6374,24 +6373,6 @@ - - -

    The WorkBench simply provides a place to temporarily store test elements while not in use, for copy/paste purposes, or any other purpose you desire. -When you save your test plan, WorkBench items are not saved with it by default unless you check "Save Workbench" option. -Your WorkBench can be saved independently, if you like (right-click on WorkBench and choose Save).

    -

    Certain test elements are only available on the WorkBench:

    -
      -
    • -
    • -
    • -
    - - - Allow to save the WorkBench's elements into the JMX file. - - -
    -

    --- src/core/org/apache/jmeter/gui/action/Load.java (date 1510611537000) +++ src/core/org/apache/jmeter/gui/action/Load.java (date 1510663205000) @@ -38,7 +38,6 @@ import org.apache.jmeter.services.FileServer; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; -import org.apache.jmeter.testelement.WorkBench; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.collections.HashTree; import org.slf4j.Logger; @@ -181,7 +180,7 @@ if (merging){ // Check if target of merge is reasonable final TestElement te = (TestElement)tree.getArray()[0]; - if (!(te instanceof WorkBench || te instanceof TestPlan)){// These are handled specially by addToTree + if (!(te instanceof TestPlan)){// These are handled specially by addToTree final boolean ok = MenuFactory.canAddTo(guiInstance.getCurrentNode(), te); if (!ok){ String name = te.getName(); --- src/core/org/apache/jmeter/gui/action/Move.java (date 1510611537000) +++ src/core/org/apache/jmeter/gui/action/Move.java (date 1510663205000) @@ -33,7 +33,6 @@ import org.apache.jmeter.gui.util.MenuFactory; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; -import org.apache.jmeter.testelement.WorkBench; /** * Move a node up/down/left/right @@ -120,7 +119,7 @@ private JMeterTreeNode getParentNode(JMeterTreeNode currentNode) { JMeterTreeNode parentNode = (JMeterTreeNode) currentNode.getParent(); TestElement te = currentNode.getTestElement(); - if (te instanceof TestPlan || te instanceof WorkBench) { + if (te instanceof TestPlan) { parentNode = null; // So elements can only be added as children } return parentNode; --- src/core/org/apache/jmeter/gui/action/Save.java (date 1510611537000) +++ src/core/org/apache/jmeter/gui/action/Save.java (date 1510663205000) @@ -50,7 +50,6 @@ import org.apache.jmeter.services.FileServer; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; -import org.apache.jmeter.testelement.WorkBench; import org.apache.jmeter.threads.ThreadGroup; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.collections.HashTree; @@ -163,13 +162,7 @@ } } else { fullSave = true; - HashTree testPlan = GuiPackage.getInstance().getTreeModel().getTestPlan(); - // If saveWorkBench - if (isWorkbenchSaveable()) { - HashTree workbench = GuiPackage.getInstance().getTreeModel().getWorkBench(); - testPlan.add(workbench); - } - subTree = testPlan; + subTree = GuiPackage.getInstance().getTreeModel().getTestPlan(); } String updateFile = GuiPackage.getInstance().getTestPlanFile(); @@ -225,10 +218,6 @@ if (fullSave) { // Only update the stored copy of the tree for a full save FileServer.getFileServer().setScriptName(new File(updateFile).getName()); subTree = GuiPackage.getInstance().getTreeModel().getTestPlan(); // refetch, because convertSubTree affects it - if (isWorkbenchSaveable()) { - HashTree workbench = GuiPackage.getInstance().getTreeModel().getWorkBench(); - subTree.add(workbench); - } ActionRouter.getInstance().doActionNow(new ActionEvent(subTree, e.getID(), ActionNames.SUB_TREE_SAVED)); } @@ -396,13 +385,6 @@ .orElse(0); } - /** - * check if the workbench should be saved - */ - private boolean isWorkbenchSaveable() { - JMeterTreeNode workbenchNode = (JMeterTreeNode) ((JMeterTreeNode) GuiPackage.getInstance().getTreeModel().getRoot()).getChildAt(1); - return ((WorkBench) workbenchNode.getUserObject()).getSaveWorkBench(); - } /** * Check nodes does not contain a node of type TestPlan or ThreadGroup --- src/core/org/apache/jmeter/gui/util/MenuFactory.java (date 1510611537000) +++ src/core/org/apache/jmeter/gui/util/MenuFactory.java (date 1510663205000) @@ -53,7 +53,6 @@ import org.apache.jmeter.testbeans.gui.TestBeanGUI; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; -import org.apache.jmeter.testelement.WorkBench; import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.visualizers.Printable; import org.apache.jorphan.gui.GuiUtils; @@ -616,9 +615,6 @@ if (null == parentNode) { return false; } - if (foundClass(nodes, new Class[]{WorkBench.class})){// Can't add a Workbench anywhere - return false; - } if (foundClass(nodes, new Class[]{TestPlan.class})){// Can't add a TestPlan anywhere return false; } @@ -632,9 +628,11 @@ return false; } - if (parent instanceof WorkBench) {// allow everything else - return true; + // Cannot move Non-Test Elements from root of Test Plan + if (!(parent instanceof TestPlan) && foundMenuCategories(nodes, NON_TEST_ELEMENTS)) { + return false; } + if (parent instanceof TestPlan) { if (foundClass(nodes, new Class[]{Sampler.class, Controller.class}, // Samplers and Controllers need not apply ... @@ -657,6 +655,7 @@ } return true; } + // All other return false; } @@ -672,6 +671,18 @@ } return false; } + + // Is any node an instance of one of the menu category? + private static boolean foundMenuCategories(JMeterTreeNode[] nodes, String category) { + for (JMeterTreeNode node : nodes) { + for (String c : node.getMenuCategories()) { + if (category.equals(c)) { + return true; + } + } + } + return false; + } // Is any node an instance of one of the classes, but not an exception? private static boolean foundClass(JMeterTreeNode[] nodes, Class[] classes, Class except) { --- src/core/org/apache/jmeter/gui/action/CheckDirty.java (date 1510611537000) +++ src/core/org/apache/jmeter/gui/action/CheckDirty.java (date 1510663205000) @@ -28,7 +28,6 @@ import org.apache.jmeter.gui.GuiPackage; import org.apache.jmeter.gui.tree.JMeterTreeNode; import org.apache.jmeter.testelement.TestElement; -import org.apache.jmeter.testelement.WorkBench; import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.HashTreeTraverser; import org.apache.jorphan.collections.ListedHashTree; @@ -91,9 +90,6 @@ } else if (action.equals(ActionNames.ADD_ALL)) { previousGuiItems.clear(); GuiPackage.getInstance().getTreeModel().getTestPlan().traverse(this); - if (isWorkbenchSaveable()) { - GuiPackage.getInstance().getTreeModel().getWorkBench().traverse(this); - } } else if (action.equals(ActionNames.CHECK_REMOVE) || action.equals(ActionNames.CHECK_CUT)) { GuiPackage guiPackage = GuiPackage.getInstance(); @@ -118,9 +114,6 @@ //remember previousGuiItems.clear(); GuiPackage.getInstance().getTreeModel().getTestPlan().traverse(this); - if (isWorkbenchSaveable()) { - GuiPackage.getInstance().getTreeModel().getWorkBench().traverse(this); - } } else { dirty = false; @@ -129,13 +122,6 @@ HashTree wholeTree = GuiPackage.getInstance().getTreeModel().getTestPlan(); wholeTree.traverse(this); - // check the workbench for modification - if(!dirty) { // NOSONAR - if (isWorkbenchSaveable()) { - HashTree workbench = GuiPackage.getInstance().getTreeModel().getWorkBench(); - workbench.traverse(this); - } - } } finally { checkMode = false; } @@ -143,13 +129,6 @@ GuiPackage.getInstance().setDirty(dirty); } - /** - * check if the workbench should be saved - */ - private boolean isWorkbenchSaveable() { - JMeterTreeNode workbenchNode = (JMeterTreeNode) ((JMeterTreeNode) GuiPackage.getInstance().getTreeModel().getRoot()).getChildAt(1); - return ((WorkBench) workbenchNode.getUserObject()).getSaveWorkBench(); - } /** * The tree traverses itself depth-first, calling addNode for each --- src/core/org/apache/jmeter/control/gui/TestPlanGui.java (date 1510611537000) +++ src/core/org/apache/jmeter/control/gui/TestPlanGui.java (date 1510663205000) @@ -92,6 +92,7 @@ JMenu addMenu = new JMenu(JMeterUtils.getResString("add")); // $NON-NLS-1$ addMenu.add(MenuFactory.makeMenu(MenuFactory.THREADS, ActionNames.ADD)); addMenu.add(MenuFactory.makeMenu(MenuFactory.FRAGMENTS, ActionNames.ADD)); + addMenu.add(MenuFactory.makeMenu(MenuFactory.NON_TEST_ELEMENTS, ActionNames.ADD)); addMenu.add(MenuFactory.makeMenu(MenuFactory.CONFIG_ELEMENTS, ActionNames.ADD)); addMenu.add(MenuFactory.makeMenu(MenuFactory.TIMERS, ActionNames.ADD)); addMenu.add(MenuFactory.makeMenu(MenuFactory.PRE_PROCESSORS, ActionNames.ADD)); --- src/core/org/apache/jmeter/control/gui/WorkBenchGui.java (date 1510611537000) +++ src/core/org/apache/jmeter/control/gui/WorkBenchGui.java (date 1510663205000) @@ -38,6 +38,7 @@ * preparations for the test plan. * */ +@Deprecated public class WorkBenchGui extends AbstractJMeterGuiComponent { private static final long serialVersionUID = 240L; // This check-box defines whether to save WorkBench content or not --- src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java (date 1510611537000) +++ src/core/org/apache/jmeter/gui/tree/JMeterTreeModel.java (date 1510663205000) @@ -18,6 +18,7 @@ package org.apache.jmeter.gui.tree; +import java.util.Collection; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; @@ -25,11 +26,13 @@ import javax.swing.tree.DefaultTreeModel; import org.apache.jmeter.config.gui.AbstractConfigGui; +import org.apache.jmeter.control.TestFragmentController; +import org.apache.jmeter.control.gui.TestFragmentControllerGui; import org.apache.jmeter.control.gui.TestPlanGui; -import org.apache.jmeter.control.gui.WorkBenchGui; import org.apache.jmeter.exceptions.IllegalUserActionException; import org.apache.jmeter.gui.GuiPackage; import org.apache.jmeter.gui.JMeterGUIComponent; +import org.apache.jmeter.gui.util.MenuFactory; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; import org.apache.jmeter.testelement.WorkBench; @@ -40,13 +43,13 @@ private static final long serialVersionUID = 240L; - public JMeterTreeModel(TestElement tp, TestElement wb) { - super(new JMeterTreeNode(wb, null)); - initTree(tp,wb); + public JMeterTreeModel(TestElement tp) { + super(new JMeterTreeNode(tp, null)); + initTree(tp); } public JMeterTreeModel() { - this(new TestPlanGui().createTestElement(),new WorkBenchGui().createTestElement()); + this(new TestPlanGui().createTestElement()); } /** @@ -57,7 +60,7 @@ */ @Deprecated public JMeterTreeModel(Object o) { - this(new TestPlan(),new WorkBench()); + this(new TestPlan()); } /** @@ -90,13 +93,11 @@ * current * @param current * The node in which the subTree is to be inserted. - * Will be overridden, when an instance of {@link TestPlan} or - * {@link WorkBench} is found in the subtree. + * Will be overridden, when an instance of {@link TestPlan} * @return newly created sub tree now found at current * @throws IllegalUserActionException * when current is not an instance of * {@link AbstractConfigGui} and no instance of {@link TestPlan} - * or {@link WorkBench} could be found in the * subTree */ public HashTree addSubTree(HashTree subTree, JMeterTreeNode current) throws IllegalUserActionException { @@ -112,11 +113,11 @@ userObject.setSerialized(tp.isSerialized()); addSubTree(subTree.getTree(item), current); } else if (item instanceof WorkBench) { - current = (JMeterTreeNode) ((JMeterTreeNode) getRoot()).getChildAt(1); - final TestElement testElement = (TestElement) current.getUserObject(); - testElement.addTestElement(item); - testElement.setName(item.getName()); - addSubTree(subTree.getTree(item), current); + //Move item from WorkBench to TestPlan + HashTree workbenchTree = subTree.getTree(item); + if (workbenchTree.size() > 0) { + moveWorkBenchToTestPlan(current, workbenchTree); + } } else { addSubTree(subTree.getTree(item), addComponent(item, current)); } @@ -164,7 +165,7 @@ } public void removeNodeFromParent(JMeterTreeNode node) { - if (!(node.getUserObject() instanceof TestPlan) && !(node.getUserObject() instanceof WorkBench)) { + if (!(node.getUserObject() instanceof TestPlan)) { super.removeNodeFromParent(node); } } @@ -218,13 +219,6 @@ return getCurrentSubTree((JMeterTreeNode) ((JMeterTreeNode) this.getRoot()).getChildAt(0)); } - /** - * Get the {@link WorkBench} from the root of this tree - * @return The {@link WorkBench} found at the root of this tree - */ - public HashTree getWorkBench() { - return getCurrentSubTree((JMeterTreeNode) ((JMeterTreeNode) this.getRoot()).getChildAt(1)); - } /** * Clear the test plan, and use default node for test plan and workbench. @@ -252,23 +246,66 @@ children = getChildCount(getRoot()); } // Init the tree - initTree(testPlan,new WorkBenchGui().createTestElement()); // Assumes this is only called from GUI mode + initTree(testPlan); // Assumes this is only called from GUI mode } /** * Initialize the model with nodes for testplan and workbench. * * @param tp the element to use as testplan - * @param wb the element to use as workbench */ - private void initTree(TestElement tp, TestElement wb) { + private void initTree(TestElement tp) { // Insert the test plan node insertNodeInto(new JMeterTreeNode(tp, this), (JMeterTreeNode) getRoot(), 0); - // Insert the workbench node - insertNodeInto(new JMeterTreeNode(wb, this), (JMeterTreeNode) getRoot(), 1); // Let others know that the tree content has changed. // This should not be necessary, but without it, nodes are not shown when the user // uses the Close menu item nodeStructureChanged((JMeterTreeNode)getRoot()); } + + + /** + * Move all Non-Test Elements from WorkBench to TestPlan root. + * Other Test Elements will be move to WorkBench Test Fragment in TestPlan + * @param current - TestPlan root + * @param workbenchTree - WorkBench hash tree + */ + private void moveWorkBenchToTestPlan(JMeterTreeNode current, HashTree workbenchTree) throws IllegalUserActionException { + Object[] workbenchTreeArray = workbenchTree.getArray(); + for (Object node : workbenchTreeArray) { + if (isNonTestElement(node)) { + HashTree subtree = workbenchTree.getTree(node); + workbenchTree.remove(node); + HashTree tree = new HashTree(); + tree.add(node); + tree.add(node, subtree); + ((TestElement) node).setProperty(TestElement.ENABLED, false); + addSubTree(tree, current); + } + } + + if (workbenchTree.size() > 0) { + HashTree testFragmentTree = new HashTree(); + TestFragmentController testFragmentController = new TestFragmentController(); + testFragmentController.setProperty(TestElement.NAME, "WorkBench Test Fragment"); + testFragmentController.setProperty(TestElement.GUI_CLASS, TestFragmentControllerGui.class.getName()); + testFragmentController.setProperty(TestElement.ENABLED, false); + testFragmentTree.add(testFragmentController); + testFragmentTree.add(testFragmentController, workbenchTree); + addSubTree(testFragmentTree, current); + } + } + + private boolean isNonTestElement(Object node) { + JMeterTreeNode treeNode = new JMeterTreeNode((TestElement) node, null); + Collection categories = treeNode.getMenuCategories(); + if (categories != null) { + for (String category : categories) { + if (MenuFactory.NON_TEST_ELEMENTS.equals(category)) { + return true; + } + } + } + return false; + } } --- src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java (date 1510611537000) +++ src/protocol/http/org/apache/jmeter/protocol/http/proxy/ProxyControl.java (date 1510663205000) @@ -83,7 +83,6 @@ import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; import org.apache.jmeter.testelement.TestStateListener; -import org.apache.jmeter.testelement.WorkBench; import org.apache.jmeter.testelement.property.BooleanProperty; import org.apache.jmeter.testelement.property.CollectionProperty; import org.apache.jmeter.testelement.property.IntegerProperty; @@ -1055,7 +1054,6 @@ *

  • The controller specified by the target property. *
  • If none was specified, the first RecordingController in the tree. *
  • If none is found, the first AbstractThreadGroup in the tree. - *
  • If none is found, the Workspace. * * * @return the tree node for the controller where the proxy must store the @@ -1073,10 +1071,6 @@ myTarget = findFirstNodeOfType(AbstractThreadGroup.class); if (myTarget != null) { return myTarget; - } - myTarget = findFirstNodeOfType(WorkBench.class); - if (myTarget != null) { - return myTarget; } log.error("Program error: test script recording target not found."); return null; --- src/protocol/http/org/apache/jmeter/protocol/http/proxy/gui/ProxyControlGui.java (date 1510611537000) +++ src/protocol/http/org/apache/jmeter/protocol/http/proxy/gui/ProxyControlGui.java (date 1510663205000) @@ -77,7 +77,6 @@ import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; -import org.apache.jmeter.testelement.WorkBench; import org.apache.jmeter.testelement.property.PropertyIterator; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.exec.KeyToolUtils; @@ -1131,7 +1130,7 @@ targetNodesModel.addElement(tnw); name.append(separator); buildNodesModel(cur, name.toString(), level + 1); - } else if (te instanceof TestPlan || te instanceof WorkBench) { + } else if (te instanceof TestPlan) { name.append(cur.getName()); name.append(separator); buildNodesModel(cur, name.toString(), 0);