How to handle logical OR operation from cucumber step in java - java

I have a Cucumber step which I want to perform depending on the statement passed in Cucumber step
verify word does exists in log
clear the logs
or I may pass
verify word does not exists in log
not clear the logs
and Gherkin for this would be
("^verify word does(not|) exists in log$")
("^(|not )clear the logs$")
Can I handle this in Java?
I want to perform action depending up on the key I pass

I found the solution, I have done it in Java as below
#Then("^verify word does(not|) exists in log$")
public void verifyLogs(String action) {
switch statement
code logic
//or
if(action.contains("not")){
code logic
}
}

Here is the solution in Ruby, it might give you an idea how to Updat your step and step def.
Step:
And verify word does exist in log
And verify word does not exist in log
Step Def:
And(/^verify word does( not)? exist in log$/) do |negative|
if negative
# negative logic
else
# positive logic
end
end

Based on your examples, I'm assuming you have two different options ("does" or "does not").
You have several options of capturing this in your step definition, for instance
using capture groups:
#Then("^verify word (does|does not) exist in log$")
using regex:
#Then("^verify word (.*) exist in log$")
using Cucumber expressions:
#Then("verify word {string} exist in log")
Next, you'll have to implement the step definition, to do something different depending on whether or not the String you passed contains "not".
public void verifyLogs(String shouldContain) {
if(action.contains("not")){
// call helper method to verify logs **do not** contain the word
}
// call helper method to verify logs **do** contain the word
}
Alternatively, you could use two different step definitions:
#Then("^verify word does exist in log$")
public void verifyLogs(String shouldContain) {
// call helper method to verify logs do contain the word
}
and
#Then("^verify word does not exist in log$")
public void verifyLogs(String shouldContain) {
// call helper method to verify logs **do not** contain the word
}
The upside of the last alternative is that your step definitions will stay very simple / don't contain any logic. The downside ofcourse is you have 2 step definitions, which is not a very big downside imho.

Related

Keep the same case when replacing words in Java

My goal is to correct common grammar errors in messages. Here's what I currently have written:
#EventHandler
public void onChat(AsyncPlayerChatEvent event){
String message = event.getMessage().replaceAll("(?i)dont", "don't")
.replaceAll("(?i)youre", "you're");
event.setMessage(message);
}
This works to replace dont with don't, and youre with you're. The issue is that DONT is replaced with don't, rather than DON'T.
How would I execute this replacement while preserving case?
Use capturing groups:
> "DoNt".replaceAll("(?i)\\b(don)(t)\\b", "$1'$2")
"DoN't" (String)
> "YoUrE".replaceAll("(?i)\\b(you)(re)\\b", "$1'$2")
"YoU'rE" (String)
You should also use \b for a word boundary, so you don't inadvertently change words like "orthodontist" into "orthodon'tist".

Setter not replacing charactes on string

I am writing a setter for a domain class. What is being saved is an xml that is a response from a web service. It includes the first and last name of the user but that information needs to be masked. So i am trying to accomplish that using regex.
I wrote the following setter method:
public void setOnlineRetroCreditResponse(String xml) {
xml.replaceAll (/(?<=lastName=)([^\s]+)/){lastName ->
lastName[0].replace ( lastName[1], "X".multiply (lastName[1].size()))
}
onlineRetroCreditResponse = xml
}
I am expecting a sting like this one: "FFPAccountNumber2=12345 lastName=Doe" to be substituted and saved to the databse like this "FFPAccountNumber2=12345 lastName=XXX" but that is not working as expected. I tested my regex using different online like this one https://www.freeformatter.com/java-regex-tester.html and that does not seem to be the issue.
Any ideas would be appreciated.
There are two things: 1) you do not assign the replaced value back to the xml variable and 2) you are replacing the match explicitly while you can just do the necessary modifications to the value you have captured to return it.
Actually, you do not even need to capture the non-whitespace character chunk, you may access the whole match in the replaceAll callback. Also, you can use \S instead of [^\s].
Use
public void setOnlineRetroCreditResponse(String xml) {
onlineRetroCreditResponse = xml.replaceAll(/(?<=lastName=)\S+/){lastName ->
"X".multiply(lastName[0].size())
}
}

Unable to write a simple step passing a single string as a parameter

I work with JBehave on a daily basis, but have been tasked with working on a project that uses Cucumber. In order to add a custom reporting class functionality to that project, I need to add two steps, one at the start of the feature (story) and another at the start of the scenario. I merely want to pass to the application a description of the feature/story and the scenario to be passed to the reporting module. I know that cucumber can access the scenario name through code, but that would only resolve one of the two lines - I would still need to have another one that passes the description of the feature/story.
What I've tried in the feature file:
Feature: Ecolab BDD Test Automation Demo
Scenario Outline: User can login and logout from the landing page
Given story "EcolabWebDemo_TestCases - Ecolab BDD Test Automation Demo"
Given scenario "User can login and logout from the landing page"
Given I am on the Ecolab landing page
The corresponding code for the two added Given statements at the beginning above:
#Given("^story {string}$") // \"(\\S+)\"
public void givenStory(String storyName) {
test.initStory(storyName); // will show on report in Features column
}
#Given("^scenario {string}$") // \"(\\S+)\"
public void givenScenario(String scenarioName) {
test.initScenario(scenarioName);
}
The commented regex patterns afterwards are the suggested ones I should try but do not seem to work either.
The current configuration at least seems to "find" the steps but reports:
cucumber.runtime.CucumberException:
java.util.regex.PatternSyntaxException: Illegal repetition near index
13 ^the scenario {string}$
So that's obviously not the solution. The regex used instead of {string} simply does not find a match and does not run.
regex is absolute Greek to me, not sure why it can't just be simple like the {string} option implied it would be in the cucumber documentation. I've been searching on-line for guidance for the better part of two days to no avail, I'm apparently not even sure what to be searching for.
Based on Grasshopper's suggestion, I updated the version of Cucumber from 1.2.0 to 1.2.5. I was prepared to change the pom.xml to use the 3.x versions but tried the latest of the specified libraries first, and it did report after an attempted run what the correct regex should be for the two steps I added.
#Given("^story \"([^\"]*)\"$")
and
#Given("^scenario \"([^\"]*)\"$")
Now that the project has a version that seems to recognize strings and also reports the missing steps, the project now runs as intended.
Thanks for your help, Grasshopper.

Selenium Webdriver: Validate the information displayed in Camel case

I am implementing as automation script and following BDD frame work with selenium webdriver.
Acceptance Criteria:
Scenario: Members name
Given that the web page is displayed
When the user clicks anywhere on the member row
Then member First Name, Middle Initial, Last Name will be displayed
And Member First Name, Middle Initial, Last name display in Camel case
Would you pleas let me know how to validate the Camel case for displayed information in web page? Like "Jhon D Hamton".
By using WordUtils in the Apache Commons lang library:
Specifically, the capitalizeFully(String str, char[] delimiters) method should do the job:
String blah = "LORD_OF_THE_RINGS";
assertEquals("LordOfTheRings", WordUtils.capitalizeFully(blah, new char[]{'_'}).replaceAll("_", ""));
Resource Link:
What is the simplest way to convert a Java string from all caps (words separated by underscores) to CamelCase (no word separators)?
Well, assuming you can grab your string, I'd split it then check that the first letter is uppercase:
boolean isCamelCase(String s) {
String[] split_string = s.split(" ");
for(int i=0;i<split_string.length;i++) {
if(!Character.isUpperCase(split_string[i].charAt(0))){
return false;
}
}
return true;
}
If you know how, or are able to get the entire name as a string, you can use the following Regex to assert that it is camel case:
[A-Z]([A-Z0-9]*[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*
This matches strings that start with an uppercase letter, contain only letters and numbers, and contain at least one lowercase letter and at least one other uppercase letter.
For Java, you want to call the String class's matches() method, which returns true or false:
boolean doesItMatch = yourString.matches('theRegexAbove');

Getting qualified method name by the line number

This question is Java and Maven specific. Please note the additional constraints below as they are different from other questions.
I have several Maven (Java) projects to analyze. What I have is:
the source code
maven-compiled Jave code with binaries in target/ folder
The question is:
Given one source code file (.java) and a line number there, how can I get the fully qualified name of the method that spans over that line? If the line is not in a method then just output null. Acceptable languages to implement this are: Java, ruby, or python.
Could you please answer the question in one of the following two ways?
use the binary and extract qualified method name of that line. (This might involve weave in debug info, but that is fine.)
directly use the source file given, try to parse it and use the AST.
Using specific libraries (like BCEL) or any 3rd party ones (as long as they are well documented and usable) are OK, too.
Many many thanks for the huge help!
Unfortunately, your question is full of drawbacks:
You could, of corse, parse the input source (through an Javacc or ANTLR parser) until you reach the desired line. But it seems a waste of effort to parse the same source since you already have the .class files.
So, it seems better to analyze the .class file. But unfortunately, you have no gurantee that this is the class where your line spawns at, because there can be more than one class defined in the same source file.
Augh! That leads me to a kind of complicated solution:
I'll declare a class which will contain all the login:
public class SourceMethodsIndexer
{
private final SortedMap<Integer, List<Method>> indexOfMethodsByFirstLineNumber;
}
The constructor will be like this:
public SourceMethodsIndexer(File sourceFile)
... and should do these tasks:
1.Browse the class directory related to the target package.
File targetPackageDir=getTargetPackageDir(sourceFile);
File[] classFiles=targetPackageDir.listFiles(new FileFilter(){
public boolean accept(File dir, String name){
return name.endsWith(".class");
}
});
2.Use Apache BCEL to collect all the non public classes belonging to your input source file (you can invoke JavaClass.getSourceFileName() to filter classes), plus the public class corresponding to the name of your input source file.
Collection<JavaClass> targetClasses=getNonPublicClasses(classFiles, sourceFile.getName());
targetClasses.add(publicClass);
3.Collect then all the methods in each class.
Set<Method> targetMethods=new HashSet<Method>(1024);
for (JavaClass javaClass:targetClasses)
{
targetMethods.addAll(Arrays.asList(javaClass.getMethods()));
}
4.Now you can either search directly your line number, or index first the methods by line number to access them later more quickly: JavaClass.getMethods()[n].getLineNumberTable().getSourceLine(0) (take care that there could be repeated values).
this.indexOfMethodsByFirstLineNumber=new TreeMap<Integer, List<Method>>((int)(1.7d*methods.size()));
for (Method method: methods)
{
// Note: The -1 in this line stands to make the SortedMap work properly when searching for ranges.
int firstLine=getLineNumberTable().getSourceLine(0)-1;
List<Method> methodsInTheSameLine=indexOfMethodsByFirstLineNumber.get(firstLine);
if (methodsInTheSameLine==null)
{
methodsInTheSameLine=new ArrayList<Method>();
indexOfMethodsByFirstLineNumber.put(firstLine,methodsInTheSameLine);
}
methodsInTheSameLine.add(method);
}
5.Public a method to do the search:
public Method getMethodByLine(int lineNumber)
{
Set<Method> methodsInTheSameLine=this.indexOfMethodsByFirstLineNumber.headMap(lineNumber).lastKey();
if (methodsInTheSameLine.size()==0)
{
// There are no methods method in that line: Absurd.
}
else if (methodsInTheSameLine.size()>1)
{
// There are more than one method in that line. Hardly probable, but possible.
}
else
{
// There is one method in that line:
return methods.get(0);
}
}
There are a number of open source Maven plugins which analyse source code, and report on a per-method basis. A careful study of some of those may be your best bet.
Examples include Checkstyle, FindBugs, PMD, JDepend, JavaNCSS.
Also take a look at SonarQube.

Categories