天天看點

Macaca自動化測試架構 介紹 前置準備 Macaca環境安裝 注意事項 官網示例 啟動 常用指令 代碼

介紹

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。

位址:https://nodejs.org/en/

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/[email protected]/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/[email protected]/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()                

繼續閱讀