nightwatchjs, run same test on multiple pages - nightwatch.js

I have written some tests for my homepage but the tests are very generic, like footer, header checking.
My test structure is like:
const footerCheck = function(browser){
browser.url("example.com");
browser.verify.elementPresent(".footer-top", "Footer-top is present.")
browser.verify.elementPresent(".footer-middle", "Legal notice bar is present")
browser.verify.elementPresent(".footer-bottom", "Copyright bar is present")
}
export.module = {
"Footer Check" : footerCheck
}
Lets say I have 100 pages. I would like to run footerCheck function run on all hundred pages.
URLs like example.com/page1 , example.com/page2 , example.com/page3...
Since all the tests are valid for other pages I would like to loop all pages for the same test cases. Somehow could not get my head around it.
How is that possible, any help would be appreciated.
Thanks

In my personal experience, the best way to do BDD is adding cucumber that uses gherkin syntax. It is clearer and helps a lot to reduce redundant code if you know to use it well. There is a Nightwatch npm plugin to add cucumber, once you have added it you have to create your .feature file like the following
Feature: Check elements are present
Scenario Outline:
Given the user enters on a <page>
Then .footer-top, .footer-middle and .footer-bottom class should be enabled
Examples:
|page|
|page.com/page1|
|page.com/page2|
|page.com/page3|
And your step definitions (where you declare what will do each step) it automatically will run each step for each url provided in the examples (note the <page> flag that will be replaced on the example, first row is the name of the tag).
Take a look to the examples

Related

How can I gather all the tags for a Feature file?

I am trying to leverage the tag names that are associated with a feature file in my cucumber ruby Framework. Below is what I am currently doing to gather the tag names using a Before hook, but unfortunately more code other than just the tags are being collected.
Before do |scenario|
#feature_tags = scenario.feature.tags
end
Take for example this sample feature file snippet:
#regression #etc
Feature: File description for something
Background:
* etc etc etc
Scenario: Description for something
* etc etc etc
What is currently being captured with the above hook is:
[#<Cucumber::Core::Ast::Tag "#regression" (features/long/file/path.feature:1)>,
#<Cucumber::Core::Ast::Tag "#etc" (features/long/file/path.feature:1)>]
Is there any way that I can isolate simply the tag names ie: "#regression" ?
Try the below.
scenario.source_tag_names

NUnit- Custom Property Attribute display in Test Explorer window

I created custom property attribute to link every system test to its driving requirements which is similar to something described in the link below:
NUnit - Multiple properties of the same name? Linking to requirements
I used the code given in the above link
[Requirements(new string[] { "FR50082", "FR50084" })]
[Test]
public void TestSomething(string a, string b) { // blah, blah, blah
Assert.AreNotEqual(a, b); }
which gets displayed in Test explorer (filter by traits) as :-
Requirements[System.String[]] (1)
TestSomething.....
But this is not what I was expecting. I require every requirement to get displayed individually though they are associated to the same test case in test explorer window.
I want to get it displayed as (in test explorer):-
Requirements[FR50082] (1)
TestSomething.....
Requirements[FR50084] (1)
TestSomething.....
and so on....
So, if I am associating n number of Requirements to a test case, the test explorer should display the same test case n times under different requirements. Please let me know how could this be achieved ??
It sounds like you are heading down the BDD (Behavior Driven Design) route. SpecFlow is a good choice in .Net if you don't mind a VS extension.
The big win for you I think would be that you can reuse step definitions, what you're calling TestSomething. You can set up different contexts, your Requirements, as I'm reading them, and in the Then step call your TestSomething to verify all is well.

Automatic Step Generation in cucumber javascript using javascript

I am using javascript for cucumber javascript for automation.My concern is can i generate .js file for step definitions automatically? as of now am copy pasting them(steps) from command line window so can I skip it and directly generate the step file?
Two Suggestions:
1.
You can create a new gherkin file, and run it with cucumber.js, it will generate JavaScript stub automatically for you. For example:
"cucumber-js math.feature"
It will output something like:
1) Scenario: easy maths - math.feature:7
Step: Given a variable set to 1 - math.feature:8
Message:
Undefined. Implement with the following snippet:
this.Given(/^a variable set to (\d+)$/, function (arg1, callback) {
// Write code here that turns the phrase above into concrete actions
callback(null, 'pending');
});
It has the parameter automatically generated based on your tests. You can then copy the snippet into your code file.
2.
If you are using Windows 10, you can also try a BDD development tool CukeTest, and it provide some convenient features like code generation from step text, or navigate between code and steps etc.
You can use 'Live Template'/'Code snippets' in your IDE. It's the best way to improve performace.
https://www.jetbrains.com/help/idea/creating-code-constructs-by-live-templates.html
If you use VC Code then you can use extension Cucumber (Gherkin) Syntax and Snippets:
https://marketplace.visualstudio.com/items?itemName=stevejpurves.cucumber

Is it better idea to save elements in yml file?

I'm writing automated tests using Selenium WebDriver with Ruby. So, I'm thinking to keep elements in another file and actual code in another file. And for Ruby, I found yaml gem which allows to store data and access it. Hence I stored elements in lib.yml and test code in test.rb as following:
lib/lib.yml
homepage:
frame: 'mainPage'
email: 'loginPage-email'
password: 'loginPage-password'
login_button: 'btnLogin'
tests/test.rb
require 'selenium-webdriver'
require 'yaml'
driver = Selenium::WebDriver.for :firefox
driver.get 'http://www.abc.com'
config = YAML.load_file('./lib/lib.yml')
driver.switch_to.frame(config['homepage']['frame'])
email = driver.find_element(:id, config['homepage']['email'])
password = driver.find_element(:id, config['homepage']['password'])
email.clear
email.send_keys 'abc#gmail.com'
password.clear
password.send_keys 'password'
driver.find_element(:id, config['homepage']['login_button']).click
driver.quit
This way maintenance becomes easier. I just want to make sure if doing so is a good way or not. I'm asking because I'm trying this first time and don't know what difficulties I'll run into if I choose this for larger project.
I know, using Page object model, we can achieve same thing. But I don't know about Page object. So should I avoid using yml gem and directly go for page object gem?
Also, can someone explain how using yml will not be good idea(if it's not)?
Note:
In above code, config['homepage']['something'] is repetitive code. I'll write method to avoid repetition for that.
Yeah this definitely is useful... It keeps the changes to minimum when there is UI change in future.. You always have just one place to edit... Is there any data you have to pass to your code? How are storing the automation data passed to your test.. The only concern might be you might end up with too many yaml files which could be difficult to keep track...
In your specific case I don't see how this adds much value. Half of the settings (frame, login_button) won't change for your tests, so I suggest leaving them directly in the code where they are used. The html structure is not something that usually changes.
The other two values (email, password) seem like they might change when you want to try out different users (i.e. different cases). If you have one test with several example inputs then I suggest using a more readable solution as Cucumber.
(I'd suggest using capybara anyway for testing browser interaction, as it abstracts away many details of the underlying driver)
Apart from that, yaml is usually the ruby way for storing configuration.
I added one more step: Declared locator (id, name etc) in the yaml itself.
Ex:(yaml)
Declared env.rb which load the environment from yaml files
env.yml:
LOGIN:
UserName: {id: UserName}
Password: {id: Password}
RememberME: {id: RememberMe}
Submit: {xpath: "//input[#value='Log On']"}
Then added "pages\Login.rb"
#Loads all objects from yaml
def get_objects
username=#browser.find_element( $object_array['LOGIN']['UserName'])
password=#browser.find_element( $object_array['LOGIN']['Password'])
remember_me=#browser.find_element( $object_array['LOGIN']['RememberME'])
submit= #browser.find_element($object_array['LOGIN']['Submit'])
end
#Added methods in this class like
def loginas(uname,pass)
username.send_keys uname
password.send_keys pass
remember_me.click
submit.click
end #loginas_siteadmin
Created Tests file Login_tests.rb
lp=LoginPage::new(#browser)
lp.navigate
lp.loginas('SiteAdmin','password123')
This way your scripts and maintainable and most importantly you are free of any other external gem or dependency.

SoapUI XPath assertion with wildcards

Is there a way to use a wildcard inside an assertion in a XPath test with SoapUI?
I took a look at SoapUI's documentation and they say you can do something like this
<path1>
<path2>*</path2>
</path1>
I checked the 'Allow Wildcards' checkbox.
My question is : I want to assert my date starts with 2012-08-22 but i dont care about the minutes and seconds. I guess my the expression should be something like 2012-08-22* but it doesn't work.
What you are doing sounds like it should work. Here is a quick example i cooked up using a rest service from http://www.geonames.org/export/web-services.html#timezone. I'm using the demo they have supplied
http://api.geonames.org/timezone?lat=47.01&lng=10.2&username=demo
output is
<geonames>
<timezone tzversion="tzdata2012c">
<countryCode>AT</countryCode>
<countryName>Austria</countryName>
<lat>47.01</lat>
<lng>10.2</lng>
<timezoneId>Europe/Vienna</timezoneId>
<dstOffset>2.0</dstOffset>
<gmtOffset>1.0</gmtOffset>
<rawOffset>1.0</rawOffset>
<time>2012-07-25 04:39</time>
<sunrise>2012-07-25 05:50</sunrise>
<sunset>2012-07-25 21:00</sunset>
</timezone>
</geonames>
If you do an xpath match on the result and use the select from current button you get
//geonames/timezone/time
2012-07-25 04:39
If you update this to
//geonames/timezone/time
2012-07-25*
this will work fine and when updating the rest request with a new lat and lng the assertion will still pass since it is not checking the time. If this doesn't help, please supply your full assertion and maybe i could help more.
*note: for soap requests, make sure to declare the namespace and then use the proper format
//ns1:message
It will be sort of a pain, but here is what you can do:
1) Figure out an Xpath 'base' using the assertion tab (sounds like you are here already). I used this public site to test against: http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl
I used the CornerPoints method with 'hawaii' as the single param.
I created this 'base' xpath:
declare namespace ns1='http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl';
declare namespace SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/';
declare namespace SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/';
/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:CornerPointsResponse/listLatLonOut
(it will write the declare statements for you if you click declare)
(which you can test out in the assertions window)
2) Create a Properties step
3) Create a Property transfer step
4) Create a groovy script
5) add a property... i called mine misc
6) add a transfer step
* transfer from the CornerPoints - Request 1 --- Response
* paste the Xpath stuff in the box under the 'transfer from'
* Transfer to your property
(You can test with the little play button)
7) Add something like this to your groovy script:
def x = context.expand( '${Properties#misc}' )
def parts = x.tokenize(',')
for (def part in parts)
{
log.info(part)
if (part.startsWith("-153"))
log.info("good")
}
In the groovy step you can do anything you need to get at your (partial) data. The sample code I added gets lat/lons out of a long line wrapped in CDATA and then checks for just the starting part of some of the data.. just an example.
Remember that you can use groovy and java string methods:
http://groovy.codehaus.org/groovy-jdk/java/lang/String.html
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html
More groovy tips:
http://www.soapui.org/Scripting-Properties/tips-a-tricks.html

Resources