I have a Cucumber step that looks like this:
When I enter the credentials for the user
and another that says
When I enter the correct credentials for the user
Corresponding step definitions are:
#When("I enter the ([^\"]*) for the user$")
public void stepDefinition(String cred){
//code
}
#When("I enter the correct ([^\"]*) for the user$")
public void otherStepDefinition(String cred){
//other code
}
But my second cucumber step ("I enter the correct credentials for the user") is matched by the first step definition, only with the word "correct" added to the credentials.
How do I fix this?
I'm new to regex. Would it be possible to exclude the "correct" part from the 'When' step so I could have a basic step that could be 'extended' with the "correct" part?
The first rule should be changed to
#When("I enter the (\\S+) for the user$")
Here, \S+ matches 1 or more non-whitespace characters. If there can be no non-whitespace chars use \S*.
To match two "words" you may use
#When("I enter the (\\S+\\s+\\S+) for the user$")
Note that you may control the number of "words" using quantifiers, e.g. this will match 2 or 3 words:
#When("I enter the (\\S+(?:\\s+\\S+){1,2}) for the user$")
To match 2 or more words:
#When("I enter the (\\S+(?:\\s+\\S+){1,}) for the user$")
#When("I enter the (\\S+(?:\\s+\\S+)+) for the user$")
There are a couple of ways you could improve these steps and avoid the use of regex.
1) Have the user know its credentials and have the step ask the user for the credentials
So you would have
Given I am a user
#user = create_user # method creates a user with credentials
end
When `I enter the users credentials` do
fill_in username: #user.username
fill_in password: #user.password
end
When `I enter the wrong credentials for the user` do
fill_in username: #user.username
fill_in password: #user.bad_password # or perhaps just bad_password
end
this approach removes all the complexity from cucumber and places it in the helper methods you are calling to create a user.
2) Have more arguments for your step definition
When 'I enter the credentials user: (\\S+) password: (\\S+) do |username, password|
fill_in username: username
fill_in password: password
end
When 'I enter the bad credentials user: (\\S+) password: (\\S+) do |username, password|
fill_in username: username
fill_in password: password
end
I strongly prefer the first approach, you should keep features and scenarios super simple and push complexity down to code. Code is much better at dealing with complexity than Cucumber.
I've been cuking since before Cucumber was named, and now never use regex's or scenario outlines when I cuke. You don't need to either.
Several answers suggest an imperative approach which is considered an anti-pattern in BDD. Instead I strong suggest you follow the declarative approach with your Gherkin using natural or business language. If you are actually testing the login feature, I'd propose something like:
When an authorised user enters their credentials
or role based
When an Administrator is authorised
If login is actually a prerequisite for the feature under test then something such as:
Given an authorised user
or
Given an authorised Administrator
These can be backed up with a Credentials Manager.
... = ExpectedData.credentialsFor("#authorised");
The tag should represent the characteristics, not the identity of the expected data, to be retrieved from a test data db or csv containing something like:
#admin, administrator, password
#authorised, user, password
#unauthorised, user, wrong
The same approach should be used for all test data entry, such as:
Given a Cash Customer
Given a Credit Customer
Given a Customer with an overdue account
A strong benefit of this approach is the test suit can be readily reused on different environment by making the data/credential handler environment aware.
Please execute below step definitions and let us know if worked for you.
#When("^I enter the ([^\"]*) for the user$")
public void stepDefinition(String cred){
//code
}
#When("^I enter the correct ([^\"]*) for the user$")
public void otherStepDefinition(String cred){
//other code
}
Without Parameter
With Parameter
Two metacharacters (^, $) are called anchors, because they’re used to tie down each
end of the regular expression to the beginning and end of the string that they
match on.
Related
I would like to validate email address from user giving information to my chatbot.
Is there a simple way to deny unexpected symbols with regular expressions and CSML?
Here's my current code:
askEmail:
say "Thank you {{firstname}}"
say "What is your email address?"
hold
remember email = event
if (Find("#", in="email")) goto askCompany
else {
say "Please enter a real email address"
goto askEmail
}
I need to replace Find with a function using regexp and check all unexpected symbols.
There is a contains_regex string method in CSML that you can use to verify more complex rules than just "is there a # in this string?".
It's quite hard to cover all possible valid email addresses with a regex (see https://emailregex.com), but let's just agree for your purpose that emails are in the general form of "whatever#whatever.whatever" where "whatever" is any string that does not contain any line break.
This is obviously not a 100% foolproof regex as it is a bit naive, but validating emails is still a Hard Thing ®. Good enough is usually good enough.
Here goes:
askEmail:
say "Thank you {{firstname}}"
say "What is your email address?"
hold
remember email = event
if (email.contains_regex("^.+#.+\..+$")) goto askCompany
else {
say "Please enter a real email address"
goto askEmail
}
You can obviously tweak the regex to your liking!
emailPattern = /^([a-z\d]{1})([\w-\.!#$%&'*+\/=?\^`\{\|\}~"\(\),:;<>\[\\\]]){2,}([a-z\d]{1})#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-z\-0-9]+\.)+[a-z]{2,}))$/i;
console.log('Regex test is: ', emailPattern.test('test#test.test'));
emailPattern = /^([a-z\d]{1})([\w-\.!#$%&'*+\/=?\^`\{\|\}~"\(\),:;<>\[\\\]]){2,}([a-z\d]{1})#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-z\-0-9]+\.)+[a-z]{2,}))$/i;
Email Regular Expression Pattern
^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)* #[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$;
I have a registration test that creates one account but I want to add a loop to this so that if will run 5 times in a row entering different usernames and email address, I already have the usernames I want to use stored in a seperate python file. Any ideas on how to do this?
Welcome to SO. There are different approaches but below is the simple approach.
Store all the required details in the list and then iterate.
users = [['user1','pass1'],['user2','pass2'],['user3','pass3'],['user5','pass5'],['user5','pass5']]
for user in users:
# get user name and use in registration
userName = user[0]
# get password and use in registration
passWord = user[1]
print (userName + ":" + passWord)
Completely new to regex only read a few guides my problem is as follows. A 3rd party solution is being connected to our Adfs 2016 enviroment. We have run into a problem as the solution cannot handle long usernames and the Upn and email of our users are in the format of users initials 3 or 4 letters.department#ourcompany.com, so Dave Dibley Jr would be ddj.department#ourcompany.com
what i would like to do is use Regex to Cut everything after the initals from the claim any suggestions how to do this ?
You can use RegEx for string manipulation in the Claims Rules Language. Fx:
c:[type == “http://contoso.com/role”]
=> issue (Type = “http://contoso.com/role”, Value = RegExReplace(c.Value, “(?i)director”, “Manager“);
Pass through any role claims. If any of the claims contain the word “Director”, RegExReplace() will change it to “Manager”. For example, “Director of Finance” would pass through as “Manager of Finance”.
See https://social.technet.microsoft.com/wiki/contents/articles/16161.ad-fs-2-0-using-regex-in-the-claims-rule-language.aspx for more information.
My goal is to use Robot to take a list of login credentials and iterate through the list, logging into the page and essentially proving those users can see the page.
From what I've been finding, I need to use a Template, but I haven't found it very clear how do implement one when you have all the values you want to use in the same robot file.
I've been using https://github.com/robotframework/QuickStartGuide/blob/master/QuickStart.rst and http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#data-driven-style
Based on this example they have:
Templated test case
[Template] Example keyword
first argument second argument
They don't explicitly show an example of where the data is set up to run the test.
Here's what I have so far:
*** Settings ***
Documentation Test Access Levels of the new Page
Library Selenium2Library
Test Template Security Login Test
*** Test Cases ***
All Users Login Test
Security Login Test Login Test
User1 Pass1
User2 Pass2
User3 Pass3
*** Keywords ***
Enter User Name
input text working_username_field need_to_put_username_here
Enter Password
input text working_password_field need_corresponding_password_here
Click Login
click element working_login_button
Enter Store Number
input text working_store_field working_store_number
Click Search
click element working_search_button
Login Test
open browser working_url Chrome
enter user name
enter password
click login
enter store number
click search
go to working_sub_url
What I don't know is how I then put those parameters into my Keywords so it will go through each on.
I know I could use a file for this, but that seems slightly more complicated, so I want to figure this way out first.
Thanks for any help you can offer!
When you use a suite-level template, each testcase is typically a single row. The first column is the test case name, and additional columns are arguments to the template keyword.
For example:
*** Settings ***
Test Template Security Login Test
*** Test Cases ***
# test case name # username # password
Normal user joe.user#example.com test123
Admin user sally.admin#example.com abc123
Banned user boris.badguy#example.com knockknock
*** Keywords ***
Security Login Test
[Arguments] ${username} ${password}
Enter username ${username}
Enter Password ${password}
The rest of your code here...
Enter username
[Arguments] ${username}
log entering username '${username}
Enter password
[Arguments] ${password}
log entering password '${password}'
The rest of your code here...
log another keyword
i am new on python and just started learning, i want to create a simple script to run a program by authenticating user, valid or not...
main problem, i am facing is that i have a file "users" in which i mentioned all valid users,
so i need a program which searches the input given by user in "users" file, if found then continue otherwise "authentication failed"
what i tried is ...
fp = open("users", "r")
for line in fp.readlines():
if "michel" in line : # user michel is available in users file
print "true"
else :
print "false"
it works, prints 'true' because michel is in file.. but in case of when user enters "mic" .. also prints true ...... so what will be the solution...
For starters, it is probably best for security purposes to use os.getlogin() to determine the user's login name rather than prompting the user to type their username. This will at least guarantee that the user logged in via some authentication mechanism to get onto the system, meaning that they have a known & consistent username.
So if you wanted to turn this into a function you could write:
def is_valid_user(username):
fp = open("users", "r")
for line in fp.readlines():
if username in line:
fp.close()
return True
fp.close()
return False
You could then call the function using:
import os
is_valid = is_valid_user(os.getlogin())
if is_valid:
print("valid user")
else:
print("invalid user")
Some suggestions for added security now and in the future:
Modify your "users" file to contain names surrounded by delimiters such as ":jonesj:" rather than "jonesj" and search for ":" + username + ":" in line which will avoid false positives in situations where a user "jones" is currently logged in and a username "jonesj" is in your "users" file but "jones" is not, and you incorrectly identify "jones" as being an authorized user (since "jones" is a subset of the string "jonesj").
Make sure the permissions on your "users" file is set to read-only so that users can't go add their username to the file to grant permissions to themselves.
Sometime in the future you may want to consider using LDAP or Kerberos server or some other more formal authentication mechanism rather than a "users" file. There are good python client libraries for quite a number of authentication backend servers.
You can use re to make sure the whole line is a match:
import re
fp = open("users", "r")
for line in fp.readlines():
if re.match('^michel$', line, re.I):
print "true"
else :
print "false"