Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Introduce Appium
@testotips.io
Twitter id: @Kazu_cocoa
Appium
?
Appium is an open source test
automation framework for use
with native, hybrid and mobile
web apps.
It drives iOS and Andr...
from: http://www.3pillarglobal.com/insights/appium-a-cross-browser-mobile-automation-tool
Integration TestUnit Test
Flow of automated test
GUI Test
Feature Test
(E2E Test)
GUI / Feature testing
Integration TestUnit Test
GUI Test
Feature Test
(E2E Test)
$ npm install appium
($ npm install -g appium)
node_module/.bin
appium.js
appium-doctor.js
authorize_ios.js
$ $(npm bin)appium
node_modules/appium/bin/appium.js
var appium = require('../lib/server/main.js');	
!
var startRepl = function () {	
var hel...
node_modules/appium/lib/server/main.js
var http = require('http')	
, express = require('express')	
, favicon = require('se...
var loggerjs = require('./server/logger.js')	
, logger = loggerjs.get('appium')	
, UUID = require('uuid-js')	
, _ = requir...
!
node_modules/appium/lib/server/capabilities.js
var _ = require('underscore')	
, logger = require('./logger.js').get('app...
Appium
meets
iOS
Capabilities
IOS_CAPS_81 = {
automationName: 'Appium',
platformName: :ios,
platformVersion: '8.1',
deviceName: 'iPhone 6 P...
create new plist before start app
appium/lib/devices/ios/ios.js
IOS.prototype.setDeviceTypeInInfoPlist = function (cb) {	
...
Appium
meets
Android
Capabilities
ANDROID_CAPS = {
automationName: 'Appium',
platformName: :android,
platformVersion: '4.2',
deviceName: ‘Andro...
appium/lib/devices/android/android.js
Android.prototype.pushAppium = function (cb) {	
logger.debug("Pushing appium bootstr...
appium/lib/devices/android/bootstrap/
例えば、UiDeviceのpressBack()を使う
Common
Selectors
exports.checkValidLocStrat = function (strat, includeWeb, cb) {	
if (typeof includeWeb === "undefined") {	
includeWeb = fa...
XPath
find_element :xpath, ”なんらかのXPath"
accessibility id
find_element :accessibility_id, ”なんらかの要素"
css selector
find_element ...
iOS: UIAutomation
find_element :uiautomator,
"new UiSelector()
.className("android.widget.TextView")
.text("#{element_name}...
Run test
concurrently
Appium is just server
Appium1: $appium -p 4723 &
Appium2: $appium -p 4725 -bp 4726 &
Appium1
iOS App Android
Appium
appium...
Fin
One more tip
DroidDriver
DroidDriver
• Clone from Google to SauceLab(Appium)
• https://github.com/appium/droiddriver
• UiDeviceとか、UiElementとか使ってそう
...
Thanks
20150319 testotipsio
Upcoming SlideShare
Loading in …5
×

20150319 testotipsio

5,351 views

Published on

testotips.ioでの発表資料です

Published in: Software
  • Be the first to comment

20150319 testotipsio

  1. 1. Introduce Appium @testotips.io
  2. 2. Twitter id: @Kazu_cocoa
  3. 3. Appium ?
  4. 4. Appium is an open source test automation framework for use with native, hybrid and mobile web apps. It drives iOS and Android apps using the WebDriver protocol. from: http://appium.io/
  5. 5. from: http://www.3pillarglobal.com/insights/appium-a-cross-browser-mobile-automation-tool
  6. 6. Integration TestUnit Test Flow of automated test GUI Test Feature Test (E2E Test)
  7. 7. GUI / Feature testing Integration TestUnit Test GUI Test Feature Test (E2E Test)
  8. 8. $ npm install appium ($ npm install -g appium)
  9. 9. node_module/.bin appium.js appium-doctor.js authorize_ios.js
  10. 10. $ $(npm bin)appium
  11. 11. node_modules/appium/bin/appium.js var appium = require('../lib/server/main.js'); ! var startRepl = function () { var help = function () { console.log("nWelcome to the Appium CLI".cyan); console.log(" - Access the appium object via the object: 'appium'".grey); console.log(" - appium.run is the function to start the server".grey); console.log(" - args is the default params data structure".grey); console.log(" - set args.app then run appium.run(args);n".grey); return 'Thanks for asking'; }; ! help(); ! var r = repl.start('(appium): '); r.context.appium = appium; r.context.parser = parser(); r.context.help = help; r.context.args = { app: '/path/to/test/app' , udid: null , address: '127.0.0.1' , port: 4723 }; ! var connections = 0; var server = net.createServer(function (socket) { connections += 1; socket.setTimeout(5 * 60 * 1000, function () { socket.destroy(); }); repl.start("(appium): ", socket); }).listen(process.platform === "win32" ? ".pipenode-repl-sock-" + process.pid : "/tmp/node-repl-sock-" + process.pid); ! r.on('exit', function () { server.close(); process.exit(); });
  12. 12. node_modules/appium/lib/server/main.js var http = require('http') , express = require('express') , favicon = require('serve-favicon') , bodyParser = require('body-parser') , methodOverride = require('method-override') , morgan = require('morgan') // logger , routing = require('./routing.js') , path = require('path') , appium = require('../appium.js') , parserWrap = require('./middleware').parserWrap , appiumVer = require('../../package.json').version , appiumRev = null , async = require('async') , helpers = require('./helpers.js') , logFinalWarning = require('../helpers.js').logFinalDeprecationWarning , getConfig = require('../helpers.js').getAppiumConfig , allowCrossDomain = helpers.allowCrossDomain , catchAllHandler = helpers.catchAllHandler , checkArgs = helpers.checkArgs , configureServer = helpers.configureServer , startListening = helpers.startListening , conditionallyPreLaunch = helpers.conditionallyPreLaunch , prepareTmpDir = helpers.prepareTmpDir , requestStartLoggingFormat = require('./helpers.js').requestStartLoggingFormat , requestEndLoggingFormat = require('./helpers.js').requestEndLoggingFormat , domainMiddleware = require('./helpers.js').domainMiddleware;
  13. 13. var loggerjs = require('./server/logger.js') , logger = loggerjs.get('appium') , UUID = require('uuid-js') , _ = require('underscore') , Capabilities = require('./server/capabilities') , IOS = require('./devices/ios/ios.js') , Safari = require('./devices/ios/safari.js') , Android = require('./devices/android/android.js') , Selendroid = require('./devices/android/selendroid.js') , Chrome = require('./devices/android/chrome.js') , FirefoxOs = require('./devices/firefoxos/firefoxos.js') , jwpResponse = require('./devices/common.js').jwpResponse , status = require("./server/status.js"); ! var DT_IOS = "ios" , DT_SAFARI = "safari" , DT_ANDROID = "android" , DT_CHROME = "chrome" , DT_SELENDROID = "selendroid" , DT_FIREFOX_OS = "firefoxos"; node_modules/appium/lib/appium.js
  14. 14. ! node_modules/appium/lib/server/capabilities.js var _ = require('underscore') , logger = require('./logger.js').get('appium') , warnDeprecated = require('../helpers.js').logDeprecationWarning; ! var capsConversion = {...}; ! var okObjects = [...]; ! var requiredCaps = [...]; ! var strictRequiredCaps = [...]; ! var generalCaps = strictRequiredCaps.concat([...]); ! var androidCaps = [...]; ! var iosCaps = [...];
  15. 15. Appium meets iOS
  16. 16. Capabilities IOS_CAPS_81 = { automationName: 'Appium', platformName: :ios, platformVersion: '8.1', deviceName: 'iPhone 6 Plus', app: IOS_APP_PATH, bundleId: APP_BUNDLE_ID, ! calendarFormat: 'gregorian', ! sendKeyStrategy: 'grouped' ! localizableStringsDir: 'ja.lproj', language: 'ja', locale: 'ja_JP', ! screenshotWaitTimeout: 20 }
  17. 17. create new plist before start app appium/lib/devices/ios/ios.js IOS.prototype.setDeviceTypeInInfoPlist = function (cb) { var plist = path.resolve(this.args.app, "Info.plist"); var dString = this.getDeviceString(); var isiPhone = dString.toLowerCase().indexOf("ipad") === -1; var deviceTypeCode = isiPhone ? 1 : 2; parsePlistFile(plist, function (err, obj) { if (err) { logger.error("Could not set the device type in Info.plist"); return cb(err, null); } else { var newPlist; obj.UIDeviceFamily = [deviceTypeCode]; if (binaryPlist) { newPlist = bplistCreate(obj); } else { newPlist = xmlplist.build(obj); } fs.writeFile(plist, newPlist, function (err) { if (err) { logger.error("Could not save new Info.plist"); cb(err); } else { logger.debug("Wrote new app Info.plist with device type"); cb(); } }.bind(this)); } }.bind(this)); };
  18. 18. Appium meets Android
  19. 19. Capabilities ANDROID_CAPS = { automationName: 'Appium', platformName: :android, platformVersion: '4.2', deviceName: ‘Android’, app: ANDROID_APP_PATH, ! unicodeKeyboard: true, ! fullReset: true, screenshotWaitTimeout: 20 }
  20. 20. appium/lib/devices/android/android.js Android.prototype.pushAppium = function (cb) { logger.debug("Pushing appium bootstrap to device..."); var binPath = path.resolve(__dirname, "..", "..", "..", "build", "android_bootstrap", "AppiumBootstrap.jar"); fs.stat(binPath, function (err) { if (err) { cb(new Error("Could not find AppiumBootstrap.jar; please run " + "'grunt buildAndroidBootstrap'")); } else { this.adb.push(binPath, this.remoteTempPath(), cb); } }.bind(this)); }; ! Android.prototype.startApp = function (args, cb) { if (args.androidCoverage) { this.adb.androidCoverage(args.androidCoverage, args.appWaitPackage, args.appWaitActivity, cb); } else { this.adb.startApp({ pkg: args.appPackage, activity: args.appActivity, action: args.intentAction, category: args.intentCategory, flags: args.intentFlags, waitPkg: args.appWaitPackage, waitActivity: args.appWaitActivity, optionalIntentArguments: args.optionalIntentArguments, stopApp: args.stopAppOnReset }, cb); } };
  21. 21. appium/lib/devices/android/bootstrap/
  22. 22. 例えば、UiDeviceのpressBack()を使う
  23. 23. Common Selectors
  24. 24. exports.checkValidLocStrat = function (strat, includeWeb, cb) { if (typeof includeWeb === "undefined") { includeWeb = false; } var validStrats = [ 'xpath', 'id', 'name', 'class name' ]; var nativeStrats = [ '-ios uiautomation', 'accessibility id', '-android uiautomator' ]; var webStrats = [ 'link text', 'css selector', 'tag name', 'partial link text' ]; var nativeDeprecations = {}; var webDeprecations = {}; var deprecations = {name: 'accessibility id'};
  25. 25. XPath find_element :xpath, ”なんらかのXPath" accessibility id find_element :accessibility_id, ”なんらかの要素" css selector find_element :css_selector, ”なんらかの要素" # Ruby Client使用時
  26. 26. iOS: UIAutomation find_element :uiautomator, "new UiSelector() .className("android.widget.TextView") .text("#{element_name}");” find_element :uiautomation, ”$.mainApp().alert().buttons()[‘#{text}'];" Android: uiautomator
  27. 27. Run test concurrently
  28. 28. Appium is just server Appium1: $appium -p 4723 & Appium2: $appium -p 4725 -bp 4726 & Appium1 iOS App Android Appium appium_server = “http://127.0.0.1: 4723” appium_server = “http://127.0.0.1: 4725” adb: 4726
  29. 29. Fin
  30. 30. One more tip
  31. 31. DroidDriver
  32. 32. DroidDriver • Clone from Google to SauceLab(Appium) • https://github.com/appium/droiddriver • UiDeviceとか、UiElementとか使ってそう • https://github.com/appium/droiddriver/tree/master/droiddriver- android_support_test • android-support-test libraryと並行して使うユースケースもある が、android-support-test libraryはまだ開発されて日が浅いので optionとしての統合に留められている
  33. 33. Thanks

×