定向班录播课程长命令及URL整理

本贴是初步的粗略整理出来的成果,难免会有遗漏,如果同学们发现重要命令或者url遗漏,请联系助教进行补充。

Linux与shell三剑客

1、Linux系统与shell环境准备

ls: 列出目录
cd:切换目录
pwd:显示目前的目录
mkdir:创建一个新的目录
rmdir:删除一个空的目录
cp: 复制文件或目录
rm: 移除文件或目录
mv: 移动文件与目录,或修改文件与目录的名称

Shell基础

常见的shell

Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne Again Shell(/bin/bash)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh

运行shell

  • chmod +x ./test.sh #使脚本具有执行权限
    ./test.sh #执行脚本

  • /bin/sh test.sh

Linux常用命令

文件

ls: 列出目录
cd:切换目录
pwd:显示目前的目录
mkdir:创建一个新的目录
rmdir:删除一个空的目录
cp: 复制文件或目录
rm: 移除文件或目录
mv: 移动文件与目录,或修改文件与目录的名称

文件权限

r 读权限read 4
w 写权限write 2
x 操作权限execute 1
chmod 777 test,修改test文件属性

网络

netstat:打印Linux网络系统的状态信息
-t 列出所有tcp
-u 列出所有udp
-l 只显示监听端口
-n 以数字形式显示地址和端口号
-p 显示进程的pid和名字

性能

top:持续监视系统性能
ps:查看进程信息
-aux 显示所有进程,包括用户,分组情况

3、Linux三剑客与管道使用

管道

Linux提供管道符“|”将两个命令隔开,管道符左边命令的输出就会作为管道符右边命令的输入

正则

正则表达式就是记录文本规则的代码

演练环境

举例

找出所有的hi单词 \bhi\b
hi单词后面有lucy单词 \bhi\b.*\blucy\b
以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字 0\d{2}-\d{8}

grep

根据用户指定的模式(pattern)对目标文本进行过滤,显示被模式匹配到的行

选项

-v 显示不被pattern匹配到的行
-i 忽略字符大小写
-n 显示匹配的行号
-c 统计匹配的行数
-o 仅显示匹配到的字符串
-E 使用ERE,相当于egrep

sed

sed是流编辑器,一次处理一行内容

sed [-hn…][-e][-f<script文件>][文本文件]
-h 显示帮助。
-n 仅显示script处理后的结果。

sed [-hnV][-e][-f<script文件>][文本文件]
-e 以选项中指定的script来处理输入的文本文件。
-f<script文件> 以选项中指定的script文件来处理输入的文本文件。

a :新增 sed -e ‘4 a newline’
c :取代 sed -e ‘2,5c No 2-5 number’
d :删除 sed -e '2,5d’
i :插入 sed -e ‘2i newline’
p :打印 sed -n ‘/root/p’
s :取代 sed -e 's/old/new/g’

awk

把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行后续处理

awk ‘pattern + action’ [filenames]
-pattern 正则表达式
-action 对匹配到的内容执行的命令(默认为输出每行内容)

FILENAME awk浏览的文件名
BEGIN 处理文本之前要执行的操作
END 处理文本之后要执行的操作
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数(列数)
NR 已读的记录数(行数

OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
$0 整条记录
$1 表示当前行的第一个域…以此类推

Bash编程语法

变量

命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
中间不能有空格,可以使用下划线(_)
不能使用标点符号
不能使用bash里的关键字(可用help命令查看保留关键字)

变量类型

字符串:your_name=“hogwarts”
拼接字符串:greeting=“hello, “$your_name” !”
数组 array_name=(value0 value1 value2 value3)
取数组 valuen=${array_name[n]}
单独赋值 array_name[0]=value0

控制语句

if

比较两个变量的大小并输出不同的值
i f [ $a -eq $b ]; then echo “equal”; elif [ $a -lt $b ];then echo “small”; elif [ $a -gt $b ];then echo “big”;fi

for

循环读取文件内容并输出
for i in $(cat dir.txt);do echo $i;done

while

循环读取文件内容并输出
while read line;do echo $line;done<dir.txt

Bash脚本编写

read

read命令是用于从终端或者文件中读取输入的内部命令
读取整行输入
每行末尾的换行符不被读入

使用

从标准输入读取输入并赋值给变量
read var
从标准输入读取多个内容
read var1 var2 var3
不指定变量(默认赋值给REPLY)
read

脚本传参

$0 脚本名称
$1~$n 获取参数
$# 传递到脚本的参数个数
$$ 脚本运行的当前进程ID号
$* 以一个单字符串显示所有向脚本传递的参数
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误

算数运算

a=10  b=20
+	加法	`expr $a + $b` 结果为 30
-		减法	`expr $a - $b` 结果为 -10
*	乘法	`expr $a \* $b` 结果为  200
/	     除法	`expr $b / $a` 结果为 2
a=10  b=20
%	取余	`expr $a % $b` 结果为 10
=	赋值	a=$b 将把变量 b 的值赋给 a
==	相等  相同则返回 true:[ $a == $b ] 返回 false
!=	不相等 不相同则返回 true:[ $a != $b ] 返回 true

-eq	检测相等 [ $a -eq $b ] 返回 false
-ne	检测不相等 [ $a -ne $b ] 返回 true
-gt		检测左边是否大于右边	[ $a -gt $b ] 返回 false
-lt		检测左边是否小于右边  [ $a -lt $b ] 返回 true
-ge	检测左边是否大于等于右边 [ $a -ge $b ] 返回 false
-le		检测左边是否小于等于右边  [ $a -le $b ] 返回 true

数据库

sql

SQL下载地址

https://dev.mysql.com/downloads/mysql/

工作库下载地址

内连接查询 inner join

select * from a_table a inner join b_table b on a.a_id = b.b_id

左连接查询 left join

SELECT  * FROM a_table a left join b_table b ON a.a_id = b.b_id

右连接 right join

SELECT  * FROM a_table a right outer join b_table b on a.a_id = b.b_id

redis

redis下载地址

https://github.com/microsoftarchive/redis/releases

java使用redis引入依赖

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.1.0</version>
        </dependency>

Java使用Redis-创建Jedis实例

//连接本地的 Redis 服务
        Jedis jedis = new Jedis("localhost");
        jedis.auth("hogwarts");//此处为你设置的密码
        System.out.println("连接成功");
        //查看服务是否运行
        System.out.println("服务正在运行: "+jedis.ping());

Selenium

官方网站

driver

driver介绍

https://www.selenium.dev/documentation/en/webdriver/driver_requirements/

driver下载

淘宝镜像:CNPM Binaries Mirror

官方网站:https://chromedriver.storage.googleapis.com/index.html

driver安装

找到和自己浏览器版本适配的driver版本 ChromeDriver - WebDriver for Chrome - Version Selection

SeleniumIDE

IDE下载

Chrome插件:
https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd

Firefox插件:

代码导出与常见问题

代码导出:

常见问题:

web控件交互进阶

Actions

官方文档:Generated Documentation (Untitled)

用法

具体写法:

链式写法
Actions actions=new Actions(driver).moveToElement(ele).click().perform(ele);
分布写法
Actions actions =new  Actions(driver);
actions.move_to_element(element)
actions.click(element)
actions.perform()

拖拽练习网址

http://sahitest.com/demo/dragDropMooTools.htm

按键练习网址

http://sahitest.com/demo/label.htm

多窗口处理

https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable

代码

@Test
public void frameTest() {
    try {
        driver.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable");
        driver.switchTo().frame("iframeResult");
        System.out.println(driver.findElement(By.id("draggable")).getText());
        driver.switchTo().parentFrame();
        driver.switchTo().parentFrame();

        driver.findElement(By.id("submitBTN")).click();
        System.out.println(driver.findElement(By.id("submitBTN")).getText());
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

多浏览器支持

代码

public static WebDriver driver;

@BeforeAll
public static  void initData(){
    String browserName= System.getenv("browser");
    if(browserName.equals("chrome")){
        System.setProperty("webdriver.chrome.driver","/Users/naruto0728/Downloads/chromedriver");
        driver=new ChromeDriver();
    }else if(browserName.equals("firefox")){
        System.setProperty("webdriver.gecko.driver","/Users/naruto0728/Downloads/geckodriver");
        driver = new FirefoxDriver();
    }
}

@Test
public void fun(){

    driver.get("https://home.testing-studio.com");
}

@AfterAll
public static void tearDown(){
    driver.quit();

执行js脚本

例如js代码:

window.alert(‘Selenium弹框测试')   
a = document.getElementById(‘kw’).value
document.title

selenium如何调用js,selenium提供了一个内置 的方法execute_script()

driver.execute_script("window.alert('Selenium弹框测试')")
driver.execute_script("a = document.getElementById(‘kw’).value;window.alert(a)”)

如何返回呢?

driver.execute_script("return document.getElementById('kw').value")

文件上传与弹框处理

文件上传

driver.findElement(By.xpath(“xxx”)).sendKeys(“路径”)

弹框处理

网址:
https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable

代码

@Test
public void fun() {
    try {
        driver.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable");
        Actions actions = new Actions(driver);
        driver.switchTo().frame("iframeResult");

        actions.dragAndDrop(driver.findElement(By.id("draggable")),
                            driver.findElement(By.id("droppable"))).perform();

        driver.switchTo().alert().accept();

        driver.switchTo().parentFrame();

        driver.findElement(By.id("submitBTN")).click();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

PO设计模式

PO设计模式历史

2013 Martin Flower PageObject

2015 Selenium https://github.com/SeleniumHQ/ selenium/wiki/PageObjects

2020 /documentation/test_practices/encouraged/page_object_models/

Appium

官网:http://appium.io/

github地址:https://github.com/appium

appium环境安装

JDK

JDK1.8下载地址
http://www.oracle.com/technetwork/java/javase/downloads/index.html

安装(一直点下一步-〉完成,用默认的路径即可)
配置环境变量(windows)
JAVA_HOME D:\Android\Java\jdk1.8.0_25 (注意这里面的JAVA_HOME大写后面会用到)

classpath .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;(最前面加个点和分号 .;)

path %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
检查JAVA环境是否配置好
进入命令行,输入java -version 或javac -version,输出版本号信息即成功。

安装SDK

下载sdk

Android studio地址
https://developer.android.com/studio/index.html
中文官网下载地址:http://tools.android-studio.org/index.php/sdk
安装sdk

其实sdk就是个文件夹,下载之后需要手动更新, 配上环境变量就可以使用,不需要手动安装
配置android SDK环境变量,如下:

ANDROID_HOME D:\adt-bundle-mac-x86_64-20140702\sdk
PATH %ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools

检查是否安装成功,cmd输出
adb回车或者adb shell 然后回车

appium环境安装

安装appium desktop (appium server + appium inspector工具)

下载对应操作系统的安装包:https://github.com/appium/appium-desktop/releases

如果不需要appium inspector ,也可以通过 npm直接安装appium

官方安装(不推荐)

npm install -g appium

淘宝提供(推荐)

npm install -g cnpm --registry=https://registry.npm.taobao.org 
cnpm install -g appium

运行
appium (不报错说明安装成功)

安装appium python client
方式一:Pip install appium-python-client(推荐)

方式二:下载源码包:

下载地址:https://github.com/appium/python-client
https://pypi.python.org/pypi/Appium-Python-Client

解压后在命令行中进入python-client-master目录,该目录下包含setup.py文件

执行命令python setup.py install命令安装客户端

安装appium doctor

cnpm install appium-doctor

运行测试用例

from appium import webdriver
desired_caps={}
desired_caps['platformName']='Android'
desired_caps['platformVersion']='6.0'
desired_caps['deviceName']='emulator-5554'
desired_caps['appPackage']='com.android.settings'
desired_caps['appActivity']='com.android.settings.Settings'
driver=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps)
driver.quit()

appium元素定位与隐式等待

Capability设置

appActivity Activity名字

adb logcat | grep ActivityManager
adb shell dumpsys activity activities | grep mFocusedActivity
aapt dumpsys badging com.android.chrome.apk |grep 'launchable-activity'

官方文档:

https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

app控件定位

定位方式:

id定位
driver.findElement(By.id("xxx"))(resource-id属性值)

accessibility_id定位
driver.findElement(MobileBy.AccessibilityId("xxx"));(content-desc属性值)
xpath定位

driver.findElement(By.xpath("xxx"))(xpath 属性值)

classname定位(不推荐)

Free Online XPath Tester / Evaluator - FreeFormatter.com #ad-output格式化xml

app控件交互

get_attribute()方法能获取的属性,元素的属性几乎都能获取到,属性名称和 uiautomatorviewer 里面的一致

源码地址:https://github.com/appium/appium-uiautomator2-server/blob/master/app/src/main/java/io/appium/uiautomator2/handler/GetElementAttribute.java

高级定位技巧

Xpath定位

https://www.w3school.com.cn/xpath/xpath_syntax.asp

实例演示

public void priceTest() {
    //定位首页搜索框
    driver.findElement(By.id("com.xueqiu.android:id/home_search")).click();

    //定位搜索页搜索框
    driver.findElement(By.id("com.xueqiu.android:id/search_input_text")).sendKeys("阿里巴巴");

    //
    driver.findElement(By.xpath("//*[@text='BABA']")).click();

    driver.findElement(By.xpath("//*[@resource-id='com.xueqiu.android:id/title_text'][@text='股票']")).click();

    System.out.println(
            driver.findElement(By.xpath("//*[@text='09988']/../../..//*[@resource-id='com.xueqiu.android:id/current_price']")).getText()
    );
}

uiautomator定位

https://developer.android.com/reference/android/support/test/uiautomator/UiSelector.html

表达式

((AndroidDriver<MobileElement>)driver).findElementByAndroidUIAutomator(表达式).click()

组合定位

id与text属性组合
String id_text = 'resourceId("com.xueqiu.android:id/tab_name").text("交易")'
driver.findElementByAndroidUIAutomator(id_text).click()


class与text属性组合
String class_text = 'className("android.widget.TextView").text("行情")'
driver.findElementByAndroidUIAutomator(class_text).click()

父子关系定位  childSelector
son = 'resourceId("com.xueqiu.android:id/scroll_view").childSelector(text("热门"))'

兄弟定位 fromParent
brother = 'resourceId("com.xueqiu.android:id/tab_name").fromParent(text("我的"))'

实现滚动查找元素
'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("查找的文本").instance(0));'

appium显式等待机制

wait等待方式

全局隐式等待
在服务端等待
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

显式等待
在客户端等待
new WebDriverWait(driver).until(ExpectedConditions.visibilityOfElementLocated(By.xpath(“"))).action;

WebDriverWait用法

WebDriverWait 用法

wait=new WebDriverWait(driver, 10, 1000);
driver:浏览器驱动
timeOutInSeconds:最长超时时间,默认以秒为单位
sleepInMillis:检测的间隔步长,默认为0.5s

WebDriverWait 的 until()

wait.until(ExpectedConditions.visibilityOf(home_search)).click();

ExpectedConditions类

presenceOfElementLocated 判断元素是否被加到了DOM里,并不代表该元素一定见
用法:

wait.until(ExpectedConditions.presenceOfElementLocated(By.id("home_search")));

visibilityOfElementLocated 判断某个元素是否可见,可见代表元素非隐藏,并且元素的宽和高都不等于0
用法

wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(“home_search”));

显式等待案例

public void fun3(){
    wait=new WebDriverWait(driver, 10, 1000);
    driver.findElement(By.id("home_search")).click();
    driver.findElement(By.id("search_input_text")).sendKeys("阿里巴巴");
    wait=new WebDriverWait(driver, 10, 2);

    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@text='BABA']"))).click();
}

触屏操作自动化

TouchAction 用法

https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/touch-actions.md

滑动

通过坐标滑动
touchAction.longPress(PointOption.point(200,600)).moveTo(PointOption.point(500,1200)).release().perform();
driver.manage().window().getSize().height
driver.manage().window().getSize().width

toast控件识别

案例

public void toastTest() throws Exception {
    DesiredCapabilities caps = new DesiredCapabilities();

    caps.setCapability("platformName", "Android");
    caps.setCapability("udid", "emulator-5554");
    caps.setCapability("deviceName", "xxxx");
    caps.setCapability("appPackage", "io.appium.android.apis");
    caps.setCapability("appActivity", "io.appium.android.apis.view.PopupMenu1");
    caps.setCapability("noReset", "true");
    driver = new AndroidDriver<>(new URL("http://localhost:4723/wd/hub"), caps);
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    driver.findElement(MobileBy.AccessibilityId("Make a Popup!")).click();
    driver.findElement(By.xpath("//*[@text='Search']")).click();
    System.out.println(driver.getPageSource());
    System.out.println(driver.findElement(By.xpath("//*[@class='android.widget.Toast']")).getText());
}

appium属性获取与断言

Get_attribute原理分析

官方文档:
http://appium.io/docs/en/commands/element/attributes/attribute/

hamrest断言

官网:http://hamcrest.org/JavaHamcrest/

使用方法:

断言案例

public void priceTest() {
    //定位首页搜索框
    driver.findElement(By.id("com.xueqiu.android:id/home_search")).click();

    //定位搜索页搜索框
    driver.findElement(By.id("com.xueqiu.android:id/search_input_text")).sendKeys("阿里巴巴");

    driver.findElement(By.xpath("//*[@text='BABA']")).click();

    driver.findElement(By.xpath("//*[@resource-id='com.xueqiu.android:id/title_text'][@text='股票']")).click();

    assertThat(Double.parseDouble(driver.findElement(
                By.xpath("//*[@text='09988']/../../..//*[@resource-id='com.xueqiu.android:id/current_price']")).getText())
                ,greaterThan(500d));
}

参数化案例

@ParameterizedTest
@MethodSource("byNameGetPrice")
public void comparePriceTest(String name,String code, double price) {
    driver.findElement(By.id("com.xueqiu.android:id/home_search")).click();

    //定位搜索页搜索框
    driver.findElement(By.id("com.xueqiu.android:id/search_input_text")).sendKeys(name);

    driver.findElement(By.xpath("//*[@text='"+code+"']")).click();

    String stockPrice = driver.findElement(By.xpath("//*[@text='" + code + "']/../../..//*[@resource-id='com.xueqiu.android:id/current_price']")).getText();

    System.out.println(stockPrice);

    driver.findElement(By.id("com.xueqiu.android:id/action_close")).click();

   assertThat("股票的实际和预期价格对比",Double.parseDouble(stockPrice),greaterThan(price));
}

private static Stream<Arguments> byNameGetPrice() {
    return Stream.of(
            Arguments.of("alibaba", "BABA",210d),
            Arguments.of("wangyi","NTES", 200d),
            Arguments.of("baidu","BIDU", 185d),
            Arguments.of("google","GOOGL", 300d)
    );
}

Android 纯web页面测试

环境准备

手机端

被测浏览器:(不可以是第三方浏览器) ’Safari’ for iOS and ‘Chrome’, ‘Chromium’, or ‘Browser’ for Android,
PC端

安装Chrome浏览器(或chromium),并且能登录https://www.google.com/

下载对应手机浏览器对应的driver版本

国内镜像地址:CNPM Binaries Mirror
appium

github:https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md

客户端代码:

desirecapability
“browser” = “Browser” 或者“browser” = ”Chrome”
“chromedriverExecutable” = “指定driver地址”

Mac Chromedriver 默认地址:
/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/

获取webview版本

查看手机浏览器的版本

adb shell pm list package |grep webview
adb shell pm dump com.android.browser|grep version
adb shell pm dump com.android.chrome|grep version
adb shell pm dump com.android.webview|grep version

默认的浏览器启动

des_caps = {
    'platformName': 'android',
    'platformVersion': '6.0',
    'browserName': 'Browser',
    # 'browserName':'Chrome',
    'deviceName':'192.168.56.101:5555',
    # 'noReset': 'true'
}
self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", des_caps)
self.driver.get("http://m.baidu.com")
self.driver.implicitly_wait(5)
time.sleep(3)

appium混合应用

前提条件

PC:
浏览器能访问 https://www.google.com/

chromedriver下载对应的版本

https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/web/chromedriver.md

手机端

应用代码需要打开webview开关

代码

appPackage, appActivity
desirecapability里面添加:chromedriverExecutable:driver路径

webview开关

文档:
https://developers.google.com/web/tools/chrome-devtools/remote-debugging/webviews?hl=zh-cn

定位元素方式

chrome://inspect

appium设备交互

常用的设备交互命令

官方地址:http://appium.io/docs/en/about-appium/intro/

模拟电话、短信

driver.makeGsmCall(PHONE_NUMBER, GsmCallActions.CALL);
driver.makeGsmCall(PHONE_NUMBER, GsmCallActions.ACCEPT);
driver.makeGsmCall(PHONE_NUMBER, GsmCallActions.CANCEL);
driver.sendSMS("555-123-4567", “Appium Test”);

网络设置

driver.toggleAirplaneMode();
driver.toggleWifi();
driver.toggleData();

横竖屏切换

切换成横屏
driver.rotate(Screenorientation.LANDSCAPE)

切换成竖屏
driver.rotate(Screenorientation.PORTRAIT)

其它常用操作

锁屏

driver.lock()

截图

File screenshotAs = driver.getScreenshotAs(OutputType.FILE);
File file=new File(System.getProperty(“user.dir")+"/src/main/resources/demo.png");
FileUtils.copyFile(screenshotAs,file);

录屏 模拟器需要androidAPI>27 ,华为不支持   只支持 8.0以上的版本

driver.startRecordingScreen();
driver.stopRecordingScreen();

设置地理位置 (only emulator)

driver.setLocation();

硬件操作

driver.pressKey(new KeyEvent().withKey(AndroidKey.BACK));
比如,back, home,menu,power, voice up,voice down,

keycode查看地址:
https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_MENU

Capability 高级用法

newCommandTimeout
udid
autoGrantPermissions

测试策略相关
- noReset
- fullreset
- dontStopAppOnReset

性能相关
- skipServerInstallation
 - skipDeviceInitialization
 - skipUnlock
 - skipLogcatCapture
 - systemPort
- relaxed-security    启动的时候设置

Appium 启动命令
Appium  - relaxed-security

客户端测试平台

Android monkey测试工具

使用Monkey

adb shell monkey  100 对所有包随机操作
adb shell monkey -p com.xueqiu.android 100 对指定包
adb shell monkey -p com.xueqiu.android -s 20  80 时间种子
adb shell monkey -p com.xueqiu.android  -vv -s 20  80 详细日志

时间延迟

adb shell monkey -p com.xueqiu.android --throttle 5000 100

事件百分比

adb shell monkey -p com.xueqiu.android --pct-touch 10 1000

常用事件

--pct-touch:触摸事件,比如点击

--pct-motion:动作事件,比如滑动(直线)

--pct-trackball:轨迹事件,比如移动+点击,曲线滑动

--pct-majornav:主要导航事件,比如回退按键、菜单按键:

maxim

使用

https://github.com/zhangzhao4444/Maxim

adb push framework.jar /sdcard

adb push monkey.jar /sdcard

命令

adb shell CLASSPATH=/sdcard/monkey.jar:/sdcard/framework.jar exec app_process /system/bin tv.panda.test.monkey.Monkey -p com.panda.videoliveplatform --uiautomatormix --running-minutes 60 -v -v

AppCrawler

项目地址:https://github.com/seveniruby/AppCrawler

环境要求

appcrawler 2.5

java8 appium 1.8.x

安装方法

  • 直接下载
  • 从源代码编译

备注

后面提到的appcrawler命令或者java -jar appcrawler.jar皆表示用jar -jar命令执行对应版本的jar包文件,比如

java -jar appcrawler-2.4.0-jar-with-dependencies.jar

quick_start

appcrawler --capability
“appPackage=com.xueqiu.android,appActivity=.view.WelcomeActivityAlias”

常用事件

参数模式

  • java -jar <appcrawler.jar路径> --demo
  • appcrawler --capability “appPackage=com.xueqiu.android,appActivity=.view.WelcomeActivityAlias”

配置文件 [推荐方式]

  • java -jar <appcrawler.jar路径> \
  • -c example.yml \
  • –capability “appPackage=com.xueqiu.android,appActivity=.view.WelcomeActivityAlias” \
  • -o /tmp/xueqiu/1

capability设置示例

appPackage: “com.xueqiu.android”

appActivity: “.view.WelcomeActivityAlias”

app: 
appium: “http://127.0.0.1:4723/wd/hub”

noReset: true
automationName: uiautomator2
dontStopAppOnReset: true

OpenSTF

官网地址:https://github.com/openstf/stf

docker安装

docker pull openstf/stf:latest
docker pull sorccu/adb:latest
docker pull rethinkdb:latest

启动rethinkdb

docker run -d --name rethinkdb -v /srv/rethinkdb:/data --net host rethinkdb rethinkdb --bind all --cache-size 8192 --http-port 8090

启动stf

docker run -d --name stf --net host openstf/stf stf local --allow-remote

启动rethinkdb

docker run -d --name rethinkdb -v /srv/rethinkdb:/data --net host rethinkdb rethinkdb --bind all --cache-size 8192 --http-port 8090

localhost:7100

命令行启动

docker run --name=hub -p 5001:4444 -e GRID_TIMEOUT=0 -e GRID_THROW_ON_CAPABILITY_NOT_PRESENT=true -e GRID_NEW_SESSION_WAIT_TIMEOUT=-1 -e GRID_BROWSER_TIMEOUT=15000 -e GRID_TIMEOUT=30000 -e GRID_CLEAN_UP_CYCLE=30000 -d selenium/hub:3.7.1-beryllium

docker run --name=chrome -p 5902:5900 -e NODE_MAX_INSTANCES=6 -e NODE_MAX_SESSION=6 -e NODE_REGISTER_CYCLE=5000 -e DBUS_SESSION_BUS_ADDRESS=/dev/null -v /dev/shm:/dev/shm --link hub -d selenium/node-chrome-debug:3.7.1-beryllium

Selenium Grid

官网:https://www.selenium.dev/downloads/

hub

java -jar selenium-server-standalone-3.141.59.jar -role hub

node

java -jar selenium-server-standalone-3.141.59.jar -role node -port 5677

配置文件启动Node

java -jar selenium-server-standalone.jar -role node -nodeConfig node1Config.json

https://www.selenium.dev/documentation/en/grid/setting_up_your_own_grid/

selenium实现

把hub与nodes,放入字典

hub_nodes = {
    "http://127.0.0.1:4444/wd/hub": "chrome",
    "http://127.0.0.1:5677/wd/hub": "firefox",
    "http://127.0.0.1:5678/wd/hub": "internet explore"
}

for host, browser in hub_nodes.items():
    capabilities = {'platform': 'ANY',
                    'browserName': '',
                    'version': '',
                    'javascriptEnable': True
                    }
    driver = Remote(command_executor=host,
    desired_capabilities=capabilities)
    driver.get("https://home.testing-studio.com/")

app自动化测试平台实战 1

动作支持action

“” 只是截图记录

back 后退

backApp 回退到当前的app 默认等价于back行为 可定制

monkey 随机事件

xxx() 执行代码

  • Thread.sleep(3000)
  • driver.swipe(0.9, 0.5, 0.1, 0.5)

click

longTap

非以上所有行为是输入 xx ddd

获取dom结构

windows

adb shell “uiautomator dump && cat /sdcard/window_dump.xml” | clip
adb shell “uiautomator dump && cat /sdcard/window_dump.xml” > tmp.xml

Mac

adb shell "uiautomator dump && cat /sdcard/window_dump.xml" | pbcopy

客户端专项测试

启动性能分析

adb logcat

package=com.xueqiu.android

清理缓存数据:adb shell pm clear $package

停止进程:adb shell am force-stop $package

启动app:adb shell am start  -S -W $package/.view.WelcomeActivityAlias

获取数据:adb logcat |grep -i displayed

startTime:记录刚准备调用startActivityAndWait()的时间点;

endTime:记录startActivityAndWait()函数调用返回的时间点

WaitTime:startActivityAndWait()调用耗时

  • WaitTime = endTime - startTime

使用ffmpeg拆帧

adb shell am force-stop $package
adb shell screenrecord --bugreport --time-limit 30 /data/local/tmp/xueqiu.mp4 &
adb shell am start  -S -W $package/.view.WelcomeActivityAlias
wait
adb pull /data/local/tmp/xueqiu.mp4 .
ffmpeg -i xueqiu.mp4  xueqiu.gif
ffmpeg -i xueqiu.mp4  -r 10 frames_%03d.jpg

H5性能分析

https://www.w3.org/TR/navigation-timing/

自动化获取性能指标

appium/selenium的ExecuteScript Api

注⼊js

return JSON.stringify(window.performance.timing) 

JSON.stringify(window.performance.getEntriesByName (document.querySelector("img").src)[0], null, 2)

卡顿分析

systrace

sdk/platform-tools/systrace

帧分析:

adb -s devicesname shell dumpsys gfxinfo | less

系统资源分析

参考阅读:https://developer.android.com/topic/performance/rendering/inspect-gpu-rendering

耗电量测试

安装:

git clone https://github.com/google/battery-historian.git
cd battery-historian
go get -d -u github.com/google/battery-historian/...
go run setup.go
go run cmd/battery-historian/battery-historian.go

batterystats收集数据

1. 清理耗电量数据
adb shell dumpsys batterystats --reset
adb shell dumpsys batterystats --enable full-wake-history
2. 运行测试用例/手工操作
3. 收集数据
Android 7.0:adb bugreport bugreport.zip
Android6.0:adb bugreport > bugreport.txt

上传数据

打开localhost:9999,把zip或者txt数据上传

使用脚本

start=$(date +%s); 
while true; do 
cur=$(date +%s); 
((cur-start>6)) && break; 
adb shell input swipe 100 800 100 300; 
sleep 1;
echo $((cur-start)); 
done

弱网测试

使用charles模拟弱网

服务端性能测试

jmeter安装

jmeter分布式

influxDB

InfluxDB 是一个用 Go 语言开发的开源分布式时序数据库。
新建容器网络:docker network create grafana
运行容器:docker run -d --name=influxdb --network grafana -p 8086:8086 -v ${PWD}/influxdb/:/var/lib/influxdb/ influxdb:1.7.10
创建数据库
第一种方式:curl -i -XPOST http://localhost:8086/query --data-urlencode “q=CREATE DATABASE jmeter”
第二种方式:docker exec -it influxdb influx,执行语句 create database jmeter;
简单使用
show databases;
use jmeter;
show measurements;
select * from jmeter limit 3;

性能监控体系

部署Prometheus
配置文件:https://github.com/prometheus/prometheus/blob/master/documentation/examples/prometheus.yml
运行:docker run -d --name prometheus --network grafana -p 9090:9090 -v ${PWD}/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus:v2.16.0 --config.file=/etc/prometheus/prometheus.yml

部署node_exporter

下载地址: https://github.com/prometheus/node_exporter/releases

配置Grafana

配置 Prometheus 数据源
配置面板:https://grafana.com/grafana/dashboards/8919

Docker容器技术

docker file

常用指令

FROM:基础镜像,FROM 命令必须是 Dockerfile 的首个命令。
LABEL:为镜像生成元数据标签信息。
USER:指定运行容器时的用户名或 UID,后续 RUN 也会使用指定用户。
RUN:RUN 命令是 Dockerfile 执行命令的核心部分。它接受命令作为参数并用于创建镜像。每条 RUN 命令在当前基础镜像上执行,并且会提交一个新镜像层。
WORKDIR:设置 CMD 指明的命令的运行目录。为后续的 RUN、CMD、ENTRYPOINT、ADD 指令配置工作目录。
ENV:容器启动的环境变量。
ARG:构建环境的环境变量。
COPY:复制文件
CMD:容器运行时执行的默认命令。
ENTRYPOINT:指定容器的“入口”。
HEALTHCHECK:容器健康状态检查。

Jenkins持续集成

节点管理

Jenkins的任务可以分布在不同的节点上运行

节点上需要配置Java运行时环境 ,Java_Version > 1.5

节点支持 Windows, Linux, Mac

Jenkins运行的主机在逻辑上是 master 节点

Jenkins报警机制

Jenkins 模板配置

  • $BUILD_STATUS – 构建结果
  • $PROJECT_NAME – 构建脚本名称
  • $BUILD_NUMBER – 构建脚本编号
  • $JOB_DESCRIPTION – 构建项目描述
  • $CAUSE – 脚本启动原因
  • $BUILD_URL – 脚本构建详情URL地址

持续交付

Jenkins API 接口

远程调用Jenkins API启动任务

远程API服务地址:

http://106.53.223.46:8080/job/first_job/build

远程调用Jenkins API返回最新任务编号

远程API服务地址:

http://106.53.223.46:8080/job/first_job/lastBuild/buildNumber

远程调用Jenkins API查询任务状态

远程API服务地址:

http://106.53.223.46:8080/job/first_job//api/json

Jenkins file语法简介

Declarative pipeline 示例代码

stages{
stage('git pull souce code'){
		steps{
				echo "sync updated code"
				git "https://github.com/princeqjzh/iPipeline.git"
		}
}
}

 post {
        success {
            echo 'goodbye pipeline success!'
            sleep 2
        }
        always {
            echo 'always say goodbye'
        }
    }
options {
        timeout(time: 30, unit: 'SECONDS')
			  buildDiscarder(logRotator(numToKeepStr: '2'))
        retry(5)
    }
parameters {
        string(name: 'PERSON', defaultValue: 'Jenkins', description: '输入的文本参数')
    }
    stages {
        stage('Test Parameters'){
            steps {
                echo "Hello ${params.PERSON}"
            }
        }
    }
流程控制之 – if/else
node {
    stage('Example') {
        if (env.BRANCH_NAME == 'master') {
            echo 'I only execute on the master branch'
        } else {
            echo 'I execute elsewhere'
        }
    }
}
流程控制之 – try/catch
    node{
        echo "This is test stage which run on the slave agent."
        try {
            echo "This is in the try block."
        }catch (exc) {
            echo "Something failed, I'm in the catch block."
        }finally {
            echo "Finally, I'm in the finally block."
        }
    }

例子源码地址:
https://gitee.com/ytq12875/pipeline

测试平台开发

测试平台前端

vue.js 安装

  1. CDN
    image

  2. NPM
    通过webpack和CLI安装使用

安装node.js环境

https://nodejs.org/zh-cn/download/

组件库的使用

ElementUI
https://element.eleme.io/#/
BootstrapVue
https://bootstrap-vue.org/
Vuetify
https://vuetifyjs.com/zh-Hans/

axios

官方网址:http://www.axios-js.com/

安装

$ npm install axios

VSCode插件

Vetur:VSCode支持VUE的工具,有语法高亮、格式化、错误检查、自动完成等功能。

JavaScript (ES6) code snippets:包含VSCode的ES6语法中的JavaScript代码段。

(推荐)Auto Close Tag:自动添加HTML/XML结束标签。
(推荐)Auto Rename Tag:自动重命名对应的HTML/XML标签。

Highlight Matching Tag:突出显示匹配的开始和结束标签。

测试平台后端

Jenkins调用

Jenkins调用-maven依赖

<dependency>
            <groupId>com.offbytwo.jenkins</groupId>
            <artifactId>jenkins-client</artifactId>
            <version>0.3.8</version>
 </dependency>

常用类-JenkinsHttpClient

  • 封装了调用JenkinsAPI的底层方法。
  • JenkinsHttpClient(URI uri, String username, String password)
  • get(String path)
  • getFile(URI path)
  • post(String path, boolean crumbFlag)
  • post(String path, D data, Class cls)
  • post_xml(String path, String xml_data, boolean crumbFlag)
    等等

常用类-JenkinsServer

  • 封装了调用JenkinsAPI的语义级别的方法。
  • JenkinsServer(JenkinsHttpConnection client)
  • getJob(String jobName)
  • createJob(String jobName, String jobXml, Boolean crumbFlag)
  • updateJob(String jobName, String jobXml, boolean crumbFlag)
  • getJobXml(String jobName)
  • deleteJob(FolderJob folder, String jobName, boolean crumbFlag)
    等等

常用类-Job

  • Jenkins中job对应的实体类,有很多实用的语义级别的方法。
  • Job(String name, String url)
  • build(Job job)
  • build(Job job, Map<String, String> params)
  • getFileFromWorkspace(String fileName)
  • setClient(JenkinsHttpConnection client)

springboot

  1. 进入 https://start.spring.io/

  2. 使用IDE的插件进行快速创建

restful风格的接口实现方式

  1. SpringBootApplication:springboot主类,用来加载springboot各种特性

  2. RestController:Spring会转换返回值并自动将其写入HTTP响应

  3. RequestMapping: 用于类和方法,在方法级别时,用于处理HTTP 的各种方法

  4. RequestBody:将request body中的json/xml对象解析成该参数类型的Javabean对象

  5. PathVariable:处理动态的 URI,URI 的值可以作为控制器中处理方法的参数

  6. Post/Put/Get/DeleteMapping:在方法的级别上使用,在方法级别时,用于处理HTTP 的各种方法

  7. RequestParam:处理get请求的参数

lombok使用

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
 </dependency>

集成swagger-配置类

@Configuration
@EnableSwagger2
public class SwaggerConfig {

}

集成swagger-配置项

@Bean
public Docket docket() {
 		//header
		//apiInfo
}

private ApiInfo apiInfo() {
}

常用配置介绍

server:
  port: 8093
  connection-timeout: 18000000
  servlet
     session:
      timeout: 30m #30分钟,测试的话时间不能太短,否则不准。m(分钟),s(秒),h(小时),不写单位默认毫秒
spring:
  application:
    name: aitest

springboot多环境配置

<profiles>
        <!--开发环境-->
        <profile>
            <id>dev</id>
            <properties>
                <spring.profiles.active>dev</spring.profiles.active>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
</profiles>

简单运行脚本

test_start_8097.sh
nohup java -Xms256m -Xmx512m -XX:PermSize=64m -XX:MaxPermSize=128m  -server -Dserver.port=8012 -jar aitest-mini.jar 'aitest-mini' --spring.profiles.active=dev  >>./test_info_8097.log 2>&1 &
  • ps -ef | grep aitest-mini #查询已经存在的aitest-mini进程,进程号为10179
  • kill -9 10179 # 停止该进程
  • sh test_start_8099.sh #执行启动命令
  • tail -f test_info_8099.log #实时查看服务输出日志

Cors跨域资源共享
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

数据持久化技术

mybatis配置

  • springboot集成mybatis配置
  • mybatis相关配置
  • sql语句打印配置

@MapperScan(“com.hogwartstest.aitestmini.dao”)

tk.mybatis使用-mapper统一父类

mybatis的mapper的统一父类,用于简单sql语句的快速编码

public interface MySqlExtensionMapper<T> extends Mapper<T>, MySqlMapper<T>, IdsMapper<T> {
}

持久化常见注解

  • Table:表对应的实体类标识,name属性为表名

  • Id:主键标识

  • GeneratedValue(strategy = GenerationType.IDENTITY):配置主键为自增策略

  • Column:列名标识,当类属性与表字段不符时,用name属性标识表字段

  • Transient:标识此字段不进行持久化

mybatis常见特性

  • #{createUserId}

  • ${createUserId}

  • concat(‘%’, #{params.caseSign}, ‘%’):MySQL函数,返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。