Bypass login between each scenario? - selenium

I am using rspec/capybara here.
I'd like to be able to log into the system only once, then run a bunch of scenarios. Should a scenario fail, it can effectively move onto the next one.
The problem is that once a scenario fails, a new browser session is started and I am asked to log in again. Is there a way around this?
How is this type of testing handled? Many systems require a user to log in first prior to exercising all its functions/features.

So many ways to achieve this but I myself prefer a new instance per spec at least if not context or sometimes even it. I like atomic self contained tests.
Anyway, if you decide want to do this, then you could;
Reuse a cookie session between tests but still open a new browser. Obviously this depends upon the system under test
Create a global Before all which only creates a browser and sign in if you are not already signed in.
Create a global After all which navigates to a known state (eg. Home page) but doesn't log out.
There are many approaches which could work

Related

How to determine if an automated functional test was successful

Goal:
Determine if a functional test was successful.
Scenario:
We have a functional requirement: "A user should be able to signup with username and password. The username has to be a valid email-adress. The password has to be at least 8 characters long".
We have a method "SignupResult UserManager.Signup(string username, string password)".
We want a happy-test with valid intputs, and a sad-test with invalid inputs.
Sub-Systems of the UserManager (e.g. Database) can be either mocked or real systems.
Question:
What would be the best way to determine if the user was successfully signed up. I can imagine the following options:
If any of the sub-system was mocked, one could check if a specific function like "DB.SaveUser(...)" was called. This would destroy the idea of a functional test being a blackbox test and requires that the test-writer has knowledge of the implementation.
If we use real sub-systems, one could for example check if the row in the DB exists. That would be not adequate like the attempt above.
One could use another function like "UserManager.CheckUser(...)" to check if the user was created. This would introduce another method that is tested, also there may be operations that would have no "test-counterpart", or one would have to implement them, just for testing - that seems not ideal.
We could check the result "SignupResult" and/or check for exceptions thrown. This would require defining the interface of the method. This also would require all methods to return a sensible value - I guess this will be a good approach anyway.
To me the last methods seems to be the way to go. Am I correct? Are there other approaches? How would we check side-effects like "an email was sent to the new user" ?
You may want to acquaint yourself with the concept of the Test Pyramid.
There's no single correct way to design and implement automated tests - only trade-offs.
If you absolutely must avoid any sort of knowledge of implementation details, there's really only way to go about it: test the actual system.
The problem with that is that automated tests tend to leave behind a trail of persistent state changes. For example, I once did something like what you're asking about and wrote a series of automated tests that used the actual system (a REST API) to sign up new users.
The operations people soon asked me to turn that system off, even though it only generated a small fraction of actual users.
You might think that the next-best thing would be a full systems test against some staging or test environment. Yes, but then you have to take it on faith that this environment sufficiently mirrors the actual production environment. How can you know that? By knowing something about implementation details. I don't see how you can avoid that.
If you accept that it's okay to know a little about implementation details, then it quickly becomes a question of how much knowledge is acceptable.
The experience behind the test pyramid is that unit tests are much easier to write and maintain than integration tests, which are again easier to write and maintain than systems tests.
I usually find that the sweet spot for these kinds of tests are self-hosted state-based tests where only the actual system dependencies such as databases or email servers are replaced with Fakes (not Mocks).
Perhaps it is the requirement that needs further refinement.
For instance, what precisely would your user do to verify if she has signed up correctly? How would she know? I imagine she'd look at the response from the system: "account successfully created". Then she'd only know that the system posts a message in response to that valid creation attempt.
Testing for the posted message is actionable, just having a created account is not. This is acceptable as a more specific test, at a lower test level.
So think about why exactly users should register? Just to see response? How about the requirement:
When a user signs up with a valid username and a valid password, then she should be able to successfully log into the system using the combination of that username and password.
Then one can add a definition of a successful login, just like the definitions of validity of the username and password.
This is actionable, without knowing specifics about internals. It should be acceptable as far as system integration tests go.

How to not continually repeat a background scenario for Cucumber features that depend on that background scenario

I'm writing some end-to-end tests for my application using Cucumber and Selenium. I'm keeping every scenario totally independent of one another, as advised on the Cucumber website. However, my application has session based authentication, so every time a new scenario is run, it will required a login process in order to first access the site. Right now my approach is to put the login scenario as a background scenario for all other scenarios, like so:
Background: User is Logged In
Given I am on the login screen
When I enter my login details
And I click submit
Then I should be logged in
However, this feels like a lot of duplicated 'code'. Moreover, having each scenario run independently requires a new WebDriver instance being created and a browser being run for each scenario, which feels a bit inefficient?
Can anyone advise firstly on how I can avoid duplicating the background scenario in every other scenario (if possible) and secondly if having a separate WebDriver instance for each scenario is the correct approach?
First of all each of your scenarios is going to have to login and create a new session. Thats the price you pay to do end to end testing. The cost of this in runtime should be relatively small with a standard login process as most login screens are simple, and have short rendering times and very little db access. It really is a very bad idea to tray and save runtime here by trying to share sessions between scenarios.
To start tidying your cukes you could follow Daniel's answer, but instead of nesting the steps I would recommend extracting the code to a helper method and calling that instead.
To do this elegantly with power, i.e. deal with different users with roles and extra attributes you need to do a bit more. You can see a detailed example of this here (https://github.com/diabolo/cuke_up).
To use this effectively follow the commit history and focus mostly on the features folder.
This has some framework code that allows you to register/create users and then use them in lots of different configurations. There is some underlying code that is a little complex, which gives you the power to create users who know their own passwords, as well as add other attributes like roles.
The end result is that you can write a step definitions like
Given I am registered
Given I am an admin
Given I am logged in
Given I am logged in as an admin
which are implemented as
Given 'I am registered' do
#i = create_user
end
Given 'I am an admin' do
#i = create_user role: 'admin'
end
Given 'I am logged in' do
#i = create_user
login as: #i
end
Given 'I am logged in as an admin' do
#i = create_user role: 'admin'
login as: #i
end
note: the variable #i is used to pass the user from one step to the next
You don't have to worry about repetition here as all the steps make calls to the same helper methods. You can use the patterns shown here in a much wider context to simplify your features/
This example is in Ruby. You can group up the steps used for Login in login_steps.rb file.
In the .feature file you'll need to write a step like "Given the user is logged in". You can pass in login data in this step as well, if you want. Then in the login_steps.rb file, you create:
Given(/^the user is logged in$/) do
step('I am on the login screen')
step('I enter my login details')
step('I click submit')
step('I should be logged in')
end
I'm sure you can find the equivalent in any other language. Now you can write a the background like:
Background: Given the user is logged in
and it will be used before each scenario of that specific .feature file
As for the Webdriver, as far as I'm aware, you create a session when the test starts and you quit when it ends.
Hope it helps!

Is it possible to add an "Else" after "Given, When, Then"?

I'm new to Gherking and trying to write my first scenarios as best as I can, but I regularly find myself in situations where I'm really tempted to add an "Else" to my scenario. "Given, When, Then" becomes "Given, When, Then, Else". I know that the "Else" keyword is not defined and so not implemented in Gherkin tools but it doesn't care to me because I don't use these tools.
Do you think it is correct to write this :
Example :
Scenario : Application starts
Given I start the application
When I already have an open session
Then I see the home screen
Else I see the login screen
Or is it better to write two different scenarios :
Scenario : Application started by authenticated user
Given I have an open session
When I start the application
Then I see the home screen
Scenario : Application started by unauthenticated user
Given I don't have an open session
When I start the application
Then I see the login screen
In short no, but here are options to handle multiple variants of a scenario:
If it was only tailing elements of the scenario steps that differed you could of moved early steps in to a common 'Background' section, making repeated differing scenarios shorter and clearer.
But from your example it is all steps differing slightly so you can:-
accept the repitition of multiple scenarios
Or
parametise the differences and use data tables in the 'given' and 'then' sections to give before and after values.
Or (my prefernece)
Use the 'scenario outline' syntax that uses an examples table to provide sets of data fixtures with their expected results. These replace in the scenario steps as runtime. The scenario is then 'played out' once for each row in the examples table.
So:
Scenario : Application started by authenticated user
Given I have an open session
When I start the application
Then I see the home screen
Scenario : Application started by unauthenticated user
Given I don't have an open session
When I start the application
Then I see the login screen
Becomes:
Scenario Outline: Application Start and login
Given Application started by <AuthenticationStatus> user
And I have <SessionState> session
When I start the application
Then I see the <FirstScreen> screen
Examples:
|AuthenticationStatus |SessionState |FirstScreen|
|Authenticated |open |home |
|Un-Authenticated |not open |login |
IMHO for 2 scenarios it might not be worth the loss of readabiltiy but for more than that I think it's definitely worth it.

How do I make my selenium tests detectable by the server?

I'm currently working on making a few improvements to our selenium based UI tests. One feature I'm looking for is a reliable way for our website to detect what traffic is coming from our tests, so I can filter this traffic out of our browser usage metrics and logging.
One thought I had is to set a tracking cookie with selenium that I could read server side to append to my logs/metrics making it easier to filter it out. The challenge here is cookies are domain specific, and as far as I know wouldn't be readable from other sites. Cookies are also a finite resource, and given the size/distributed nature of our website it's quite possible to run into a situation where this could blow the size limit on cookies/headers and cause issues in the page.
Is this my best option, or is there another reliable way to detect from my webserver if my page is being automated with selenium. (I'm not trying to combat bots, we have other systems in place to guard against DoS/DDoS attacks.
When using Chrome, the Selenium driver injects a webdriver property into the browser’s navigator object. This means that for me, adding the following js to my page redirected it to StackOverflow:
if (navigator.webdriver == true) {
window.location = "https://stackoverflow.com";
}
So I guess just replace window.location = "https://stackoverflow.com"; with whatever you want, I'm guessing logging the requests somewhere or somehow excluding them from whatever tool you use to measure traffic.
So, the server obviously needs some token that tells it that a session is selenium based. Given that, here is what I would do.
Create a super simple API on your server. Have that API take the session token of the logged in used and pass that in the API (almost always automatic). When the API receives that session token, mark something in the database (new table or same table that stores session ID's if any).
Have the API flag the session as a test session, and thus not valid for metrics.
This is not a statistically significant impact on any server, so there is no worry about resources or impact.
Should take a very simple code-behind API, a very lightweight table that could simply have a single column with a foreign key to the session id involved. All inserted session IDs in this table, by virtue of existing here, are test sessions.
And then, your metrics recording will need to add a single clause to a query that has effectively "WHERE (SELECT COUNT(sessionId) FROM TestSessionsTable WHERE sessionId = currentIdChecked) = 0"
And that would give you what you need. I am happy to be told of a better solution, but this strikes me as the simplest effort, with the least impact on resources.
As for detecting Webdriver sessions on the client side, you can either use C. Peck's suggestion, or directly call the API from your automation run using the WebDriver's Javascript Executor logic.

What is preventing people from using someone else's CAPTCHA as their own?

Why (other than moral reasons) don't more people use the CAPTCHAs of other sites as their own while selling the solving of said CAPTCHAs?
To me, such a system seems like it would be simple to implement:
set up a script that does something on another website that requires a CAPTCHA to be completed through the use of a proxy service
when a user on your site performs a task that requires the completion of a CAPTCHA, simply serve them the CAPTCHA that the other
site asks you to solve
when the user solves the CAPTCHA, your script can perform the desired action on the other site that is the source of the CAPTCHA,
and the user on your site is also verified through this process
Is this commonplace? If not, why not? What, if anything, could be done to prevent this?
Fetching the captcha. Assuming one could easily fetch the exact visual of the captcha from the foreign host. To do this, you have to pass the referral check (most browsers (navigated by humans) allow to send the http_referer). You also would have to save the session_id and the secret from the hidden input.
Checking the result. The foreign host must link the saved variables with the ones associated with the session of your first request, which requires you to implement tricky cURL methods. You would have to handle multiple parallel requests, all from your single ip.
Your server will probably use more resources when hacking a captcha on a foreign host than if it generates a captcha on its own.
Prevents
http_referer check
limit requests for single IP to e.g. 5 / minute
good session handling and tricky cookies
it's not impossible to reverse engineer javascript, but the more complicated your javascript is, ...
you have to find a pattern that recognizes the result on the foreign host. the easiest signature may be the Location header field, leading either to /path/success.html or /path/tryagain.php
Challenge:
I took a moment to prepare an example: http://woisteinebank.de/test/
In this example, I attach keys to the session_id(); and save it in the database.
Through session_regenerate_id(); I have a fresh session on every request.
In check.php, I compare the database values to the $_GET values.
Try to find a way to get leech this captcha, I'll try to defend. Everytime you sucessfully use my captcha on your site, I try to defend it.