Browser Stack Local Testing Parellel Test - browserstack

I need to run my all test cases in parallel of 4 different browser.
On my chrome driver its work fine.
Problem arise when i try to run in parallel as local testing.
I get following error
com.browserstack.local.LocalException: *** Error: Either another browserstack local client is running on your machine or some server is listening on port 45691
I am using TestNG as my test runner.

It is too late but maybe it is good for other developers.
I do not know in which language you are programming but if you are using java and using the browserstack-local-java which has poor documentation :(
You need to add browserstack.localIdentifier = "specific id" to the capabilities when you create the WebDriver
At the same time when creating the com.browserstack.local.Local which calls ./BrowserStackLocal under the hood you need to specify an option called localIdentifier and it must have the same value as the browserstack.localIdentifier.
This is not documented but I tested it and it works and take a look on https://github.com/webdriverio/webdriverio/issues/2252

Code to start browserstack local before start of test.
I just use the current date-timestamp as my localIdentifier's value as it is unique every time i run it.
I have the following bit code in my configuration file
onPrepare: function (config, capabilities) {
console.log("Connecting local");
return new Promise(function (resolve, reject) {
exports.bs_local = new browserstack.Local();
exports.bs_local.start({ localIdentifier,'key': exports.config.key }, function (error) {
if (error) return reject(error);
console.log('Connected. Now testing...');
resolve();
});
});
},

I had hard time solving the issue[Error: Either another browserstack local client is running on your machine or some server is listening on port 45691] when running parallel tests.
So, I'm adding supporting details for those whore are using browserstack-local-java bindings.
Make sure you are using the correct key names in setting the local identifier for both Browserstack and Local connection.
String localIdentifier = "random string";
localConnectionOptions.put("localIdentifier", localIdentifier);
bsCapabilities.setCapability("browserstack.localIdentifier", localIdentifier);
For more details, refer to the Browserstack documentation.

Related

Workstation hosted vscode extension not processing message from remote hosted extension

QV https://github.com/microsoft/vscode-remote-release/issues/7736
I have two extensions. One of them is of uiKind workspace and may run locally or remotely depending on the workspace, and the other is of uiKind ui and always runs locally.
The ui extension is responsible for spawning a browser on the user's workstation to load a URI provided by the argument of a command print.launchBrowser that it registers using vscode.commands.registerCommand
The workspace extension uses vscode.commands.executeCommand to invoke print.launchBrowser.
The point of this arrangement is to allow the browser to be launched on the workstation irrespective of whether the extension host is local or remote.
This should work. The following documentation explicitly says it works: https://code.visualstudio.com/api/advanced-topics/remote-extensions#communicating-between-extensions-using-commands
However, when I test it works only when both extensions run on the workstation.
Before anyone tells me to use vscode.env.openExternal(Uri) I am aware of this and am using it to launch the default browser, but this is no use for launching a non-default browser. Many of my users exploit the support for an alternate browser to use Chrome for printing while using a less invasive alternative as their daily drive.
What could cause this to fail? Here's the abovementioned documentation:
Some extensions return APIs as a part of their activation that are intended for use by other extensions (via vscode.extension.getExtension(extensionName).exports). While these will work if all extensions involved are on the same side (either all UI Extensions or all Workspace Extensions), these will not work between UI and Workspace Extensions.
Fortunately, VS Code automatically routes any executed commands to the correct extension regardless of its location. You can freely invoke any command (including those provided by other extensions) without worrying about impacts.
That's not ambiguous.
Since the code for the browser agent is very short I present it in its entirety.
import * as vscode from 'vscode';
import * as child_process from "child_process";
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand("print.launchBrowser", url => {
const browserPath = vscode.workspace.getConfiguration("print").browserPath;
child_process.exec(`${escapePath(browserPath)} ${url}`, (error: child_process.ExecException | null, stdout: string, stderr: string) => {
if (error || stderr) {
const err = error ? error.message : stderr;
if (!err.startsWith("[")) {
vscode.window.showErrorMessage(err);
}
}
});
}));
}
function escapePath(path: string) {
switch (process.platform) {
case "win32":
return path.includes('"') || !path.includes(" ") ? path : `"${path}"`;
default:
return path.replace(/ /g, "\\ ");
}
}
Code to call it is straightforward. Any extension containing the following should open a browser window and load the bing.com default page, although if you want to use the agent above you'll need to either supply the print.browserPath setting with a value containing the workstation path to a browser or put in such a path as a literal for testing purposes.
There aren't any tests for things like whether browserPath has a value that resolves to a file. That's all in the calling extension, which is designed to use the agent only when it runs in a remote workspace. The agent is essentially nothing but a platform independent remote procedure call.
vscode.commands.executeCommand("print.launchBrowser", "https://bing.com");
All this has been tested and failed on two separate computers and also with VS Code Insiders 1.75.0, which also resolves the question of whether I have a borked VS Code installation.

Simulating intermittent network failures with Selenium

Running a test that has a long running (non-request/response action) along with polling to check the status. While this polling is going on, I'd like to make a few packets disappear. I keep seeing things that look like this might work with WebDriver only to come up short. Is there anyway to do this completely inside of selenium or do I have to go to a completely external proxy?
My thoughts were to act like an ad blocker in that I could watch what was being requested and refuse certain connections and return things like 502s or return nothing at all. But I'd like it to be under the control of the test, not an external setup.
You can manipulate requests by using a proxy. It's simplest to block requests. Depending on how your webapp is performing this might be a way to do it.
Check out Browsermob proxy usage:
Look here to get started: URL blacklisting with BrowserMobProxy in Robot Framework/Selenium?
// Start the server and get the selenium proxy object
ProxyServer server = new ProxyServer(proxy_port); // package net.lightbody.bmp.proxy
server.start();
server.setCaptureHeaders(true);
// Blacklist google analytics
server.blacklistRequests("https?://.*\\.google-analytics\\.com/.*", 410);
// Or whitelist what you need
server.whitelistRequests("https?://*.*.yoursite.com/.*. https://*.*.someOtherYourSite.*".split(","), 200);
Proxy proxy = server.seleniumProxy(); // Proxy is package org.openqa.selenium.Proxy
// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, proxy);
// start the driver ;
Webdriver driver = new FirefoxDriver(capabilities);
return driver;
But you should be able to dynamically configure the proxy to alternate request blocking.

TestCafe EC2 Network logs

We are "successfully" running our gherkin-testcafe build on ec2 headless against chromium. The final issue we are dealing with is that at a certain point in the test a CTA button is showing ...loading instead of Add to Bag, presumably because a service call that gets the status of the product, out of stock, in stock, no longer carry, etc. is failing. The tests work locally of course and we have the luxury of debugging locally opening chrome's dev env and inspecting the network calls etc. But all we can do on the ec2 is take a video and see where it fails. Is there a way to view the logs of all the calls being made by testcafe's proxy browser so we can confirm which one is failing and why? We are using. const rlogger = RequestLogger(/.*/, {
logRequestHeaders: true,
logResponseHeaders: true
});
to log our headers but not getting very explicit reasons why calls are not working.
TestCafe uses the debug module to perform internal logging functionality. So, in order to view the TestCafe proxy logs, you can set the DEBUG environment variable in the following manner:
export DEBUG='hammerhead:*'

How can I replace the server in Web Component Tester

I have a project set up based around the Polymer Starter Kit, which includes Web-Component-Tester
This project includes php server code which I would also like to test by writing tests to run in the browser which will utilise the PHP server code through Ajax Calls.
This implies replacing the server that Web Component Tester is using ONLY when testing server side code. I hope to make a separate gulp task for this.
Unfortunately, I don't understand the relationship between WCT, Selenium and what ever server is run currently. I can see that WCT command starts Selenium, but I can't find out what the web server is and how that is started. I suspect it is WCT, because there is configuration of the mapping of directories to urls, but other than that I haven't a clue, despite trying to read the code.
Can someone explain how I go about making it run its own server when testing the client, but relying on an already set up web server (nginx) when running the server. I can set nginx to run from local host, or an other domain if that is a way to choose a different configuration.
EDIT: I have now found that runner/webserver.js starts an express server, and that urls get mapped so the base directory for the test runner and the bower_components directory both get mapped to the /components url.
What is currently confusing me is in what circumstances this gets run. It appears that loading plugins somehow does it, but my understanding from reading the code for this is tenuous.
The answer is that web component tester itself has a comment in the runner/config.js file.
In wct-conf.js, you can use registerHooks key into the Object that gets returned to add a function that does
registerHooks: function(wct) {
wct.hook('prepare:webserver', function(app, done) {
var proxy = require('express-http-proxy');
app.use('/api',
proxy('pas.dev', {
forwardPath: function(req, res) {
return require('url').parse(req.url).path;
}
})
);
done();
});
This register hook function allows you to provide a route (/api in my case) which this proxies to a server which can run the php scripts.

Webdriver(Selenium2) - How to make selenium operate elements without wating for connecting to external AD links?

Environment:
- Selenium 2.39 Standalone Server
- PHP 5.4.11
- PHPUnit 3.7.28
- Chrome V31 & ChromeDriver v2.7
I'm testing a website,which invokes a lot of Advertisement Systems,such as Google AD.
The browser takes a lot of time to connect to external AD links , even all the elements of the page has already been loaded.
If my internet network was not fast when I ran my tests on a webpage,
Selenium would wait for a very long time ,since the AD links responsed slowly.
Under this condition ,Selenium usually waits for over 60 seconds, and throws a timeout exception.
I'm not sure how Senelium works, but it seems that Selenium has to wait for a sign of webpage's full loading, then pulls the DOM to find elements.
I want to make selenium operate elements without waiting for connectiong to external AD links.
Is there a way to do that ? Thank you very much.
I would suggest that you could make use of a proxy. Browsermob integrates well with selenium, very easy to use it:
// start the proxy
ProxyServer server = new ProxyServer(4444);
server.start();
// get the Selenium proxy object
Proxy proxy = server.seleniumProxy();
// This line will automatically return http.200 for any request going to google analytics
server.blacklistRequests("https?://.*\\.google-analytics\\.com/.*", 200);
// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, proxy);
// start the browser up
WebDriver driver = new FirefoxDriver(capabilities);
I'm not sure how Senelium works, but it seems that Selenium has to
wait for a sign of webpage's full loading, then pulls the DOM to find
elements.
It is pretty much like this. The default loading strategy is "NORMAL" which means:
NORMAL of type DOMString
The remote end MUST wait until the "document.readyState" of the frame currently handling commands equals "complete", or there are no
more outstanding network requests other than XMLHttpRequests.
I finally found a simple solution for my condition.
I decide to block these Ad requests and tried some firewall and proxy softwares,for example,
comodo,privatefirewall, etc.
comodo is too heavy and complex ,privatefirewall doesn't support wildcards, and firewall would interrupt tests. At last I choosed a proxy software CCproxy. Trial Version is enough.
I create a rule for localhost ,to make it can request my test website domain only, and all other requests are rejected.
Running a test costs about 1-2 minutes before and only 30 seconds now ,it's apparently more stable and fast without connecting to the useless Ad links.
Here're configuration steps:
1.launch CCproxy with Administor privilege( you should set it using Adminisrator in the file property)
2.click Options, select AutoStartup,select AutoDetected for Local IP Address. click OK.
3.create a txt file ,input your domains,like " *.rong360.com*;*.rong360.*; "
4.click Account, select PermitOnly for Permit Category;
click New, input 127.0.0.1 for IP Address/Range;
select WebFilter,click the E button at right side to create a filter;
click the ... button,select the text file you create at Step3,
select PermittedSites. click OK
click OK.
5.click OK to return to the main UI of CCproxy.
6.launch IE and config the local proxy with 127.0.0.1:808
other browsers will use this config automatically too.
now you can run the tests again , you'll feel better if have same condition :)