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:
Sebastian Bazley 2008-10-10 15:46:34 +00:00
parent c0125b1521
commit f3bca638d4
6 changed files with 298 additions and 7 deletions

View File

@ -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.
*
* 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.
*
* @author Michael Stover
* @version $Revision$
*/
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();
}
}
}

View File

@ -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();
}
}

View File

@ -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\:

View File

@ -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);
}
}

View File

@ -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,16 +532,45 @@ 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);
AssertionResult assertionResult = assertion.getResult(result);
result.setSuccessful(result.isSuccessful() && !(assertionResult.isError() || assertionResult.isFailure()));
result.addAssertionResult(assertionResult);
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(result.isSuccessful()));
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);
}
private void runPostProcessors(List extractors) {

View File

@ -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>