或可直接查詢testerhome發表的文章: https://testerhome.com/topics/7898
介紹
Macaca是一套完整的自動化測試解決方案,基於node.js開發。由阿里巴巴公司開源:
地址:https://github.com/macacajs/
特點:
同時支持PC端和移動端(Android、iOS)自動化測試。
支持JavaScript(Node.js)、Java、Python。
前置准備
安裝Java
Java下載地址:(http://www.java.com/zh_CN/download/manual.jsp)
打開下載鏈接選擇相應的版本進行下載。我們以Windows安裝JDK為例,
雙擊下載的JDK ,設置安裝路徑。這里我選擇默認安裝在:
D:\Program Files (x86)\Java\jdk1.8.0_25\目錄下。
下面設置環境變量:
【我的電腦】->右鍵菜單--->屬性--->高級--->環境變量--->系統變量-->新建:
變量名:JAVA_HOME
變量值:D:\Program Files (x86)\Java\jdk1.8.0_25
變量名:CALSS_PATH
變量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
找到path變量名—>“編輯”添加:
變量名:PATH
變量值:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
安裝Ant構建工具
Apache Ant,是一個將軟件編譯、測試、部署等步驟聯系在一起加以自動化的一個工具,大多用於Java環境中的軟件開發。
下載地址:http://ant.apache.org/manualdownload.cgi
下載zip包之后解壓,我的解壓位置為:D:\java\apache-ant
然后,將該目錄添加到環境變量path下面。
變量名:PATH
變量值:D:\java\apache-ant\bin;
安裝Android SDK
Android SDK提供了你的API庫和開發工具構建,測試和調試應用程序
官方地址:(http://developer.android.com)
如果無法下載,你也可以通過該地址下載Studio與SDK。
下載地址: (http://www.android-studio.org/index.php/download)
如果只是想運行Android模擬器,單獨下載SDK也可以。
Android SDK(Windows)百度網盤下載地址:(http://pan.baidu.com/s/1kVOvxEB)
下面設置環境變量:
【我的電腦】右鍵菜單--->屬性--->高級--->環境變量--->系統變量-->新建..
變量名:ANDROID_HOME
變量值:D:\android\android-sdk-windows (以本機為主)
找到path變量名—>“編輯”添加:
變量名:PATH
變量值:;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\tools;
iOS前置准備
-
安裝homebrew
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" -
安裝ios-webkit-debug-proxy
brew install ios-webkit-debug-proxy
Macaca環境安裝
1、Macaca由Node.js開發,所以需要安裝Node.js。
2、安裝Node.js完成。 首先切換切換淘寶源,因為國外資源訪問很慢,而且有些資源還無法下載。
- npm install -g cnpm --registry=https://registry.npm.taobao.org
3、通過淘寶源安裝 macaca-cli
- cnpm i macaca-cli -g
4、安裝webdriver-client
- cnpm install webdriver-client
5、安裝macaca-electron
- cnpm install macaca-electron -g
macaca-electron是基於Electron開發的Macaca驅動,是Macaca驅動之一。
6、安裝macaca-chrome
- cnpm install macaca-chrome -g
7、安裝Macaca Python Client,支持pip安裝。
下載地址:https://pypi.python.org/pypi/wd
- python3 -m pip install wd
8、安裝macaca-chromedriver
- cnpm install macaca-chromedriver -g
9、安裝macaca-android
- cnpm install macaca-android -g
10、安裝macaca-ios
- cnpm i macaca-ios -g
注意事項
1、npm方式安裝慢的問題
- npm install -g cnpm --registry=http://r.cnpmjs.org (或用淘寶鏡像:registry = https://registry.npm.taobao.org)
- 或者先安裝cnpm,再用cnpm代替npm命令 (安裝cnpm方式,請參照上述)
2、切換源方式
按快捷鍵【Win+X】 --> 選擇“提示命令符(管理員)A”,打開超級管理員權限的cmd命令窗口,
輸入命令:“npm config set registry https://registry.npm.taobao.orgnpm”
回車,即可跟換源,輸入命令“ config get registry ”回車可以查看更換是否成功
3、安裝chromedriver超時失敗
- npm install -g chromedriver --chromedriver_cdnurl=http://chromedriver.storage.googleapis.com
- 或者 npm install -g chromedriver --chromedriver_cdnurl=http://npm.taobao.org/mirrors/chromedriver
官網示例
- Sample示例地址: https://github.com/macaca-sample/macaca-test-sample-python
- Python API文檔:https://macacajs.github.io/wd.py/
啟動
啟動Macaca服務
- macaca server --verbose 【加--verbose,打印詳細日志】
- python tests/macaca-desktop-sample.test.py 【運行測試】
常用命令
安裝
- npm i macaca-cl -g
服務端
- macaca server (正常模式)
- macaca server -p 3456 (設置端口)
- macaca server -p 3456 & (設置端口后台運行)
- macaca server --verbose(輸出詳細日志)
測試
- macaca run (運行當前目錄用例集)
- macaca run -d ./test (運行指定目錄下用例集)
檢查
- macaca doctor (環境檢查)
幫助
- macaca -h
- macaca server -h
- macaca run -h
- macaca doctor -h
代碼
- macaca electron示例
import unittest
import time
from macaca import WebDriver
desired_caps = {
'platformName': 'desktop',
'browserName': 'electron'
}
server_url = {
'hostname': 'localhost',
'port': 3456
}
class MacacaTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = WebDriver(desired_caps, server_url)
cls.driver.init()
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_get_url(self):
self.driver \
.set_window_size(1280, 800) \
.get('https://www.baidu.com')
def test_search_macaca(self):
self.driver \
.element_by_id('kw') \
.send_keys('macaca')
self.driver \
.element_by_id('su') \
.click()
time.sleep(3)
html = self.driver.source
self.assertTrue('macaca' in html)
self.assertTrue(
self.driver.element_by_css_selector_if_exists(
'#head > div.head_wrapper'))
self.driver \
.element_by_xpath_or_none('//*[@id="kw"]') \
.send_keys(' elementByXPath')
self.driver \
.element_by_id('su') \
.click()
self.driver.take_screenshot()
if __name__ == '__main__':
unittest.main()
- chrome 示例
#coding=utf-8
import unittest
from macaca import WebDriver
from time import sleep
desired_caps = {
'platformName': 'Desktop', #// iOS, Android, Desktop
'browserName': 'Chrome', #// Chrome, Electron
}
# 對應Macaca服務的ip和端口號。
server_url = {
'hostname': '127.0.0.1',
'port': 3456
}
class MacacaTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = WebDriver(desired_caps, server_url)
cls.driver.init()
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_get_url(self):
self.driver.get('https://www.baidu.com')
self.assertEqual(self.driver.title, '百度一下,你就知道')
def test_search_macaca(self):
self.driver.element_by_id("kw").send_keys("macaca")
self.driver.element_by_id("su").click()
sleep(2)
title = self.driver.title
self.assertTrue('macaca',title)
if __name__ == '__main__':
unittest.main()
- android示例
#coding=utf-8
import unittest
import os
import time
from macaca import WebDriver
desired_caps = {
'platformName': 'android',
'app': 'https://npmcdn.com/android-app-bootstrap@latest/android_app_bootstrap/build/outputs/apk/android_app_bootstrap-debug.apk',
'reuse': 3
}
server_url = {
'hostname': 'localhost',
'port': 3456
}
def switch_to_webview(driver):
contexts = driver.contexts
driver.context = contexts[-1]
return driver
def switch_to_native(driver):
contexts = driver.contexts
driver.context = contexts[0]
return driver
class MacacaTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = WebDriver(desired_caps, server_url)
cls.driver.init()
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_01_login(self):
self.driver \
.element_by_xpath('//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.EditText[1]') \
.send_keys('中文+Test+12345678') \
els = self.driver \
.elements_by_class_name('android.widget.EditText')
els[1].send_keys('111111')
self.driver \
.element_by_name('Login') \
.click()
def test_02_scroll_tableview(self):
self.driver \
.element_by_name('HOME') \
.click()
self.driver \
.element_by_name('list') \
.click()
def test_03_gesture(self):
self.driver \
.touch('drag', {
'fromX': 200,
'fromY': 400,
'toX': 200,
'toY': 100,
'steps': 50
})
time.sleep(1)
self.driver \
.touch('drag', {
'fromX': 100,
'fromY': 100,
'toX': 100,
'toY': 400,
'steps': 50
})
self.driver \
.element_by_name('Alert') \
.click()
time.sleep(1)
self.driver \
.accept_alert() \
.back()
time.sleep(1)
self.driver \
.element_by_name('Gesture') \
.click()
self.driver \
.touch('tap', {
'x': 100,
'y': 100
})
time.sleep(1)
self.driver \
.touch('doubleTap', {
'x': 100,
'y': 100
})
time.sleep(1)
self.driver \
.touch('press', {
'x': 100,
'y': 100,
'steps': 100
})
time.sleep(1)
self.driver \
.element_by_id('com.github.android_app_bootstrap:id/info') \
.touch('pinch', {
'percent': 200,
'steps': 200
})
time.sleep(1)
self.driver \
.touch('drag', {
'fromX': 100,
'fromY': 100,
'toX': 100,
'toY': 600,
'steps': 100
})
def test_04_webview(self):
self.driver \
.element_by_name('Webview') \
.click()
time.sleep(3)
self.driver.save_screenshot('./webView.png') # save screen shot
switch_to_webview(self.driver) \
.element_by_id('pushView') \
.touch('tap')
switch_to_webview(self.driver) \
.element_by_id('popView') \
.touch('tap')
def test_05_web(self):
switch_to_native(self.driver) \
.element_by_name('Baidu') \
.touch('tap')
time.sleep(3)
self.driver.save_screenshot("./baidu.png")
switch_to_webview(self.driver) \
.element_by_id('index-kw') \
.send_keys('macaca')
self.driver \
.element_by_id('index-bn') \
.touch('tap')
def test_06_logout(self):
switch_to_native(self.driver) \
.element_by_name('PERSONAL') \
.click()
self.driver.element_by_name('Logout') \
.click()
if __name__ == '__main__':
unittest.main()
- android示例【簡精版】
#coding=utf-8
import unittest
import time
from macaca import WebDriver
desired_caps = {
'platformName': 'Android', # iOS, Android, Desktop
#'browserName': 'Chrome', # Chrome, Electron
"package": "com.huawei.iptv.stb",
"activity": "com.huawei.iptv.stb.ui.HeadTabActivity",
"deviceName":"192.168.1.105:5555",
}
server_url = {
'hostname': '127.0.0.1',
'port': 3456
}
class MacacaTest(unittest.TestCase):
def setUp(self):
self.driver = WebDriver(desired_caps, server_url)
self.driver.init()
def tearDown(self):
self.driver.quit()
def test_macaca(self):
el=self.driver.element_by_name("直播")
el.click()
time.sleep(2)
if __name__ == '__main__':
unittest.main()
- iOS示例
import unittest
import os
import time
from macaca import WebDriver
desired_caps = {
'platformName': 'iOS',
'platformVersion': '10.0',
'deviceName': 'iPhone 5s',
'app': 'https://npmcdn.com/ios-app-bootstrap@latest/build/ios-app-bootstrap.zip',
}
server_url = {
'hostname': 'localhost',
'port': 3456
}
def switch_to_webview(driver):
contexts = driver.contexts
driver.context = contexts[-1]
return driver
def switch_to_native(driver):
contexts = driver.contexts
driver.context = contexts[0]
return driver
class MacacaTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = WebDriver(desired_caps, server_url)
cls.driver.init()
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_01_login(self):
self.driver \
.element_by_xpath('//XCUIElementTypeTextField[1]') \
.send_keys('中文+Test+12345678') \
self.driver \
.element_by_xpath('//XCUIElementTypeSecureTextField[1]') \
.send_keys('111111') \
self.driver \
.element_by_name('Login') \
.click()
def test_02_scroll_tableview(self):
self.driver \
.element_by_name('HOME') \
.click()
self.driver \
.element_by_name('list') \
.click()
def test_03_gesture(self):
self.driver \
.touch('drag', {
'fromX': 200,
'fromY': 400,
'toX': 200,
'toY': 100,
'duration': 2
})
time.sleep(1)
self.driver \
.touch('drag', {
'fromX': 100,
'fromY': 100,
'toX': 100,
'toY': 400,
'duration': 2
})
self.driver \
.element_by_name('Alert') \
.click()
time.sleep(1)
driver \
.accept_alert() \
.back()
time.sleep(1)
self.driver \
.element_by_name('Gesture') \
.click()
self.driver \
.touch('tap', {
'x': 100,
'y': 100
})
time.sleep(1)
self.driver \
.touch('doubleTap', {
'x': 100,
'y': 100
})
time.sleep(1)
self.driver \
.touch('press', {
'x': 100,
'y': 100,
'duration': 1
})
time.sleep(1)
self.driver \
.element_by_id('info') \
.touch('pinch', {
'scale': 2,
'velocity': 1
})
time.sleep(1)
self.driver \
.touch('drag', {
'fromX': 100,
'fromY': 100,
'toX': 100,
'toY': 600,
'steps': 100
})
def test_04_webview(self):
self.driver \
.element_by_name('Webview') \
.click()
time.sleep(3)
self.driver.save_screenshot('./webView.png') # save screen shot
switch_to_webview(self.driver) \
.element_by_id('pushView') \
.touch('tap')
switch_to_webview(self.driver) \
.element_by_id('popView') \
.touch('tap')
def test_05_web(self):
switch_to_native(self.driver) \
.element_by_name('Baidu') \
.touch('tap')
time.sleep(3)
self.driver.save_screenshot("./baidu.png")
switch_to_webview(self.driver) \
.element_by_id('index-kw') \
.send_keys('macaca') \
.element_by_id('index-bn') \
.touch('tap')
def test_06_logout(self):
switch_to_native(self.driver) \
.element_by_name('PERSONAL') \
.click()
self.driver.element_by_name('Logout') \
.click()
if __name__ == '__main__':
unittest.main()
結束語
無