Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability for RegexExtractor to fail sampler result if there is no match #3364

Open
asfimport opened this issue Apr 18, 2014 · 8 comments
Open

Comments

@asfimport
Copy link
Collaborator

Michael Zhilin (Bug 56431):
Often there is need to stop iteration / fail sampler result if RegexExtractor doesn't find matches. To resolve this problem usually we need to add Assertion together with RegexExtractor. It duplicates code, increase processing time and make script's author less happy.

This fix is very simple, it makes RegexExtractor to add Assertion failure in case of regexp mismatch.

Also fix is posted on github: mizhka@47a46ba

Created attachment fix.diff: SVN Diff

fix.diff
Index: src/components/org/apache/jmeter/extractor/RegexExtractor.java
===================================================================
--- src/components/org/apache/jmeter/extractor/RegexExtractor.java	(revision 1588500)
+++ src/components/org/apache/jmeter/extractor/RegexExtractor.java	(working copy)
@@ -23,7 +23,9 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.StringEscapeUtils;
+import org.apache.jmeter.assertions.AssertionResult;
 import org.apache.jmeter.processor.PostProcessor;
 import org.apache.jmeter.samplers.SampleResult;
 import org.apache.jmeter.testelement.AbstractScopedTestElement;
@@ -84,6 +86,10 @@
 
     private static final String UNDERSCORE = "_";  // $NON-NLS-1$
 
+    private static final String FAILIFNOTFOUND = "RegexExtractor.fail_if_not_found";
+    
+    private static final String FAILMESSAGE = "RegexExtractor.fail_message";
+    
     private transient List<Object> template;
 
     /**
@@ -117,6 +123,10 @@
         try {
             pattern = JMeterUtils.getPatternCache().getPattern(regex, Perl5Compiler.READ_ONLY_MASK);
             List<MatchResult> matches = processMatches(pattern, regex, previousResult, matchNumber, vars);
+            
+            if(matches.isEmpty() && isFailIfNotFound()){
+                failResult(previousResult);
+            }
             int prevCount = 0;
             String prevString = vars.get(refName + REF_MATCH_NR);
             if (prevString != null) {
@@ -169,6 +179,14 @@
         }
     }
 
+    private void failResult(SampleResult previousResult){
+        previousResult.setSuccessful(false);
+        AssertionResult res = new AssertionResult(getName());
+        res.setFailure(true);
+        res.setFailureMessage(StringUtils.defaultIfEmpty(getFailMessage(), "Pattern not found - " + getRegex()));
+        previousResult.addAssertionResult(res);
+    }
+    
     private String getInputString(SampleResult result) {
         String inputString = useUrl() ? result.getUrlAsString() // Bug 39707
                 : useHeaders() ? result.getResponseHeaders()
@@ -469,4 +487,21 @@
     public void setUseField(String actionCommand) {
         setProperty(MATCH_AGAINST,actionCommand);
     }
+    
+    public void setFailIfNotFound(Boolean isFailing){
+        log.warn("Setting fail as " + isFailing);
+        setProperty(FAILIFNOTFOUND,isFailing);
+    }
+    
+    public boolean isFailIfNotFound(){
+        return getPropertyAsBoolean(FAILIFNOTFOUND);
+    }
+    
+    public void setFailMessage(String message){
+        setProperty(FAILMESSAGE, message);
+    }
+    
+    public String getFailMessage(){
+        return getPropertyAsString(FAILMESSAGE);
+    }
 }
Index: src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
===================================================================
--- src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java	(revision 1588500)
+++ src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java	(working copy)
@@ -26,6 +26,7 @@
 import javax.swing.BorderFactory;
 import javax.swing.Box;
 import javax.swing.ButtonGroup;
+import javax.swing.JCheckBox;
 import javax.swing.JComponent;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
@@ -68,6 +69,10 @@
     private JRadioButton useMessage;
 
     private ButtonGroup group;
+    
+    private JCheckBox failResult;
+    
+    private JLabeledTextField failMessage;
 
     public RegexExtractorGui() {
         super();
@@ -97,6 +102,8 @@
             defaultField.setText(re.getDefaultValue());
             matchNumberField.setText(re.getMatchNumberAsString());
             refNameField.setText(re.getRefName());
+            failResult.setSelected(re.isFailIfNotFound());
+            failMessage.setText(re.getFailMessage());
         }
     }
 
@@ -127,6 +134,8 @@
             regex.setTemplate(templateField.getText());
             regex.setDefaultValue(defaultField.getText());
             regex.setMatchNumber(matchNumberField.getText());
+            regex.setFailIfNotFound(failResult.isSelected());
+            regex.setFailMessage(failMessage.getText());
         }
     }
 
@@ -154,10 +163,21 @@
         box.add(makeTitlePanel());
         box.add(createScopePanel(true));
         box.add(makeSourcePanel());
+        box.add(makeNotMatch());
         add(box, BorderLayout.NORTH);
         add(makeParameterPanel(), BorderLayout.CENTER);
     }
 
+    private JPanel makeNotMatch(){
+        JPanel panel = new JPanel(new BorderLayout(5, 0));
+        panel.setBorder(BorderFactory.createTitledBorder("Matching options"));
+        failResult = new JCheckBox("Fail if nothing found with message");
+        failMessage = new JLabeledTextField();
+        panel.add(failResult, BorderLayout.WEST);
+        panel.add(failMessage, BorderLayout.CENTER);
+        return panel;
+    }
+    
     private JPanel makeSourcePanel() {
         JPanel panel = new JPanel();
         panel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getResString("regex_source"))); //$NON-NLS-1$

OS: All

@asfimport
Copy link
Collaborator Author

Sebb (migrated from Bugzilla):
The Response Assertion can already do this

@jgaalen
Copy link

jgaalen commented Mar 10, 2023

I'd like to reopen this ticket. It is a great addition. By far in most cases you want the sampler to fail if the regex extraction fails. Adding a response assertion with the exact same match is very unproductive, mostly forgotten and consumes extra resources.
The argument that the response assertion can already do that is irrelevant in my opinion. There are tons of features that can be done by other options.
this feature would be a valuable addition to jmeter without compromising anything

@vlsi
Copy link
Collaborator

vlsi commented Mar 10, 2023

I tend to agree with jgaalen

@vlsi vlsi reopened this Mar 10, 2023
@sginsbourg
Copy link

sginsbourg commented Mar 11, 2023 via email

@jgaalen
Copy link

jgaalen commented Mar 13, 2023

Extractors are not the place to fail a sampler. Their job is strictly to extract. Assertions are the correct place for failing a sampler. Please re-close this ticket.

It might be a bit of a semantic discussion, but it's actually under 'Post Processor', and extracting + failing a request is exactly what a post processor can do.

If a check box with 'Fail if not found' is too much for the extractors, perhaps create a similar post processor which does this: extract and fail if nog found. I think this is an important feature for a performance test tool (all other tools simply support this tho). I have seen tons of scripts made by others and I have never seen people duplicating their extractions to an assertion to make sure it actually extracted a value. If you don't do that, you have the risk that you just continue in the script and send bogus data and let the script fail too late. For the matter of creating sensible scripts, this feature is a must have in my opinion.
On the other hand, some scripts can have very cpu heavy extractors (regex/xml) and you don't want to duplicate them just to make there there's a value, especially when you extract 5+ values. It will drain the cpu because it will do double the work

@jgaalen
Copy link

jgaalen commented Dec 9, 2023

I'd like to bump this ticket. I simply don't agree with the statement that Extractors are not the place to fail a sampler. You have to think of a way to improve the tool in an effective way and how users are using it. Users don't duplicate all extractors to place assertions to fail them once an extract has no match. It is a lot more work, inefficient and error prone. All other tools do have the options to (automatically) fail if the extraction fails, for a good reason.
A simple check box would be a great and simple improvement to save time and have users with not a not of jmeter/performance testing knowledge to create better scripts.

@vlsi
Copy link
Collaborator

vlsi commented Dec 9, 2023

Could you provde a PR?

@jgaalen
Copy link

jgaalen commented Mar 22, 2024

PR here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants