mirror of https://github.com/apache/jmeter.git
Bug 45903 - allow Assertions to apply to sub-samples
- generic implementation (specific assertions to follow) git-svn-id: https://svn.apache.org/repos/asf/jakarta/jmeter/trunk@703505 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c0125b1521
commit
f3bca638d4
|
|
@ -21,18 +21,26 @@ package org.apache.jmeter.assertions.gui;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
|
||||
import org.apache.jmeter.gui.AbstractJMeterGuiComponent;
|
||||
import org.apache.jmeter.gui.util.MenuFactory;
|
||||
import org.apache.jmeter.testelement.AbstractScopedAssertion;
|
||||
|
||||
/**
|
||||
* This is the base class for JMeter GUI components which manage assertions.
|
||||
*
|
||||
* @author Michael Stover
|
||||
* @version $Revision$
|
||||
* Assertions which can be applied to different scopes (parent, children or both)
|
||||
* need to use the createScopePanel() to add the panel to the GUI, and they also
|
||||
* need to use saveScopeSettings() and showScopeSettings() to keep the test element
|
||||
* and GUI in synch.
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractAssertionGui extends AbstractJMeterGuiComponent {
|
||||
|
||||
private AssertionScopePanel assertionScopePanel;
|
||||
|
||||
/**
|
||||
* When a user right-clicks on the component in the test tree, or selects
|
||||
* the edit menu when the component is selected, the component will be asked
|
||||
|
|
@ -60,4 +68,54 @@ public abstract class AbstractAssertionGui extends AbstractJMeterGuiComponent {
|
|||
public Collection getMenuCategories() {
|
||||
return Arrays.asList(new String[] { MenuFactory.ASSERTIONS });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the scope settings panel.
|
||||
*
|
||||
* @return the scope settings panel
|
||||
*/
|
||||
protected JPanel createScopePanel(){
|
||||
assertionScopePanel = new AssertionScopePanel();
|
||||
return assertionScopePanel;
|
||||
}
|
||||
|
||||
public void clearGui(){
|
||||
super.clearGui();
|
||||
if (assertionScopePanel != null) {
|
||||
assertionScopePanel.clearGui();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the scope settings in the test element.
|
||||
*
|
||||
* @param assertion
|
||||
*/
|
||||
protected void saveScopeSettings(AbstractScopedAssertion assertion) {
|
||||
if (assertionScopePanel.isScopeParent()){
|
||||
assertion.setScopeParent();
|
||||
} else
|
||||
if (assertionScopePanel.isScopeChildren()){
|
||||
assertion.setScopeChildren();
|
||||
} else {
|
||||
assertion.setScopeAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the scope settings from the test element.
|
||||
*
|
||||
* @param assertion
|
||||
*/
|
||||
protected void showScopeSettings(AbstractScopedAssertion assertion) {
|
||||
String scope = assertion.fetchScope();
|
||||
if (assertion.isScopeParent(scope)) {
|
||||
assertionScopePanel.setScopeParent();
|
||||
} else if (assertion.isScopeChildren(scope)){
|
||||
assertionScopePanel.setScopeChildren();
|
||||
} else {
|
||||
assertionScopePanel.setScopeAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.jmeter.assertions.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
|
||||
import org.apache.jmeter.gui.util.HorizontalPanel;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
|
||||
/**
|
||||
* Assertion scope panel for Assertions so users can choose whether
|
||||
* to apply the assertion to the parent sample, the child samples or both.
|
||||
*
|
||||
* This class is a helper class for the AbstractAssertionGui.
|
||||
*
|
||||
*/
|
||||
public class AssertionScopePanel extends JPanel {
|
||||
|
||||
private JRadioButton parentButton;
|
||||
private JRadioButton childButton;
|
||||
private JRadioButton allButton;
|
||||
|
||||
/**
|
||||
* Create a new NamePanel with the default name.
|
||||
*/
|
||||
public AssertionScopePanel() {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the GUI components and layout.
|
||||
*/
|
||||
private void init() {
|
||||
setLayout(new BorderLayout(5, 0));
|
||||
setBorder(BorderFactory.createTitledBorder(JMeterUtils.getResString("assertion_scope"))); //$NON-NLS-1$
|
||||
|
||||
allButton = new JRadioButton(JMeterUtils.getResString("assertion_scope_all"));
|
||||
parentButton = new JRadioButton(JMeterUtils.getResString("assertion_scope_parent"));
|
||||
parentButton.setSelected(true);
|
||||
childButton = new JRadioButton(JMeterUtils.getResString("assertion_scope_children"));
|
||||
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
group.add(allButton);
|
||||
group.add(parentButton);
|
||||
group.add(childButton);
|
||||
JPanel buttonPanel = new HorizontalPanel();
|
||||
buttonPanel.add(parentButton);
|
||||
buttonPanel.add(childButton);
|
||||
buttonPanel.add(allButton);
|
||||
|
||||
add(buttonPanel);
|
||||
}
|
||||
|
||||
public void clearGui() {
|
||||
parentButton.setSelected(true);
|
||||
}
|
||||
|
||||
public int getSelection(){
|
||||
if (parentButton.isSelected()){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void setScopeAll() {
|
||||
allButton.setSelected(true);
|
||||
}
|
||||
|
||||
public void setScopeChildren() {
|
||||
childButton.setSelected(true);
|
||||
}
|
||||
|
||||
public void setScopeParent() {
|
||||
parentButton.setSelected(true);
|
||||
}
|
||||
|
||||
public boolean isScopeParent() {
|
||||
return parentButton.isSelected();
|
||||
}
|
||||
|
||||
public boolean isScopeChildren() {
|
||||
return childButton.isSelected();
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +72,10 @@ assertion_not=Not
|
|||
assertion_pattern_match_rules=Pattern Matching Rules
|
||||
assertion_patterns_to_test=Patterns to Test
|
||||
assertion_resp_field=Response Field to Test
|
||||
assertion_scope=Which samples to test
|
||||
assertion_scope_all=Main sample and sub-samples
|
||||
assertion_scope_children=Sub-samples only
|
||||
assertion_scope_parent=Main sample only
|
||||
assertion_substring=Substring
|
||||
assertion_text_resp=Text Response
|
||||
assertion_textarea_label=Assertions\:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.jmeter.testelement;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Super-class for all Assertions that can be applied to main sample, sub-samples or both.
|
||||
* Test elements merely need to extend this class to support scoping.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Their corresponding GUI classes need to add the AssertionScopePanel to the GUI
|
||||
* using the AbstractAssertionGui methods:
|
||||
* <ul>
|
||||
* <li>createScopePanel()</li>
|
||||
* <li>saveScopeSettings()</li>
|
||||
* <li>showScopeSettings()</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public abstract class AbstractScopedAssertion extends AbstractTestElement {
|
||||
|
||||
private static final String SCOPE = "Assertion.scope";
|
||||
private static final String SCOPE_PARENT = "parent";
|
||||
private static final String SCOPE_CHILDREN = "children";
|
||||
private static final String SCOPE_ALL = "all";
|
||||
|
||||
/**
|
||||
* Get the scope setting
|
||||
* @return the scope, default parent
|
||||
*/
|
||||
public String fetchScope() {
|
||||
return getPropertyAsString(SCOPE, SCOPE_PARENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the assertion to be applied to the main (parent) sample?
|
||||
*
|
||||
* @param scope
|
||||
* @return if the assertion is to be applied to the parent sample.
|
||||
*/
|
||||
public boolean isScopeParent(String scope) {
|
||||
return scope.equals(SCOPE_PARENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the assertion to be applied to the sub-samples (children)?
|
||||
*
|
||||
* @param scope
|
||||
* @return if the assertion is to be applied to the children.
|
||||
*/
|
||||
public boolean isScopeChildren(String scope) {
|
||||
return scope.equals(SCOPE_CHILDREN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the assertion to be applied to the all samples?
|
||||
*
|
||||
* @param scope
|
||||
* @return if the assertion is to be applied to the all samples.
|
||||
*/
|
||||
public boolean isScopeAll(String scope) {
|
||||
return scope.equals(SCOPE_ALL);
|
||||
}
|
||||
|
||||
public void setScopeParent() {
|
||||
removeProperty(SCOPE);
|
||||
}
|
||||
|
||||
public void setScopeChildren() {
|
||||
setProperty(SCOPE, SCOPE_CHILDREN);
|
||||
}
|
||||
|
||||
public void setScopeAll() {
|
||||
setProperty(SCOPE, SCOPE_ALL);
|
||||
}
|
||||
}
|
||||
|
|
@ -39,6 +39,7 @@ import org.apache.jmeter.samplers.SampleListener;
|
|||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.samplers.Sampler;
|
||||
import org.apache.jmeter.testbeans.TestBeanHelper;
|
||||
import org.apache.jmeter.testelement.AbstractScopedAssertion;
|
||||
import org.apache.jmeter.testelement.AbstractTestElement;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jmeter.testelement.TestListener;
|
||||
|
|
@ -531,17 +532,46 @@ public class JMeterThread implements Runnable {
|
|||
log.info("Stop Thread detected by thread " + threadName);
|
||||
}
|
||||
|
||||
private void checkAssertions(List assertions, SampleResult result) {
|
||||
private void checkAssertions(List assertions, SampleResult parent) {
|
||||
Iterator iter = assertions.iterator();
|
||||
while (iter.hasNext()) {
|
||||
Assertion assertion = (Assertion) iter.next();
|
||||
TestBeanHelper.prepare((TestElement) assertion);
|
||||
if (assertion instanceof AbstractScopedAssertion){
|
||||
AbstractScopedAssertion scopedAssertion = (AbstractScopedAssertion) assertion;
|
||||
String scope = scopedAssertion.fetchScope();
|
||||
if (scopedAssertion.isScopeParent(scope) || scopedAssertion.isScopeAll(scope)){
|
||||
processAssertion(parent, assertion);
|
||||
}
|
||||
if (scopedAssertion.isScopeChildren(scope) || scopedAssertion.isScopeAll(scope)){
|
||||
SampleResult children[] = parent.getSubResults();
|
||||
boolean childError = false;
|
||||
for (int i=0;i <children.length; i++){
|
||||
processAssertion(children[i], assertion);
|
||||
if (!children[i].isSuccessful()){
|
||||
childError = true;
|
||||
}
|
||||
}
|
||||
// If parent is OK, but child failed, add a message and flag the parent as failed
|
||||
if (childError && parent.isSuccessful()) {
|
||||
AssertionResult assertionResult = new AssertionResult(((AbstractTestElement)assertion).getName());
|
||||
assertionResult.setResultForFailure("One or more sub-samples failed");
|
||||
parent.addAssertionResult(assertionResult);
|
||||
parent.setSuccessful(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
processAssertion(parent, assertion);
|
||||
}
|
||||
}
|
||||
threadContext.getVariables().put(LAST_SAMPLE_OK, Boolean.toString(parent.isSuccessful()));
|
||||
}
|
||||
|
||||
private void processAssertion(SampleResult result, Assertion assertion) {
|
||||
AssertionResult assertionResult = assertion.getResult(result);
|
||||
result.setSuccessful(result.isSuccessful() && !(assertionResult.isError() || assertionResult.isFailure()));
|
||||
result.addAssertionResult(assertionResult);
|
||||
}
|
||||
threadContext.getVariables().put(LAST_SAMPLE_OK, Boolean.toString(result.isSuccessful()));
|
||||
}
|
||||
|
||||
private void runPostProcessors(List extractors) {
|
||||
ListIterator iter;
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ Moved the Scoping Rules sub-section from Section 3. "Building a Test Plan" to S
|
|||
<li>Bug 45479 - Support for multiple HTTP Header Manager nodes</li>
|
||||
<li>Bug 43119 - Save Responses to file: optionally omit the file number</li>
|
||||
<li>Allow If Controller to use variable expressions (not just Javascript)</li>
|
||||
<li>Bug 45903 - allow Assertions to apply to sub-samples</li>
|
||||
</ul>
|
||||
|
||||
<h3>Non-functional changes</h3>
|
||||
|
|
|
|||
Loading…
Reference in New Issue