Macaca 自动化框架 [Python 系列]

简介: 或可直接查询testerhome发表的文章: https://testerhome.com/topics/7898介绍Macaca是一套完整的自动化测试解决方案,基于node.js开发。由阿里巴巴公司开源:地址:https://github.com/macacajs/特点:同时支持PC端和移动端(Android、iOS)自动化测试。

或可直接查询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前置准备

Macaca环境安装

1、Macaca由Node.js开发,所以需要安装Node.js。

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

2、安装Node.js完成。 首先切换切换淘宝源,因为国外资源访问很慢,而且有些资源还无法下载。

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方式安装慢的问题

2、切换源方式
按快捷键【Win+X】 --> 选择“提示命令符(管理员)A”,打开超级管理员权限的cmd命令窗口,
输入命令:“npm config set registry https://registry.npm.taobao.orgnpm
回车,即可跟换源,输入命令“ config get registry ”回车可以查看更换是否成功

3、安装chromedriver超时失败

官网示例

启动

启动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()

结束语

技术改变世界! --狂诗绝剑
目录
相关文章
|
6月前
|
Java 数据处理 索引
(Pandas)Python做数据处理必选框架之一!(二):附带案例分析;刨析DataFrame结构和其属性;学会访问具体元素;判断元素是否存在;元素求和、求标准值、方差、去重、删除、排序...
DataFrame结构 每一列都属于Series类型,不同列之间数据类型可以不一样,但同一列的值类型必须一致。 DataFrame拥有一个总的 idx记录列,该列记录了每一行的索引 在DataFrame中,若列之间的元素个数不匹配,且使用Series填充时,在DataFrame里空值会显示为NaN;当列之间元素个数不匹配,并且不使用Series填充,会报错。在指定了index 属性显示情况下,会按照index的位置进行排序,默认是 [0,1,2,3,...] 从0索引开始正序排序行。
466 0
|
6月前
|
存储 Java 数据处理
(numpy)Python做数据处理必备框架!(一):认识numpy;从概念层面开始学习ndarray数组:形状、数组转置、数值范围、矩阵...
Numpy是什么? numpy是Python中科学计算的基础包。 它是一个Python库,提供多维数组对象、各种派生对象(例如掩码数组和矩阵)以及用于对数组进行快速操作的各种方法,包括数学、逻辑、形状操作、排序、选择、I/0 、离散傅里叶变换、基本线性代数、基本统计运算、随机模拟等等。 Numpy能做什么? numpy的部分功能如下: ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组 用于对整组数据进行快速运算的标准数学函数(无需编写循环)。 用于读写磁盘数据的工具以及用于操作内存映射文件的工具。 线性代数、随机数生成以及傅里叶变换功能。 用于集成由C、C++
544 1
|
6月前
|
Java 数据挖掘 数据处理
(Pandas)Python做数据处理必选框架之一!(一):介绍Pandas中的两个数据结构;刨析Series:如何访问数据;数据去重、取众数、总和、标准差、方差、平均值等;判断缺失值、获取索引...
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。 Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。 Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。
646 0
|
6月前
|
Java 数据处理 索引
(numpy)Python做数据处理必备框架!(二):ndarray切片的使用与运算;常见的ndarray函数:平方根、正余弦、自然对数、指数、幂等运算;统计函数:方差、均值、极差;比较函数...
ndarray切片 索引从0开始 索引/切片类型 描述/用法 基本索引 通过整数索引直接访问元素。 行/列切片 使用冒号:切片语法选择行或列的子集 连续切片 从起始索引到结束索引按步长切片 使用slice函数 通过slice(start,stop,strp)定义切片规则 布尔索引 通过布尔条件筛选满足条件的元素。支持逻辑运算符 &、|。
338 0
|
6月前
|
存储 数据采集 监控
Python定时爬取新闻网站头条:从零到一的自动化实践
在信息爆炸时代,本文教你用Python定时爬取腾讯新闻头条,实现自动化监控。涵盖请求、解析、存储、去重、代理及异常通知,助你构建高效新闻采集系统,适用于金融、电商、媒体等场景。(238字)
1052 2
|
6月前
|
数据采集 人工智能 自然语言处理
Playwright MCP 浏览器自动化框架全面解析
Playwright MCP是微软推出的开源项目,结合Playwright与MCP协议,让AI通过结构化数据直接操作浏览器。告别传统视觉识别,实现高效、精准的网页自动化,广泛应用于测试、爬虫、办公自动化等场景,大幅提升效率与可靠性。
|
7月前
|
机器学习/深度学习 算法 PyTorch
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
199 1
|
7月前
|
机器学习/深度学习 算法 PyTorch
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
318 0
|
7月前
|
数据采集 监控 Shell
无需Python:Shell脚本如何成为你的自动化爬虫引擎?
Shell脚本利用curl/wget发起请求,结合文本处理工具构建轻量级爬虫,支持并行加速、定时任务、增量抓取及分布式部署。通过随机UA、异常重试等优化提升稳定性,适用于日志监控、价格追踪等场景。相比Python,具备启动快、资源占用低的优势,适合嵌入式或老旧服务器环境,复杂任务可结合Python实现混合编程。
|
机器学习/深度学习 设计模式 测试技术
Python 高级编程与实战:构建自动化测试框架
本文深入探讨了Python中的自动化测试框架,包括unittest、pytest和nose2,并通过实战项目帮助读者掌握这些技术。文中详细介绍了各框架的基本用法和示例代码,助力开发者快速验证代码正确性,减少手动测试工作量。学习资源推荐包括Python官方文档及Real Python等网站。

推荐镜像

更多
下一篇
开通oss服务