karate mobile testing with a real device, not an emulator. I can't connect to a real device - appium

#android_sample_test
Feature: Simple test with appium
Scenario: launch chrome in appium
* configure driver =
"""
{
type: 'android',
webDriverPath : "/wd/hub",
start: true,
httpConfig : { readTimeout: 120000 }
}
"""
* def desiredConfig =
"""
{
"app":"/home/yabesh/Downloads/UiDemo.apk",
"newCommandTimeout" : 300,
"platformVersion" : "9.0",
"platformName" : "Android",
"connectHardwareKeyboard" : true,
"deviceName" : "emulator-554",
"avd": "Galaxy_Nexus_API_33",
"automationName" : "UiAutomator2",
}
"""
* driver { webDriverSession: { desiredCapabilities : "#(desiredConfig)"} }
* delay(5000).screenshot()
* delay(2500)
* close()
This is my test case for android. It works in android emulator. It works on avd not adb. I don't know how to connect a real device through (usb debugging or wifi debugging). Need help

Related

SauceLabs hybrid app test automation session is not starting on iOS devices

I'm trying to run the automation tests for hybrid app on SauceLabs (SL) on Android and iOS. For some strange reason when I start execution on SL with iOS devices I can only see device with a spinner that is trying to start a session and it is going in loop for more than 20 min (that is how much I gave tests time to timeout last time I tried). For android devices is working perfectly fine and it finishes test execution. Some input about tools and environment:
Test frameworks: Appium, WebdriverIO, Cucumber.
Language: JS
Selectors used in code (Page objects): HTML custom selectors for each button/input field etc, from ionic (hybrid) app
In order to be able to access those selectors, in appium configuration file for SL I put following ('appium:autoWebview': true) which is suggested when you are dealing with hybrid apps. Checked with other projects that are working too (project that are using saucelabs with appium), config file is written in good format.
Artifacts used: .ipa app build for iOS (built properly, I was able to use it in manual testing), .apk for Android (all good there too).
Is there anything I'm missing to configure on my side to be able to run iOS tests on SL by using frameworks and locator/selector strategy I mentioned above? Or is it maybe some bug on their side that I missed to find? I spent few days researching this issue and couldn't find anything helpful besides official documentation which (I think) I followed in good way.
I'm sharing 3 config files I have for this (1 shared config, 1 iOS and 1 for Android):
Shared config
const { generate } = require('multiple-cucumber-html-reporter');
const { removeSync } = require('fs-extra');
exports.config = {
// ====================
// Runner and framework
// Configuration
// ====================
runner: 'local',
framework: 'cucumber',
sync: false,
logLevel: 'trace',
deprecationWarnings: true,
outputDir: './test-report/output',
bail: 0,
baseUrl: 'http://the-internet.herokuapp.com',
waitforTimeout: 6000,
connectionRetryTimeout: 90000,
connectionRetryCount: 3,
specs: ['tests/features/**/*.feature'],
reporters: [
'spec',
[
'cucumberjs-json',
{
jsonFolder: '.tmp/json/',
language: 'en',
},
],
],
cucumberOpts: {
requireModule: ['#babel/register'],
backtrace: false,
compiler: [],
dryRun: false,
failFast: false,
format: ['pretty'],
colors: true,
snippets: true,
source: true,
profile: [],
strict: false,
tags: [],
timeout: 100000,
ignoreUndefinedDefinitions: false,
tagExpression: 'not #skip',
},
// ====================
// Appium Configuration
// ====================
services: ['appium'],
appium: {
// For options see
// https://github.com/webdriverio/webdriverio/tree/master/packages/wdio-appium-service
// If you need a logs from appium server, make log equal true.
log: false,
args: {
// For arguments see
// https://github.com/webdriverio/webdriverio/tree/master/packages/wdio-appium-service
},
command: 'appium',
},
port: 4723,
// ====================
// Some hooks
// ====================
/**
* Gets executed once before all workers get launched.
* #param {Object} config wdio configuration object
* #param {Array.<Object>} capabilities list of capabilities details
*/
onPrepare: function() {
// Remove the `.tmp/` folder that holds the json and report files
removeSync('.tmp/');
},
/**
* Gets executed after all workers have shut down and the process is about to exit.
* An error thrown in the `onComplete` hook will result in the test run failing.
* #param {Object} exitCode 0 - success, 1 - fail
* #param {Object} config wdio configuration object
* #param {Array.<Object>} capabilities list of capabilities details
* #param {<Object>} results object containing test results
*/
onComplete: () => {
// Generate the report when it all tests are done
generate({
// Required
// This part needs to be the same path where you store the JSON files
// default = '.tmp/json/'
jsonDir: '.tmp/json/',
reportPath: '.tmp/report/',
saveCollectedJSON: true,
});
},
//This code is responsible for taking the screenshot in case of error and attaching it to the report
afterStep(uri, feature, scenario) {
if (scenario.error) {
driver.takeScreenshot();
}
},
afterScenario() {
driver.reset();
},
afterSession() {
driver.closeApp();
},
};
iOS SL config (I put stars to API keys for purpose of privacy):
const { config } = require('../wdio.shared.conf');
// ============
// Specs
// ============
config.cucumberOpts.require = ['./tests/steps/**/app*.steps.js'];
// ============
// Capabilities
// ============
config.capabilities = [
{
deviceName: 'iPhone XR',
// The reference to the app
testobject_app_id: '1',
testobject_api_key: '00768686F013470CB81060**********',
// The name of the test for in the cloud
testobject_test_name: 'IOS run',
// Some default settings
platformName: 'iOS',
idleTimeout: 180,
maxInstances: 6,
// testobject_cache_device: true,
noReset: true,
orientation: 'PORTRAIT',
newCommandTimeout: 180,
phoneOnly: true,
tabletOnly: false,
autoWebview: true
},
];
// =========================
// Sauce RDC specific config
// =========================
config.services = ['sauce'];
config.region = 'eu';
// This port was defined in the `wdio.shared.conf.js`
delete config.port;
exports.config = config;
Android SL config:
const { config } = require('../wdio.shared.conf');
// ============
// Specs
// ============
config.cucumberOpts.require = ['./tests/steps/**/app*.steps.js'];
// ============
// Capabilities
// ============
config.capabilities = [
{
deviceName: 'Samsung Galaxy S9',
// The reference to the app
testobject_app_id: '1',
testobject_api_key: '42724CEF3061453C9F45B1**********',
// The name of the test for in the cloud
testobject_test_name: 'Android run',
// Some default settings
platformName: 'Android',
idleTimeout: 180,
maxInstances: 6,
testobject_cache_device: true,
noReset: true,
orientation: 'PORTRAIT',
newCommandTimeout: 180,
phoneOnly: true,
tabletOnly: false,
autoWebview: true
},
];
// =========================
// Sauce RDC specific config
// =========================
config.services = ['sauce'];
config.region = 'eu';
// This port was defined in the `wdio.shared.conf.js`
delete config.port;
exports.config = config;
Appium Desktop caps:
{
"platformName": "iOS",
"platformVersion": "13",
"deviceName": "iPhone 11 Pro",
"app": "path-to-ipa"
}

"Error: no such session" Webdriver-IO, Appium

I have setup Cucumber, Webdriver-IO, and Appium. Everything appears to be talking to each other, however I'm getting Error: no such session when trying to navigate to http://google.com.
On the Android device it opens up the Chrome browser, then closes it really fast.
webdriverio.js
//webdriverio.js
let client = WebDriverIO.remote({
desiredCapabilities: {
platformName: 'Android',
browserName: 'chrome',
deviceName: 'test',
},
host: 'localhost',
port: 4723,
waitForTimeout: 120 * 1000,
});
global.client = client;
module.exports = function() {
this.registerHandler('BeforeFeatures', function(event, done) {
client.init().call(done);
});
this.registerHandler('AfterFeatures', function(event, done) {
client.end().call(done);
});
};
env.js
// env.js
module.exports = function() {
// added because default 50000 ms was long enough
this.setDefaultTimeout(60 * 1000);
};
search_steps.js
// search_steps.js
module.exports = function() {
this.Given('I have visited Google', function (done) {
client
.url('http://google.com')
.call(done);
});
this.When('I search for {arg1:stringInDoubleQuotes}', function (arg1, done) {
// Write code here that turns the phrase above into concrete actions
client
.setValue('input[name="q"]', 'Kittens')
.call(done);
});
this.Then('I see {arg1:stringInDoubleQuotes}', function (arg1, done) {
// Write code here that turns the phrase above into concrete actions
client
.getValue('input[name="q"]').then(function(text){
expect('Kittens').to.eql(text);
})
.call(done);
});
};
The issue is chromedriver 2.21.371459 that is shipped with my version of Appium (1.3.5) for Mac. I downloaded the latest version of chromedriver and overwritten the existing one that is shipped with Appium. See the answer here Chrome opens for a second and the crashes for windows. For mac the location of the chromedriver exec shipped with Appium is. /Applications/Appium.app/Contents/Resources/node_modules/appium/node_modules/appium-android-driver/node_modules/appium-chromedriver/chromedriver/mac

Facebook Analytics not working with ios device

I had added app analytic for such events in my application which
perfectly works with iOS Simulator, but not with iOS device
When I run it on iOS Simulator, it gives me below log
Events: [
{
"event" : {
"_eventName" : "XXX",
"_logTime" : 1446626494,
"User ID" : "159",
},
"isImplicit" : false
}
]
Flush Result : Success
When I run it on iOS device, it gives me below log
Events: [
{
"event" : {
"_eventName" : "XXX",
"_logTime" : 1446626494,
"User ID" : "159",
},
"isImplicit" : false
}
]
Flush Result : No Connectivity
Please help me if anyone know issue.
Make sure that you are logged in with Developer Facebook ID in that
iOS device from which you had generated Facebook App ID.

appium safari ios gives error: The environment unavailable

I run appium iphone test with command mocha ios-safari.js and it gives error:
The environment you requested was unavailable
Where ios-safari.js is example downloaded from appium samples:
"use strict";
require("./helpers/setup");
var wd = require("wd"),
_ = require('underscore'),
serverConfigs = require('./helpers/appium-servers');
describe("ios safari", function () {
this.timeout(300000);
var driver;
var allPassed = true;
before(function () {
var serverConfig = process.env.SAUCE ?
serverConfigs.sauce : serverConfigs.local;
driver = wd.promiseChainRemote(serverConfig);
require("./helpers/logging").configure(driver);
var desired = _.clone(require("./helpers/caps").ios81);
desired.browserName = 'safari';
if (process.env.SAUCE) {
desired.name = 'ios - safari';
desired.tags = ['sample'];
}
return driver.init(desired);
});
after(function () {
return driver
.quit()
.finally(function () {
if (process.env.SAUCE) {
return driver.sauceJobStatus(allPassed);
}
});
});
afterEach(function () {
allPassed = allPassed && this.currentTest.state === 'passed';
});
it("should get the url", function () {
return driver
.get('https://www.google.com')
.sleep(1000)
.waitForElementByName('q', 5000)
.sendKeys('sauce labs')
.sendKeys(wd.SPECIAL_KEYS.Return)
.sleep(1000)
.title().should.eventually.include('sauce labs');
});
it("should delete cookie passing domain and path", function () {
var complexCookieDelete = function(name, path, domain) {
return function() {
path = path || '|';
return driver.setCookie({name: name, value: '', path: path,
domain: domain, expiry: 0});
};
};
return driver
.get('http://en.wikipedia.org')
.waitForElementByCss('.mediawiki', 5000)
.allCookies() // 'GeoIP' cookie is there
.deleteCookie('GeoIP')
.allCookies() // 'GeoIP' is still there, because it is set on
// the .wikipedia.org domain
.then(complexCookieDelete('GeoIP', '/', '.wikipedia.org'))
.allCookies() // now 'GeoIP' cookie is gone
.sleep(1000);
});
});
The appium log is the following:
info: [debug] Error: Could not find a device to launch. You requested
'iPhone 6 (8.1 Simulator)',
but the available devices were: [
"iPad 2 (8.3 Simulator) [2F86D724-B8D6-4F22-B5E8-97B437C9ACFB]",
"iPad Air (8.3 Simulator) [8A07B826-AF59-4FC4-BC8E-21B37ADAF539]",
"iPad Retina (8.3 Simulator) [9C589CB6-1CF4-437E-83DB-1270DB1599FC]",
"iPhone 4s (8.3 Simulator) [31F567A4-5346-4E1A-B414-C45062105964]",
"iPhone 5 (8.3 Simulator) [E820B152-B5B4-4A79-B9DE-3A1F49859662]",
"iPhone 5s (8.3 Simulator) [5A07EBE7-264A-4571-BA9E-1F17C882ADE3]",
"iPhone 6 (8.3 Simulator) [58856942-BD3F-45C6-9B1B-93102851B37E]",
"iPhone 6 Plus (8.3 Simulator)
Since I recenlty have updated X code to last version seemingly I should change device name somewhere in config from iPhone 6 (8.1 Simulator) to iPhone 6 (8.3 Simulator) [58856942-BD3F-45C6-9B1B-93102851B37E]. But where exactly should I do this - cannot figure out.
You specify the target device when you start an Appium session. On the command line, use '--device-name' parameter. In the Appium UI, you specify which device you want there in the iOS tab. I've found it to be a bit finicky about the name. I've had the most success being as general as necessary to differentiate between devices. IOW, try 'iPhone 6' or 'iPhone 5 (8.3 simulator)' instead of the entire string.

How do I detect what iOS device my function tests are running on?

I currently have a number of function tests written in javascript using Apple's UIAutomation API. The tests are written for iPhone, but the application also supports the iPad.
To extend my tests to run on an iPad I need to make some adjustments in the code, but first I need to find out what device is running the tests.
How do I detect what device/simulator is running the tests? when I'm running the javascript tests from the Automation tool.
UIATarget.localTarget().model() holds the information about which device the tests are running on.
I have discovered Alex Vollmer's tuneup_js library. It allows for device independent code to some extent as least.
e.g.)
test("my test", function(target, app) {
assertWindow({
"navigationBar~iphone": {
leftButton: { name: "Back" },
rightButton: { name: "Done" }
},
"navigationBar~ipad": {
leftButton: null,
rightButton: { name: "Cancel" }
},
});
});
edit
Found the following in tuneup_js:
/**
* A convenience method for detecting that you're running on an iPad
*/
isDeviceiPad: function() {
return this.model().match(/^iPad/) !== null;
},
/**
* A convenience method for detecting that you're running on an
* iPhone or iPod touch
*/
isDeviceiPhone: function() {
return this.model().match(/^iPhone/) !== null;
}
With these I'll be able to write device specific code.
Follow the documentation provided here, you will get all the information:
https://developer.apple.com/library/ios/#documentation/ToolsLanguages/Reference/UIATargetClassReference/UIATargetClass/UIATargetClass.html
//Here is the script I am using to get the device name, os version, bundle id, target etc..
#import "tuneupjs/Utilities.js"
var target = UIATarget.localTarget();
var app_bundle_id = target.frontMostApp().bundleID();
UIALogger.logDebug("App Bundle Id : " + app_bundle_id);
if(app_bundle_id.strContains("ShazamDev"))
UIALogger.logDebug("Running UIA Scripts for ShazamDev");
var device_name = target.name();
UIALogger.logDebug("Phone Name : " + target.name());
var device_model = target.model();
UIALogger.logDebug("Device Model: " + device_model);
//UIALogger.logDebug("System Name: " + target.systemName());
var ios_version = target.systemVersion();
UIALogger.logDebug("IOS Version: " + ios_version);
Here is the code for StrContains method in my Utilities file
String.prototype.strContains = function(value, ignorecase) {
if (ignorecase) {
return (this.toLowerCase().indexOf(value.toString().toLowerCase()) != -1);
}
else {
return this.indexOf(value) != -1;
}
};

Resources