Capybara Selenium reuse existing browser session, instead of opening new windows? - selenium-webdriver

In Capybara, How can I reuse existing browser to continue run step next. Instead of star a new session and open a new windown and next run a ton of step before.
For example :
First:
session = Capybara::Session.new(:headless_chrome, Capybara.app)
session.open(url)
session.click(...)
sesion.quit()
Second Time:
session = ...#retry the first session state
sesion.do_something()

Capybara is designed as a testing tool, where you want every test to be completely independent of other tests. Because of that it has no support for storing/reloading a session, and uses a fresh browser instance (data-dir, etc) for each session. To prevent creation of a completely new browser setup every time you create a new session you could pass your own --user-data-dir=<some_directory> option when registering your Capybara driver, but it's not Capybara supported usage (and would really not be a good idea if you're actually doing testing rather than web scraping). Another option if all you really want is the cookies retained would be something like https://github.com/kyamaguchi/capybara-sessionkeeper (again bad idea if you're testing since it couples tests to each other).

Related

Calling authentification feature from another feature

I'm starting learning automation test using selenuim webdriver & cucumber, I have tow features:
Authentification.feature
Feature: Authetification
#Test1
Scenario: Authetification (credential)
Given Open the Url
When Enter the Username and Password
Then Click connect_btn
CreateUser.feature
Feature: Create User
#Test2
Scenario: Create User
Given Open users list
When Fill the form
Then Click save_btn
How to call the authentification into CreateUser.feature ?
Thanks & Regards,Patricia
Cucumber does not support calling one feature from another feature (or one step from another step).
From the Cucumber docs - FAQ:
"How do I call other steps or scenarios?
Each scenario should be independent; you should be able to run them in any order or in parallel without one scenario interfering with another.
Each scenario should test exactly one thing so that when it fails, it fails for a clear reason. This means you wouldn’t reuse one scenario inside another scenario.
If your scenarios use the same or similar steps, or perform similar actions on your system, you can extract helper methods to do those things."
In your case, I'd recommend thinking about how to get your system to a state where a user is logged in at the start of any test where that is a precondition, without actually testing the login feature each time. That way if the login functionality breaks for any reason, you can still test other functionality of your application.

Restarting browser after every feature file cucumberjs

Currently we have an automation framework built using cucumberjs/protractor. As is now, all of our tests run in one browser instance.. this causes issues with our mocking system as it causes instabilities as more and more tests run. What is the easiest solution to make cucumberjs tests kick off a fresh browser instance at every new feature file? Would it include configuring the hooks.js?
Create a before hook in your hooks.js:
this.Before(()=> {
this.browser.restart();
})
http://www.protractortest.org/#/api?view=ProtractorBrowser.prototype.restart

How to performance test an AngularJS Web Application?

I used to do performance testing on websites mostly with JMeter scripts.
However, more and more projects are build with frontend MVC's, such as AngularJS and a current project is loading all of it's content via angular view files, REST calls etc.
Unfortunately, JMeter doesn't execute any javascript thus my load test return me the homepage in just (400ms).
In real, it actually takes several seconds to load in a browser. When I check the response data, it does not contain any data yet due to Angular.
Instead of investigating the network traffic and individually loading each component (e.g. profile.html, notification.html, REST calls etc. ). Is there a product on the market or some best case I could follow that is similar to executing JMeter scripts, but considering javascript execution and loading of external resources due to javascript?
(I am not planning to profile javascript execution times. This is still to test if the infrastructure behind is capable serving xyz simultaneous users)
Although JMeter isn't capable of executing client-side JavaScript it can record relevant requests via HTTP(S) Test Script Recorder. Once recorded you should be able to combine all the standalone requests into one "aggregate" using JMeter's Transaction Controller
If this easy approach for some reasons doesn't play for you check out How to Load Test AJAX/XHR Enabled Sites With JMeter for more options and clues.
I use Chrome dev tools to do this kind of performance tests in web apps.
I suggest you to read the Chrome Profiling docs (https://developer.chrome.com/devtools/docs/javascript-memory-profiling). All the section of Performance and Profiling in goolge documentation is really good!
You can try to use the option 'Use as Monitor' for the requests you fire up from your test.
http://jmeter.apache.org/usermanual/build-monitor-test-plan.html
They are performance killers, though. Another option is to use the listener 'Save Responses to a File' to see if the end HTML is delivered. It should not give you the ideal result but it might help.
If you want to track down performance of XHRs for a single user, you can try to play with Selenium and BrowserMob Proxy, but it is not under the stress testing, but functional testing.
You can try https://github.com/kidk/felt it is build for this specific purpose.
It uses PhantomJS/SlimerJS to generate load to a website, so you get all the API/JS/CSS and image calls you would get like in a normal browser. It is still a young project, but it might be the solution you are looking for.
(This is my personal project)

Is there any way to trigger my javascript modules to check whether they are working properly during load tests

Is there any way to trigger my javascript modules in jmeter to check whether they are working properly during load/performance tests
JMeter is not a browser so it isn't able to execute client-side JavaScript. All that JMeter is able to do in this regards is:
Download scripts along with other embedded resources like images and styles (but do it only once per virtual user) to simulate real browsers behavior more or less closely.
Simulate JavaScript-driven calls like AJAX/XHR via separate HTTP Requests
The most common practice of web application monitoring during performance session is manually accessing the application under test and assessing it's responsiveness and behavior.
This process can also be automated using JMeter's WebDriver Sampler Plugin which allows to invoke arbitrary Selenium code to orchestrate one or several real browsers to check i.e. actual page load speed during performance test session.

How to handle expired files without refreshing the browser when using Single Page Application (SPA)?

I have done a full Single Page Application (SPA) application using Angularjs.
So far so good.
As anyone knows, all javascript files are loaded in the first time access. Or, some file are loaded in lazy mode style when needed.
So far so good...
The situation is: the server updates all files (html partials, javascripts, css's) and the client remain with a lot of files out-dated.
This would be simply solved refreshing the browser, hit F5 key, control+f5, or refresh button in the browser. But this concept does not exists when working with SPA.
I'm not sure how to solve this problem.
I could detect somehow (doing a ping maybe) and just to re-load that specific file. With document.write strategy. But now rises another problem, I have a single javascript file with all javascript minified.
I could try to force a full reload in the browser or force to re-login (and reload because login are SPA part).
But reloading is an ugly solution, imagine the client lose all data in the form because he was unlucky the server have just updated. And worse, I must now create some "auto-save" feature just because of this.
I'm not sure how to handle this, if possible, doing in "angular way".
I wonder how google gmail handles this because I stay logged for many many hours without logging of.
As others have already suggested, keep the logged user on the old version of your webapp.
Not only what you ask is difficult to do in Angular, but it can also lead to a bad user experience and surprising behaviour, since there may not be a mapping between what the user is doing with the old version and what the new version provides. Views may be removed, renamed, split or merged. The behaviour of the same view may have changed, and doing so without notice for the user may cause mistakes.
You made an example with Gmail, but may have noticed that changes to the UI always happen after you logout, never while you're using it.
First of all, if your app is an intranet website used during office time, just update it while nobody is using it. This is a much simpler solution.
Otherwise, if you need to provide 24/24 availability, my suggestion is:
When you deploy the new version of your SPA, keep the old version in parallel with the new version, keep the current users on the old version, and log new users to the new version. This can be made in a number of ways depending on your setup, but it's not difficult to do.
Keep the old version around until you're confident that nobody is still using it or you're pretty sure that the new version is ok and you don't need to rollback to the old version.
The backend services should be backward-compatible with the old version of the frontend. If that's not possible you should keep multiple version of the backend services too.
As the rest of the guys said a solution can be to versioning your files. So every time that your browser check those files out the browser notice that the files are different to the ones that are in the server so the browser cache the new files.
I suggest to use some build tool like gulp, grunt or webpack, the last one is becoming more popular.
By the moment I use gulp for my projects. I´m moving to webpack though.
if you are interested in gulp you can have a look to gulp-rev and gulp-rev-replace plugins.
What do they do?
let´s say that we have the next file in your project app.js what you get after apply gulp-rev to your project is something like app-4j8888dp.js then your html file where the app.js is injected is still pointing to app.js so you need to replace it. To do that you can use gulp-rev-replace plugin.
eg. gulp task where
var gulp = require('gulp');
var rev = require('gulp-rev');
var revReplace = require('gulp-rev-replace');
var useref = require('gulp-useref');
var filter = require('gulp-filter');
var uglify = require('gulp-uglify');
var csso = require('gulp-csso');
gulp.task("index", function() {
var jsFilter = filter("**/*.js", { restore: true });
var cssFilter = filter("**/*.css", { restore: true });
var indexHtmlFilter = filter(['**/*', '!**/index.html'], { restore: true });
return gulp.src("src/index.html")
.pipe(useref()) // Concatenate with gulp-useref
.pipe(jsFilter)
.pipe(uglify()) // Minify any javascript sources
.pipe(jsFilter.restore)
.pipe(cssFilter)
.pipe(csso()) // Minify any CSS sources
.pipe(cssFilter.restore)
.pipe(indexHtmlFilter)
.pipe(rev()) // Rename the concatenated files (but not index.html)
.pipe(indexHtmlFilter.restore)
.pipe(revReplace()) // Substitute in new filenames
.pipe(gulp.dest('public'));
});
if you want to know further details see the links bellow.
https://github.com/sindresorhus/gulp-rev
https://github.com/jamesknelson/gulp-rev-replace
A single page application is that, a single stack that controls the client logic of your application. Thus, any navigation done through the application should be handled by your client, and not by the server. The goal is to have a one single "fat" HTTP request that loads everything you need, and then perform small HTTP requests.
That's why you can only have one ng-app in your apps. You are not suppose to have multiple and just load the modules you need (although the AngularJS team wants to move that way). In all cases, you should serve the same minified file and handle everything from your application.
It seems to me that you are more worried about the state of your application. As Tom Dale (EmberJS) described in the last Cage Match, we should aim to have applications that can reflect the same data between server and client at any point of time. You have many ways to do so, either by cookies, sessions or local storage.
Usually a SPA communicates with a REST based server, and hence perform idempotent operations to your data.
tl;dr You are not supposed to refresh anything from the server (styles or scripts, for instance), just the data that your application is handling. An initial single load is what SPA is all about.
separate your data and logic and reload the data using ajax whenever you want, for that i will suggest you use REST API to get the data from server.
SPA helps you to reduce the HTTP request again and again but its also require some http request to update a new data to view.
Well, you would have to unload the old existing code (i.e. the old AngularJS app, modules, controllers, services and so on). Theoretically, you could create a custom (randomized) app name (with all modules have this prefix for each unique build!) and then rebuild your app in the browser. But seriously.. that's a) very complex and b) will probably fail due memory leaks.
So, my answer is: Don't.
Caching issues
I would personally recommend to name/prefix all resources depended by a build with a unique id; either the build id, a scm hash, the timestamp or whatever like that. So, the url to the javascript is not domain.tld/resources/scripts.js but domain.tld/resources-1234567890/scripts.js which ensures that this path's content will never conflict with a (newer) version. You can choose your path/url like you want (depending on the underlaying structure: it is all virtually, can you remap urls, etcpp). It would be even not required that each version will exist forever (i.e. map all resources-(\d+)/ to resources/; however, this would be not nice for the concept of URLs.
Application state
Well, the question is how often will the application change that it would be important that such reloads are required. How long is the SPA open in a browser? Is it really impossible to support two versions at the same time? The client (the app in the browser) could even send its own version within the HTTP requests.
In the beginning of a new application, there are a lot of changes that would require a reload. But soon after your application has a solid state, the changes will be smaller and would not require a reload. The user itself will make more refreshs.. more than we ever expected :/
As with what everyone else is saying...
Don't, and while socket.io could work it's asking for trouble if you are VERY careful.
You have two options, upon server update invalidate any previous session (I would also give users a half hours notice or 5 minutes depending on application before maintenance would be done.
The second option is versioning. If they are on version 10, then they communicate with backend 10. If you release version 11 and they are still on 10 then they can still communicate with backend 10.
Remember Google wave? It failed for a reason. Too many people writing one source as the same time causes more problems then it solves.
use $state service. create state during loading page using ctor. after specified time re create state and load page.
function(state) {
state.stateCtor(action);
$state.transitionTo(action + '.detail', {}, {
notify: true
});
}
Versioning your files, so on every update increment version number and the browser will update it automaticallly.
My solution consists of several points.
While this is not important, but I send one JavaScript file to the client side, I use grunt to prepare my release. The same grunt file adds to the JavaScript tag a query with version number. Regardless of whether you have one file or lots of files, you need to add a version number to them. You may need to do this for resources as well. (check at the end for an example)
I send back in all my responses from the server (I use node) the version number of the app.
In Angular, when I receive any response, I check the version number against the version number loaded, if it has changed (this means the server code has been updated) then I alert the user that the app is going to reload. I use location.reload(true);
Once reloaded the browser will fetch all new files again because the version number in the script tag is different now, and so it will not get it from cache.
Hope this helps.
<script src="/scripts/spa.min.js?v=0.1.1-1011"></script>

Resources