Appium 第八期_Android 自动化测试_20190224

思寒_seveniruby for 霍格沃兹测试学院外部交流圈 · February 24, 2019 · Last by welephant replied at March 03, 2019 · 3854 hits

参考资料

环境准备

  • 推荐 真机
  • genymotion模拟器
  • 推荐 Android Studio自带的模拟器avd manager
  • bluestacks

Appium Server的安装

全局安装

#查询最近更新版本
npm view appium versions --json

#全局安装
#默认安装最新的正式版本,不过需要***,你们多数人估计安装会很困难
npm install -g appium
#使用淘宝提供的cnpm工具安装
cnpm install -g appium

同时安装多个版本的appium

mkdir 1.11 && cd 1.11
cnpm install appium@1.11
cd ..

#同时安装1.10
mkdir 1.10 && cd 1.10
cnpm install appium@1.10
cd ..

#启动appium 1.11版本
./1.11/node_modules/appium/build/lib/main.js
#启动appium 1.10版本
./1.10/node_modules/appium/build/lib/main.js

appium安装常见问题

  • python2依赖,不能缺少python2,appium的安装脚本中有部分代码依赖python2
  • 权限问题,没权限写目录 可执行sudo chown -R $USER /usr/local/lib/node_modules/,如果还不行就执行sudo chown -R $USER:staff /usr/local/lib/node_modules/ staff需要是你的普通权限的用户组
  • windows 资源忙或者被锁 把安装目录排除到杀毒软件外面
  • 更新npm版本到最近的6.x版本

启动时权限弹框问题

caps["autoGrantPermissions"] = "true"

隐式等待解决启动时等待

driver.implicitly_wait(10)

pytest的IDE支持

随时可能出现的弹框

通过异常处理+黑名单列表处理

动态加载内容

  • 隐式等待
  • 连续定位直到位置不变

高级定位

//*[contains(@resource-id, 'month') and @text='3']/../..//*[contains(@resource-id, 'day') and @text='10']

appium的log与启动流程剖析

appium -g appium.log

appium的启动流程剖析

  • adb devices
  • 判断待测系统
  • 安装settings.apk unclock
  • 推送Uiautomator到手机并启动
  • 启动app
  • http请求 element elements click value

capability设置

参考资料 https://appium.io/docs/en/writing-running-appium/caps/

  • app 要不要安装
  • noReset 不要pm clear
  • unicodeKeyboard 中文输入
  • autoGrantPermissions 自动给予权限

通用命令

命令:https://appium.io/docs/en/commands/session/create/

mobile命令

def test_battery(self):
print(self.driver.execute_script("mobile:batteryInfo"))

def test_shell(self):
print(self.driver.execute_script("mobile:shell",
{"command": "am",
"args": ["start", "-n", "com.android.calculator2/.Calculator"]}))

手势

  • longPress
  • swipe
def test_main_swipe(self):
self.loaded()
for i in range(1, 10):
sleep(1)
self.driver.swipe(start_x=1340, start_y=2000, end_x=200, end_y=600, duration=1000)


演练作业

作业1

  • 进去自选,点击搜索,搜索alibaba,点击添加。然后回到自选,判断阿里巴巴已经在自选中, 把测试用例代码贴到回复里。测试用例的名字 test_search_add

作业2

  • 进去自选,点击搜索,搜索“阿里巴巴”,点击添加,判断添加按钮自动变化状态 test_alibaba_search
  • 进入自选,判断阿里巴巴存在,不要使用xpath定位判断阿里巴巴股票存在 test_alibaba_exist

作业3

  • 添加一只美股,判断是否添加成功 test_add_us
  • 然后删除一只美股,判断删除成功 test_delete_us
  • 利用参数化或者数据驱动添加30只股票 test_add_batch
  • 添加10只美股,当全部股票大于2页的时候断言某个股票同时存在于“美股”与“全部”分类中 test_exist_in_all

作业4 (课后作业)

  • 提取所有adb相关的命令,给出每个命令的作用,回帖
  • 提取所有的http协议,给出说明, get post的请求与json请求体提取出来,做出说明

答案

echo "# $$ "$(date "+%Y/%m/%d %H:%M:%S") >> /tmp/adb.log
echo "# ppid: $(ps -o command $(ps -o ppid $$ | tail -1) | tail -1)" >> /tmp/adb.log
echo "adb $@" >> /tmp/adb.log
exec /Users/seveniruby/Library/Android/sdk//platform-tools/adb.bak "$@"
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 55 条回复 时间 点赞

cnpm install appium@1.10不用写安装路径吗,我要安装到别的路径呢,这个改怎么写

2Floor has been deleted

定位元素经常定位不到,报这个错

郭有权 回复

目前安装在你的执行命令的目录下,在那个目录里执行 node ./node_modules/appium/build/lib/main.js
也可以全局安装,全局安装用-g参数,这种安装可以直接使用appium命令

郭有权 回复

确认appium session结束,或者appium关闭,使用6.0的模拟器。或者你提供下具体的手机型号和版本

Genymotion 启动device时报错:

作业,加载问题还没讲不知道怎么用


#!/usr/bin/env python
# -*- Coding:utf-8 -*-
from appium import webdriver
import pytest

class TestXueQiu:

@pytest.fixture(scope="function", autouse=True) # 如果scope设置为class,则需要return driver 并将base作为参数传入后续用例调用
def base(self):
self.driver = webdriver.Remote("http://localhost:4723/wd/hub",
{"platformName":"android",
"deviceName":"demo",
"appPackage":"com.xueqiu.android",
"appActivity":".view.WelcomeActivityAlias",
"unicodeKeyboard":True,
"resetKeyboard":True,
"autoGrantPermissions":True
})
self.driver.implicitly_wait(6)
try:
self.driver.find_element_by_id("btn_allow").click()
except:
pass

try:
self.driver.find_element_by_id("btn_allow").click()
except:
pass


yield
self.driver.quit()


def test_search_add(self):
self.driver.find_element_by_xpath \
("//*[@text='自选' and contains(@resource-id,'tab_name')]").click() # 点击自选按钮
self.driver.find_element_by_id("action_create_cube").click() # 点击搜索按钮
self.driver.find_element_by_id("search_input_text").send_keys("阿里巴巴") # 输入阿里巴巴进行搜索
try:
self.driver.find_element_by_xpath \
("//*[contains(@resource-id,'follow_btn') and @instance=9]").click() # 检测并添加第一个股票到自选
except:
print("搜索的股票已经在自选股之中")
pass
try:
self.driver.find_element_by_xpath("//*[@text='下次再说']").click() # 检测是否有评价弹窗,有则点击下次再说
except:
pass
self.driver.find_element_by_id("action_close").click() # 点击取消按钮
try:
self.driver.find_element_by_id("iv_close").click()
except:
pass
assert self.driver.find_element_by_xpath\
("//*[contains(@resource-id,'portfolio_stockName') and @text='阿里巴巴']") # 验证阿里巴巴是否添加到自选中

不使用appium desktop 只用uiautomationviewer如何判断一个控件的resource-id是否在当前页面只有一个

真机锁屏状态下,运行报错, 这个有好的解决办法吗? 不锁屏运行正常.
appium日志:

[debug] [AndroidBootstrap] Received command result from bootstrap
[debug] [MJSONWP] Matched JSONWP error code 7 to NoSuchElementError
[debug] [W3C (42388801)] Encountered internal error running command: NoSuchElementError: An element could not be located on the page using the given search parameters.
[debug] [W3C (42388801)] at AndroidDriver.helpers.findElOrEls (C:\Users\21422\AppData\Roaming\npm\node_modules\appium\node_modules\appium-android-driver\lib\commands\find.js:75:11)
[HTTP] <-- POST /wd/hub/session/42388801-31f7-4425-a592-29b18c449608/element 404 5072 ms - 415

作业1

def test_search_add(self):
sleep(5)
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys("alibaba")
if len(self.driver.find_elements_by_id("follow_btn")) > 0:
self.driver.find_element_by_id("follow_btn").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_id("action_close").click()
self.driver.find_element_by_id("iv_close").click()
assert 1 == len(self.driver.find_elements_by_xpath(
"//*[contains(@resource-id, 'portfolio_stockName') and @text='阿里巴巴']"))

守护 回复

一般相同的id,都在相同的父窗体下,只要简单看下兄弟节点下有没有重复即可

mac :

virtualBox:

genymotion:


# 作业1 进去自选,点击搜索,搜索alibaba,点击添加。然后回到自选,判断阿里巴巴已经在自选中,
# 把测试用例代码贴到回复里。测试用例的名字 test_search_add
def test_search_add(self):

self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()

self.driver.find_element_by_id('action_create_cube').click()
self.driver.find_element_by_id('search_input_text').send_keys('alibaba')

self.driver.find_element_by_id('follow_btn').click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_id('action_close').click()

assert 1==len(self.driver.find_elements_by_xpath("//*[@text='阿里巴巴']"))
self.driver.quit()
15Floor has been deleted

作业2

def test_alibaba_search(self):
self.driver.find_element_by_xpath \
("//*[@text='自选' and contains(@resource-id,'tab_name')]").click() # 点击自选按钮
self.driver.find_element_by_id("action_create_cube").click() # 点击搜索按钮
self.driver.find_element_by_id("search_input_text").send_keys("阿里巴巴") # 输入阿里巴巴进行搜索
before = self.driver.find_element_by_id("add_attention").\
find_element_by_class_name("android.widget.TextView").get_attribute("resourceId")
if before == "com.xueqiu.android:id/follow_btn":
self.driver.find_element_by_id("follow_btn").click()
after = self.driver.find_element_by_id("add_attention").\
find_element_by_class_name("android.widget.TextView").get_attribute("resourceId")
assert before != after # 通过按钮的ID判断状态是否变化

try:
self.driver.find_element_by_xpath("//*[@text='下次再说']").click() # 检测是否有评价弹窗,有则点击下次再说
except:
pass
self.driver.find_element_by_id("action_close").click() # 点击取消按钮,返回自选界面
assert self.driver.find_element_by_id("portfolio_whole_item"). \
find_element_by_id("portfolio_stockName"). \
get_attribute("text") == "阿里巴巴"

作业2

def test_alibaba_search(self):
sleep(5)
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys("阿里巴巴")
self.driver.find_element_by_id("follow_btn").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()

if self.driver.find_elements_by_id("followed_btn"):
print("已添加")

def test_alibaba_exist(self):
sleep(5)
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
if self.driver.find_element_by_class_name("android.widget.LinearLayout").find_element_by_id(
"portfolio_stockName").get_attribute("text") == "阿里巴巴":
print("阿里巴巴存在")

问题:检索股票,输入 “alibaba”,可以检索到,输入“阿里巴巴” 没有内容
'''

#coding=utf-8

import pytest
import unittest
from appium import webdriver

class TestXueqiu(unittest.TestCase):

def setUp(self):
print("setup")
caps = {}
caps["platformName"] = "android"
caps["deviceName"] = "demo"
caps["appPackage"] = "com.xueqiu.android"
caps["appActivity"] = ".view.WelcomeActivityAlias"
caps["autoGrantPermissions"] = "true"

self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
self.driver.implicitly_wait(10)

def test_alibaba_search(self):
self.driver.find_element_by_xpath(
"//[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//
[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_id("action_create_cube").click()
# self.driver.find_element_by_id("search_input_text").send_keys("alibaba")
self.driver.find_element_by_id("search_input_text").send_keys("阿里巴巴")
'''

于静 回复

"unicodeKeyboard":True,
"resetKeyboard":True,
这两个要添加,第二个如果不添加不会恢复原有键盘,第一个设置为了支持中文

守护 回复

哦哦,可以了,谢谢啦

作业二:


import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static java.lang.Thread.sleep;

public class TestSearch {
private static AndroidDriver driver;

@BeforeClass
public static void setUp() throws MalformedURLException{
if (driver==null) {
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability("platformName", "android");
desiredCapabilities.setCapability("deviceName", "demo");
desiredCapabilities.setCapability("appPackage", "com.xueqiu.android");
desiredCapabilities.setCapability("appActivity", ".view.WelcomeActivityAlias");
desiredCapabilities.setCapability("unicodeKeyboard","true");

desiredCapabilities.setCapability("autoGrantPermissions", "true");


URL remoteUrl = new URL("http://localhost:4723/wd/hub");


driver = new AndroidDriver(remoteUrl, desiredCapabilities);

}
driver.manage().timeouts().implicitlyWait(6000, TimeUnit.SECONDS);
}
@Test
public void sampleTest() throws InterruptedException {
driver.findElementById("cancel").click();
sleep(3000);
// driver.findElementByXPath("//*[@text='自选' and contains(@resource-id,'tab_name')]").click();
driver.findElementByXPath("//*[contains(@resource-id,'public_timeline_actionbar')]/android.widget.LinearLayout/android.widget.ImageView").click();
driver.findElementById("search_input_text").sendKeys("阿里巴巴");

driver.findElementByXPath("//*[contains(@resource-id,'stockName') and @text='阿里巴巴']/../..//*[contains(@resource-id,'follow_btn')]").click();
sleep(1000);
driver.navigate().back();
MobileElement element = driver.findElementById("add_attention").findElement(By.className("android.widget.TextView"));
String tagName = element.getAttribute("resourceId");
Assert.assertEquals(tagName,"com.xueqiu.android:id/followed_btn");








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

}

Author only

作业三:

import io.appium.java_client.MobileElement;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.touch.WaitOptions;
import io.appium.java_client.touch.offset.PointOption;
import io.qameta.allure.Feature;
import io.qameta.allure.junit4.DisplayName;
import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.Point;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;

import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static java.lang.Thread.sleep;
@RunWith(Parameterized.class)
public class DemoTest {
private static AndroidDriver driver;
@BeforeClass
public static void setUp()throws MalformedURLException {
if (driver==null) {
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability("platformName", "android");
desiredCapabilities.setCapability("deviceName", "demo");
desiredCapabilities.setCapability("appPackage", "com.xueqiu.android");
desiredCapabilities.setCapability("appActivity", ".view.WelcomeActivityAlias");
desiredCapabilities.setCapability("noReset","true");
desiredCapabilities.setCapability("unicodeKeyboard","true");

desiredCapabilities.setCapability("autoGrantPermissions", "true");
URL remoteUrl = new URL("http://localhost:4723/wd/hub");
driver = new AndroidDriver(remoteUrl, desiredCapabilities);
}
driver.manage().timeouts().implicitlyWait(6000, TimeUnit.SECONDS);


}

@Parameterized.Parameters
public static List<Object[]> gupiao(){
return Arrays.asList(new Object[][]{
{"网易"},{"携程"},{"百度"},{"拼多多"},{"爱奇艺"},{"京东"},{"国双"},{"猎豹移动"}
,{"中国人寿"},{"优信"},{"哔哩哔哩"},{"陌陌"},{"苹果"},
});
}
@Parameterized.Parameter
public String name;

@Feature("添加删除股票")
@Test
@DisplayName("雪球添加股票测试")
public void test_add_us() throws InterruptedException {

WebElement tab =driver.findElementByXPath("//*[contains(@resource-id,'tab_name') and @text='自选']");
syup(tab);
driver.findElementByXPath("//*[contains(@resource-id,'tab_name') and @text='自选']").click();
driver.findElementByXPath("//android.widget.TextView[contains(@text,'美股')]").click();

driver.findElementById("action_create_cube").click();
driver.findElementById("search_input_text").sendKeys(name);
driver.findElementByXPath("//*[contains(@resource-id,'ll_stock_item_container')]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[2]").click();
sleep(1000);

// if (driver.findElements(By.xpath("//*[@text='下次再说']")).size()>0 ){
// driver.navigate().back();
// }
driver.navigate().back();
WebElement tac =driver.findElementByXPath("//*[@text='全部']");
syup(tac);
driver.findElementByXPath("//*[@text='全部']").click();
WebElement el = driver.findElementById("portfolio_stockName");
String tagName = el.getAttribute("text");
Assert.assertEquals(tagName,name);
driver.findElementByXPath("//android.widget.TextView[contains(@text,'美股')]").click();
sleep(1000);
swipe1(0.5,0.25);
driver.findElementByXPath("//*[@text='删除']").click();
Assert.assertNotEquals(el.getText(),name);
sleep(2000);


/**
* swipe(0.5,0.2,0.5,0.8);
*/









}
public void syup(WebElement elem) {
List<Point> list = new ArrayList<>();

for (int i = 0; i < 6; i++) {
WebElement elements = elem;
list.add(elements.getLocation());
if (i > 0) {
if (list.get(i - 1).equals(list.get(i))) {
break;
}
}

}
}
/**
* 长按封装
*/

public void swipe1(Double startX, Double startY){
Dimension size=driver.manage().window().getSize();
TouchAction touchAction = new TouchAction(driver);
touchAction.longPress(PointOption.point((int)(size.width*startX),(int)(size.height*startY)));
touchAction.release();
touchAction.perform();

}


/***
* 页面拖动封装
*/

@Ignore
public void swipe(Double startX, Double startY, Double endX, Double endY) throws InterruptedException {
Dimension size=driver.manage().window().getSize();

TouchAction touchAction = new TouchAction(driver);
touchAction.press(PointOption.point((int)(size.width*startX), (int)(size.height*startY)));
touchAction.waitAction(WaitOptions.waitOptions(Duration.ofSeconds(1)));
touchAction.moveTo(PointOption.point((int)(size.width*endX), (int)(size.height*endY)));
touchAction.release();
touchAction.perform();
Thread.sleep(1000);
}
@AfterClass
public static void tearDown() {
driver.quit();
}
}



import pytest
import unittest
from appium import webdriver
from time import sleep


class TestXueqiu(unittest.TestCase):
def setUp(self):
print("setup")
caps = {}
caps["platformName"] = "android"
caps["deviceName"] = "demo"
caps["appPackage"] = "com.xueqiu.android"
caps["appActivity"] = ".view.WelcomeActivityAlias"
caps["autoGrantPermissions"] = "true"

self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
self.driver.implicitly_wait(10)
# 作业一
# 从自选中搜索阿里巴巴股票,并添加到自选,点击取消按钮返回自选页面,断言查看是否存在该股票
def test_search_add(self):
self.driver.find_element_by_xpath(
"//*[contains(@resource-id,'tab_name') and @text='自选']")
self.driver.find_element_by_xpath(
"//*[contains(@resource-id,'tab_name') and @text='自选']").click()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys("alibaba")
if len(self.driver.find_elements_by_id("follow_btn"))>0:
self.driver.find_element_by_id("follow_btn").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_xpath(
"//*[@text='取消' and contains(@resource-id,'action_close')]").click()
assert 1 == len(self.driver.find_elements_by_xpath(
"//*[contains(@resource-id,'portfolio_stockName') and @text='阿里巴巴']"))
作业 1/2/3(上)
package appium_test;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.TouchAction;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.touch.LongPressOptions;
import io.appium.java_client.touch.offset.ElementOption;
import org.junit.*;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.DesiredCapabilities;

import java.io.File;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.concurrent.TimeUnit;

/**
* @author: panfeng
* @date: 2019/2/24 11:03
* @description:
*/

public class AppiumDemo {
private static AppiumDriver driver;
private static By home_search = By.id("home_search");
private static By search_text = By.id("search_input_text");
private static By option_pdd = By.xpath("//*[@text=\"拼多多\"]");
private static By stock_name = By.id("action_bar_stock_name");
private static By selx2 = By.xpath("//*[@text=\"自选\"]/..");
private static By sel_search = By.id("action_create_cube");
private static By flw_but = By.xpath("//*[contains(@resource-id, \"item_con\")]" +
"/android.widget.RelativeLayout[1]//*[contains(@resource-id, \"follow_\")]");
private static By uflw_but = By.xpath("//*[contains(@resource-id, \"item_con\")]" +
"/android.widget.RelativeLayout[1]//*[contains(@resource-id, \"followed_\")]");
private static By cancel_but = By.id("action_close");
private static By stk_pop_title = By.xpath("//*[contains(@resource-id, \"md_titleF\")]/*[contains(@resource-id, \"md_title\")]");
private static By stk_pop_del = By.xpath("//*[@text=\"删除\"]");
private static By hint_close = By.id("iv_close");

private static By cmt_popup = By.id("content");
private static By skip_cont = By.id("md_buttonDefaultNegative");
private static MobileElement find(By by) {
if (driver.findElement(cmt_popup).getLocation().getX() > 7) {
try {
driver.findElement(skip_cont).click();
}catch (NoSuchElementException ignored){
}
}
return (MobileElement) driver.findElement(by);
}

boolean flag = true;

@Before
public void setup() throws MalformedURLException{
// File classpathRoot = new File(System.getProperty("D:/"));
File app = new File("D:\\com.xueqiu.android_11.15_200.apk");
System.out.println(app.getAbsolutePath());
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability("app", app.getAbsolutePath());
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("deviceName", "phone");
capabilities.setCapability("appPackage", "com.xueqiu.android");
capabilities.setCapability("appActivity", ".view.WelcomeActivityAlias");
capabilities.setCapability("autoGrantPermissions", true);
capabilities.setCapability("resetKeyboard", true);
driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
}

@After
public void teardown(){
driver.removeApp("com.xueqiu.android");
driver.quit();
}
@Test
public void test_search_add(){
// 当自选按钮正常加载再点击自选按钮
for (int i=0; i<=9; i++){
Point sl = find(selx2).getLocation();
if (sl.getY() > 1000){
find(selx2).click();
break;
}
}
find(sel_search).click();
find(search_text).sendKeys("alibaba");
((AndroidDriver) driver).pressKeyCode(66);
try {
find(flw_but).click();
}
catch (NoSuchElementException e){
System.out.println("股票已添加");
}
find(cancel_but).click();
if (!driver.findElements(hint_close).isEmpty()){
driver.findElement(hint_close).click();
}
Assert.assertTrue(find(By.xpath("//*[@text=\"阿里巴巴\"]")).isDisplayed());
}

@Test
public void test_alibaba_search(){
// 当自选按钮正常加载再点击自选按钮
for (int i=0; i<=9; i++){
Point sl = find(selx2).getLocation();
if (sl.getY() > 1000){
find(selx2).click();
break;
}
}
find(sel_search).click();
find(search_text).sendKeys("alibaba");
((AndroidDriver) driver).pressKeyCode(66);
try {
find(flw_but).click();
}catch (Exception e){
find(uflw_but).click();
find(flw_but).click();
}
Assert.assertTrue(find(uflw_but).isDisplayed());
}

@Test
public void test_alibaba_exist_del(){
test_search_add();
TouchAction action = new TouchAction(driver);
MobileElement el = find(By.xpath("//*[@text=\"阿里巴巴\"]"));
action.longPress(LongPressOptions.longPressOptions().withElement(ElementOption.element(el))).release().perform();
// 验证添加的股票存在
Assert.assertEquals(find(stk_pop_title).getText(), "阿里巴巴");
// 验证股票可以被正常删除
find(stk_pop_del).click();
flag = true;
try {
for (int i = 0; i < 3; i++) {
find(By.xpath("//*[@text=\"阿里巴巴\"]"));
}
}catch (NoSuchElementException e){
flag = false;
}
Assert.assertFalse(flag);
}
}

作业 4

ADB 相关

# 检查 adb 是否存在
[ADB] Checking whether adb is present
# 找到一个 build-tools 文件夹
[ADB] Found 1 'build-tools' folders under 'D:\Program Files (x86)\Android\android-sdk' (newest first):
# 找到最新版本的 build-tools 文件夹
[ADB] D:/Program Files (x86)/Android/android-sdk/build-tools/28.0.1
# 使用对应文件夹下的 adb 命令执行程序
[ADB] Using adb.exe from D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe
# 尝试查找到一个已连接的安卓设备
[debug] [ADB] Trying to find a connected android device
# 正在获取已连接的安卓设备
# 一个安卓设备已连接
# 设置安卓设备的 id
[debug] [ADB] Getting connected devices...
[debug] [ADB] 1 device(s) connected
[debug] [ADB] Setting device id to AKC7N18609001220
# 获取安卓设备系统 api 版本(通过端口 5037
# 当前安卓设备属性 ro.build.version.sdk28
# 安卓设备 API 版本为 28
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell getprop ro.build.version.sdk'
[debug] [ADB] Current device property 'ro.build.version.sdk': 28
[debug] [ADB] Device API level: 28
# 在安卓设备连接之前把命令转载在adb的命令器中
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 wait-for-device'
# 检查安卓设备是否能响应 adb 命令
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell echo ping'
# 检查 io.appium.settings 是否安装(https://github.com/appium/io.appium.settings)
# 运行 adb shell dumpsys 命令获取包的安装状态
# io.appium.settings 已安装
[debug] [ADB] Getting install status for io.appium.settings
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell dumpsys package io.appium.settings'
[debug] [ADB] 'io.appium.settings' is installed
# 获取 io.appium.settings 包信息
# 运行 adb shell dumpsys 命令获取
[debug] [ADB] Getting package info for 'io.appium.settings'
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell dumpsys package io.appium.settings'
# 检查 aapt 命令执行程序位置
# 使用对应文件夹下的 aapt 命令执行程序
[ADB] Checking whether aapt is present
[ADB] Using aapt.exe from D:\Program Files (x86)\Android\android-sdk\build-tools\28.0.1\aapt.exe
# io.appium.settings 版本信息符合要求(>= '2.14.0')
# 不需要安装或升级 io.appium.settings
[debug] [ADB] The version name of the installed 'io.appium.settings' is greater or equal to the application version name ('2.14.0' >= '2.14.0')
[debug] [ADB] There is no need to install/upgrade 'C:\nvm\v10.15.1\node_modules\appium\node_modules\_io.appium.settings@2.14.0@io.appium.settings\apks\settings_apk-debug.apk'
# 获取所有 io.appium.settings 程序进程
[debug] [ADB] Getting IDs of all 'io.appium.settings' processes
# 检查 pgrep 是否可以执行
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell 'pgrep --help; echo $?''
# 列出相关进程 id
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell pgrep -f \^io\\.appium\\.settings\$'
# 授予 io.appium.settings 访问权限
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell appops set io.appium.settings android\:mock_location allow'
# 正在获取安卓设备平台版本
# 当前安卓设备平台版本 ro.build.version.release9
[ADB] Getting device platform version
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell getprop ro.build.version.release'
[debug] [ADB] Current device property 'ro.build.version.release': 9
# 获取安卓设备屏幕尺寸
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell wm size'
# 获取安卓设备型号
# 当前安卓设备型号 ro.product.model: CLT-AL01
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell getprop ro.product.model'
[debug] [ADB] Current device property 'ro.product.model': CLT-AL01
# 获取安卓设备厂商
# 当前安卓设备厂商 ro.product.manufacturer: HUAWEI
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell getprop ro.product.manufacturer'
[debug] [ADB] Current device property 'ro.product.manufacturer': HUAWEI
# 正在获取 com.codemao.dan 的安装状态
# 运行 adb shell dumpsys 命令获取包的安装状态
# com.codemao.dan 包未安装
[debug] [ADB] Getting install status for com.codemao.dan
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell dumpsys package com.codemao.dan'
[debug] [ADB] 'com.codemao.dan' is not installed
[debug] [ADB] App 'D:\com.codemao.dan_2.0.1_11.apk' is not installed
# 安装 apk
# 使用 adb install 命令安装apk-g 选项表示授予 apk 所有要求的权限)
[debug] [ADB] Installing 'D:\com.codemao.dan_2.0.1_11.apk'
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 install -g D\:\\com.codemao.dan_2.0.1_11.apk'
[debug] [ADB] Install command stdout: Success
# 可能是在清除一些缓存
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell rm -rf /data/local/tmp/strings.json'
# 正在提取 strings
[debug] [ADB] Extracting strings from for language: default
[ADB] Successfully extracted 218 strings from 'D:\com.codemao.dan_2.0.1_11.apk' resources for '(default)' configuration
# 将提取到的 strings.json 传至设备中
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 push C\:\\Users\\70913\\AppData\\Local\\Temp\\com.codemao.dan\\strings.json /data/local/tmp'
# 正在将 uiautomator2 server 4724 端口映射到电脑中
# 使用 adb forward 命令进行映射
[debug] [ADB] Forwarding system: 4724 to device: 4724
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 forward tcp\:4724 tcp\:4724'
# AppiumBootstrap.jar 传到安卓设备中
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 push C\:\\nvm\\v10.15.1\\node_modules\\appium\\node_modules\\_appium-android-driver\@4.8.0\@appium-android-driver\\bootstrap\\bin\\AppiumBootstrap.jar /data/local/tmp/'
# 正在试图杀死所有 uiautomator 进程
# 正在获取所有 uiautomator 进程 id
# 列出相关进程 id
# 找不到 uiautomator 进程
[debug] [ADB] Attempting to kill all uiautomator processes
[debug] [ADB] Getting IDs of all 'uiautomator' processes
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell pgrep -f \^uiautomator\$'
[ADB] No 'uiautomator' process has been found
# 正在创建 adb 子进程,启动手机端 Appium 服务进程
[debug] [ADB] Creating ADB subprocess with args: ["-P",5037,"-s","AKC7N18609001220","shell","uiautomator","runtest","AppiumBootstrap.jar","-c","io.appium.android.bootstrap.Bootstrap","-e","pkg","com.codemao.dan","-e","disableAndroidWatchers",false,"-e","acceptSslCerts",false]
# 获取设备屏幕信息
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell dumpsys window'
# 启动 app
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell am start -W -n com.codemao.dan/.view.welcome.FirstActivity -S -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000'
# 强制停止 com.codemao.dan
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell am force-stop com.codemao.dan'
# 正在按下 HOME
[debug] [ADB] Pressing the HOME button
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell input keyevent 3'
# 正在试图杀死所有 uiautomator 进程
# 正在获取所有 uiautomator 进程 id
# 列出相关进程 id
# 找不到 uiautomator 进程
[debug] [ADB] Attempting to kill all uiautomator processes
[debug] [ADB] Getting IDs of all 'uiautomator' processes
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell pgrep -f \^uiautomator\$'
[ADB] No 'uiautomator' process has been found
# 强制停止 io.appium.unlock
[debug] [ADB] Running 'D:\Program Files (x86)\Android\android-sdk\platform-tools\adb.exe -P 5037 -s AKC7N18609001220 shell am force-stop io.appium.unlock'

HTTP 相关

# 对已创建的 session 发起一个 POST 请求
# 传递代码中设置的 desiredCapabilities uiautomator
# 发起请求成功,耗时 23131 ms,传递数据长度 870
[HTTP] --> POST /wd/hub/session
[HTTP] {"desiredCapabilities":{"app":"D:\\com.xueqiu.android_11.15_200.apk","appActivity":".view.WelcomeActivityAlias","appPackage":"com.xueqiu.android","autoGrantPermissions":true,"platformName":"Android","deviceName":"phone","resetKeyboard":true},"capabilities":{"alwaysMatch":{"appium:app":"D:\\com.xueqiu.android_11.15_200.apk","appium:appActivity":".view.WelcomeActivityAlias","appium:appPackage":"com.xueqiu.android","appium:autoGrantPermissions":true,"appium:deviceName":"phone","platformName":"android","appium:resetKeyboard":true},"firstMatch":[{}]}}
[HTTP] <-- POST /wd/hub/session 200 23131 ms - 870
# 对已创建的 session 发起一个 POST 请求,进行超时设置
# 设置隐式等待时间
# 发起请求成功,耗时 2 ms,传递数据长度 14
[HTTP] --> POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/timeouts
[HTTP] {"implicit":7000}
[HTTP] <-- POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/timeouts 200 2 ms - 14
# 对已创建的 session 发起一个 POST 请求,设置元素的查找方式
# 设置查找的元素 id content
# 发起请求成功,耗时 51 ms,传递数据长度 67
[HTTP] --> POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element
[HTTP] {"using":"id","value":"content"}
[HTTP] <-- POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element 200 51 ms - 67
# 对已创建的 session 发起一个 GET 请求,进行元素查找
# 没有找到元素
# 发起请求成功,耗时 12 ms,传递数据长度 24
[HTTP] --> GET /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element/1/location
[HTTP] {}
[HTTP] <-- GET /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element/1/location 200 12 ms - 24
# 对已创建的 session 发起一个 POST 请求,进行元素的点击操作
# 传递需要执行点击操作的元素 id (该 id uiautomator 创建)
# 发起请求成功,耗时 315 ms,传递数据长度 14
[HTTP] --> POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element/2/click
[HTTP] {"id":"2"}
[HTTP] <-- POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element/2/click 200 315 ms - 14
# 对已创建的 session 发起一个 POST 请求,设置文本框的值
# 传递文本框元素 id,需要输入的文本内容
# 发起请求成功,耗时 315 ms,传递数据长度 14
[HTTP] --> POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element/4/value
[HTTP] {"id":"4","text":"pdd","value":["p","d","d"]}
[HTTP] <-- POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/element/4/value 200 4923 ms - 14
# 对已创建的 session 发起一个 POST 请求,执行卸载操作
# 传递需要卸载的包的 bundleId
# 发起请求成功,耗时 1719 ms,传递数据长度 14
[HTTP] --> POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/appium/device/remove_app
[HTTP] {"bundleId":"com.xueqiu.android"}
[HTTP] <-- POST /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc/appium/device/remove_app 200 1719 ms - 14
# 对已创建的 session 发起一个 DELETE 请求,删除创建的 session
[HTTP] --> DELETE /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc
[HTTP] {}
[HTTP] <-- DELETE /wd/hub/session/f9d54d97-2ed1-48ed-bd91-7bc8c937a4bc 200 1885 ms - 14

作业四:


#获取手机sdk版本
adb shell getprop ro.build.version.sdk

#查看设备是否安装了应用
adb shell pm list packages com.xueqiu.android

#获取设备是否安装
adb shell dumpsys package io.appium.settings

#查看手机进程
adb shell ps

#获取模拟定位权限
adb shell appops set io.appium.settings android\:mock_location allow

#隐藏键盘
adb shell settings get secure default_input_method

#切换手机输入法
adb shell ime enable io.appium.android.ime/.UnicodeIME

#查看设备系统版本
adb shell getprop ro.build.version.release

#获取设备分辨率
adb shell wm size

#获取android产品模型
adb shell getprop ro.product.model

#获取手机厂商信息
adb shell getprop ro.product.manufacturer

#获取安装包信息
adb shell dumpsys package com.xueqiu.android

#强行停止app
adb shell am force-stop com.xueqiu.android

#清除app数据
adb shell pm clear com.xueqiu.android

#查询设备上当前窗口信息
adb shell dumpsys window

#启动App,显示启动时间等数据
adb shell am start -W -n com.xueqiu.android/.view.WelcomeActivityAlias -S -a android.intent.action.MAIN -c
android.intent.category.LAUNCHER -f 0x10200000

#关闭app
adb shell input keyevent 3
# 创建session 发起post请求 desiredCapabilities相关参数 耗时6735 ms
[HTTP] --> POST /wd/hub/session
[HTTP] {"desiredCapabilities":{"appActivity":".view.WelcomeActivityAlias","appPackage":"com.xueqiu.android","aut
oGrantPermissions"
:"true","unicodeKeyboard":"true","platformName":"Android","deviceName":"demo"},"capabilities":{"alwaysMatch":{"appium:appActiv
ity"
:".view.WelcomeActivityAlias","appium:appPackage":"com.xueqiu.android","appium:autoGrantPermissions":"true","appium:deviceName":"demo","plat
formName"
:"android","appium:unicodeKeyboard":"true"},"firstMatch":[{}]}}
[HTTP] <-- POST /wd/hub/session 200 6735 ms - 832


# session发送get请求 w3c标准 耗时20ms
[HTTP] --> GET /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551
[HTTP] <-- GET /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551 200 20 ms - 764

# session发送get请求 w3c标准 耗时3ms
[HTTP] --> GET /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551
[HTTP] <-- GET /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551 200 3 ms - 764

# session发送post请求 隐式等待 耗时4ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/timeouts
[HTTP] {"implicit":6000000}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/timeouts 200 4 ms - 14

# session发送post请求 id=cancel 耗时3228ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element
[HTTP] {"using":"id","value":"cancel"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element 200 3228 ms - 53

# session发送post请求 id=1 耗时1477ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/1/click
[HTTP] {"id":"1"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/1/click 200 1477 ms - 14

# session发送post请求 xpath
耗时160ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element
[HTTP] {"using":"xpath","value":"//*[contains(@resource-id,'public_timeline_actionbar')]/android.widget.LinearLayout/android.widget.ImageView"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element 200 160 ms - 53

#session发送post请求 id=2 耗时581ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/2/click
[HTTP] {"id":"2"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/2/click 200 581 ms - 14

#session发送post请求 id=search_input_text 耗时814ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element
[HTTP] {"using":"id","value":"search_input_text"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element 200 814 ms - 53

#session发送post请求 id=3 text=阿里巴巴 输入文本:阿里巴巴 耗时4762ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/3/value
[HTTP] {"id":"3","text":"阿里巴巴","value":["阿","里","巴","巴"]}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/3/value 200 4762 ms - 14

#session发送post请求 xpath元素定位 耗时1457ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element
[HTTP] {"using":"xpath","value":"//*[contains(@resource-id,'stockName') and @text='阿里巴巴']/../..//*[contains(@resource-id,'follow_btn')]"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element 200 1457 ms - 53

#session发送post请求 id=4 耗时278ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/4/click
[HTTP] {"id":"4"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/4/click 200 278 ms - 14

#session发送post请求 返回上一页面 耗时1678ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/back
[HTTP] {}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/back 200 1678 ms - 14

#session发送post请求 id=add_attention 耗时13ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element
[HTTP] {"using":"id","value":"add_attention"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element 200 13 ms - 53

#session发送post请求 id=5 class name=android.widget.TextView 耗时42ms
[HTTP] --> POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/5/element
[HTTP] {"id":"5","using":"class name","value":"android.widget.TextView"}
[HTTP] <-- POST /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/5/element 200 42 ms - 53

#session发送post请求 执行String tagName = element.getAttribute("resourceId"); 耗时111ms
[HTTP] --> GET /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/6/attribute/resourceId
[HTTP] {}
[HTTP] <-- GET /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551/element/6/attribute/resourceId 200 111 ms -
46

#session发送DELETE 请关闭 耗时1881ms
[HTTP] --> DELETE /wd/hub/session/350f46a1-58c1-4045-9a3b-8cee4c47c551
[HTTP] {}

作业三

github地址:https://github.com/Pydaily/XueQiu/blob/master/src/test_xueqiu.py

#!/usr/bin/env python
# -*- Coding:utf-8 -*-
from appium import webdriver
import pytest
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By


class TestXueQiu:
agree = (By.XPATH, "//*[@text='允许']") # 允许按钮
optional = (By.XPATH, "//*[@text='自选' and contains(@resource-id,'tab_name')]") # 自选按钮
tv_search = (By.ID, "tv_search") # 搜索框
search_input = (By.ID, "search_input_text") # 搜索输入框
cancel = (By.ID, "image_cancel") # 取消更新按钮
add_1st = (By.XPATH, "//*[contains(@resource-id,'follow_btn') and @instance=9]") # 每个搜索的第一只股票
next_time = (By.XPATH, "//*[@text='下次再说']") # 下次再说按钮
stock_cancal = (By.ID, "action_close") # 搜索取消按钮
follow_cancel = (By.ID, "iv_close") # 关注取消按钮
us_stock = (By.XPATH, "//*[@text='美股']") # 美股按钮
stock_change = (By.ID, "btn_change") # 涨跌幅按钮
stock_alibaba = (By.XPATH, "//*[contains(@resource-id,'portfolio_stockName') and @text='阿里巴巴']") # 阿里巴巴股票
stock_del = (By.XPATH, "//*[@text='删除']") # 删除按钮
bmp_close = (By.ID, "closeBtn") # BMP关闭按钮

@pytest.fixture(scope="function", autouse=True) # 如果scope设置为class,则需要return driver 并将base作为参数传入后续用例调用
def base(self):
self.driver = webdriver.Remote("http://localhost:4723/wd/hub",
{"platformName": "android",
"deviceName": "demo",
"appPackage": "com.xueqiu.android",
"appActivity": ".view.WelcomeActivityAlias",
"unicodeKeyboard": True,
"resetKeyboard": True,
"autoGrantPermissions": True,
})
self.driver.implicitly_wait(6)
self.find(*self.agree) # 权限提示检测
self.find(*self.agree)
yield
self.driver.quit()

# 封装控件查找方法,默认选择click方法,以便处理弹窗问题
def find(self, *args, autoclick=True):
try:
if self.driver.find_element(*args):
if autoclick:
return self.driver.find_element(*args).click()
else:
return self.driver.find_element(*args)
else:
# 建立白名单,通过XPATH将随时可能出现的按钮处理掉
# 把else的代码放到except中处理会报错,后续需理清
whitelist = ["//*[@text='允许']", "//*[@text='创建您的专属选股策略']",
"//*[@text='下次再说']", "//*[contains(@resource-id,'iv_close')]"]
for key in whitelist:
if self.driver.find_element(By.XPATH, key):
self.driver.find_element(By.XPATH, key).click()
except:
pass

# 封装页面加载检测方法
def loaded(self, no_stock=True):
locations = []
while True:
if no_stock:
loc = self.find(*self.optional, autoclick=False) # 检测主页是否加载完毕
else:
loc = self.find(*self.stock_change, autoclick=False) # 检测自选股是否加载完毕
locations.append(loc.location)
if len(locations) >= 2:
if locations[-1] == locations[-2]:
break

# 封装搜索添加股票方法
def search_add_stock(self, stockname):
self.find(*self.cancel) # 点击关闭更新按钮
self.loaded() # 检测首页是否加载完成
self.find(*self.tv_search) # 点击搜索框
self.find(*self.search_input, autoclick=False).send_keys(stockname)
self.find(*self.add_1st) # 点击第一只股票的添加按钮
self.find(*self.next_time) # 处理可能出现的评价按钮

# 搜索并添加阿里巴巴股票
def test_add_us(self):
self.search_add_stock("阿里巴巴") # 搜索阿里巴巴
self.find(*self.stock_cancal) # 点击搜索取消按钮
self.find(*self.follow_cancel) # 处理可能弹出的关注tips
self.find(*self.optional) # 点击自选按钮
self.find(*self.us_stock) # 点击美股按钮
assert self.find(*self.stock_alibaba, autoclick=False)

# 删除添加阿里巴巴股票
def test_delete_us(self):
self.find(*self.cancel) # 点击关闭更新按钮
self.loaded() # 检测首页是否加载完成
self.find(*self.optional) # 点击自选按钮
self.loaded(no_stock=False) # 检测自选股是否加载完毕
self.find(*self.us_stock) # 点击美股按钮
el = self.find(*self.stock_alibaba, autoclick=False) # 查找自选中是否有阿里巴巴股票
if el:
TouchAction(self.driver).long_press(el).perform()
self.find(*self.stock_del)
assert not self.find(*self.stock_alibaba, autoclick=False)

# 参数化添加三十只股票
@pytest.mark.parametrize("stockname", [
"百度", "阿里巴巴", "腾讯", "美团", "今日头条",
"拼多多", "饿了么", "京东", "滴滴出行", "中国平安",
"中国联通", "中国移动", "Facebook", "Google", "大疆",
"雅虎", "微软", "高通", "小米", "格力",
"oppo", "vivo手机", "苹果", "美的", "恒大",
"蚂蚁金服", "网易", "陌陌", "中国人保", "京东方"
])
def test_add_batch(self, stockname):
self.search_add_stock(stockname)

# 封装查询某项所有股票名方法
def get_stocks(self,times):
my_stocks = []
for i in range(times):
stocks = self.driver.find_elements_by_id("portfolio_stockName")
for x in stocks:
my_stocks.append(x.text)
self.driver.swipe(550, 1540, 550, 500, duration=400)
my_stocks = list(set(my_stocks)) # 去掉重复元素
return my_stocks

# 检测某个股票是否同时在全部股票以及美股中存在
def test_exit_in_all(self):
self.find(*self.cancel) # 点击关闭更新按钮
self.loaded() # 检测首页是否加载完成
self.find(*self.optional) # 点击自选按钮
self.loaded(no_stock=False) # 检测自选股是否加载完毕
self.find(*self.bmp_close) # 点击BMP行情关闭按钮
all_stocks = self.get_stocks(5)

self.find(*self.us_stock) # 点击美股按钮
self.loaded(no_stock=False) # 检测美股是否加载完毕
us_stocks = self.get_stocks(3)
mystock= "阿里巴巴"
assert mystock in all_stocks and mystock in us_stocks


[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 shell dumpsys package io.appium.settings'
[AndroidDriver] Ignored error while installing Appium Settings helper: 'Could not find aapt Please set the ANDROID_HOME environment variable with the Android SDK root directory path.'. Manually uninstalling the application with package id 'io.appium.settings' may help. Expect some Appium features may not work as expected unless this problem is fixed.
[debug] [ADB] Getting IDs of all 'io.appium.settings' processes
[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 shell 'pgrep --help; echo $?''
[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 shell pgrep \^appium\\.settings\$'
[debug] [AndroidDriver] io.appium.settings is already running. There is no need to reset its permissions.
[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 shell appops set io.appium.settings android\:mock_location allow'
[debug] [Logcat] Starting logcat capture
[debug] [ADB] Getting install status for io.appium.uiautomator2.server
[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 shell dumpsys package io.appium.uiautomator2.server'
[debug] [ADB] 'io.appium.uiautomator2.server' is installed
[debug] [ADB] Getting package info for 'io.appium.uiautomator2.server'
[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 shell dumpsys package io.appium.uiautomator2.server'
[debug] [UiAutomator2] Deleting UiAutomator2 session
[debug] [UiAutomator2] Deleting UiAutomator2 server session
[debug] [WD Proxy] Matched '/' to command name 'deleteSession'
[UiAutomator2] Did not get confirmation UiAutomator2 deleteSession worked; Error was: UnknownError: An unknown server-side error occurred while processing the command. Original error: Trying to proxy a session command without session id
[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 shell am force-stop com.xueqiu.android'
[debug] [Logcat] Stopping logcat capture
[debug] [ADB] Removing forwarded port socket connection: 8200
[debug] [ADB] Running '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 forward --remove tcp\:8200'
[UiAutomator2] Unable to remove port forward 'Error executing adbExec. Original error: 'Command '/Users/bgzhou/Library/Android/sdk/platform-tools/adb -P 5037 -s 192.168.56.101\:5555 forward --remove tcp\:8200' exited with code 1'; Stderr: 'error: listener 'tcp:8200' not found'; Code: '1''
[debug] [BaseDriver] Event 'newSessionStarted' logged at 1551365559584 (22:52:39 GMT+0800 (中国标准时间))
[debug] [W3C] Encountered internal error running command: Error: Could not find aapt Please set the ANDROID_HOME environment variable with the Android SDK root directory path.
[debug] [W3C] at ADB.systemCallMethods.getBinaryFromPath (/usr/local/lib/node_modules/appium/node_modules/_appium-adb@7.2.0@appium-adb/lib/tools/system-calls.js:131:11)

想问一下添加了caps["automationName"] = "uiautomator2" 属性后,执行报错是因为什么原因,上面是appium的日志,下面是ide的报错,ANDROID_HOME这个环境变量已经配置了,不添加automationName是可以顺利运行的

selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Could not find aapt Please set the ANDROID_HOME environment variable with the Android SDK root directory path.
Xiaos-MacBook-Pro:testlearn bgzhou$ echo $ANDROID_HOME
/Users/bgzhou/Library/Android/sdk
cookie 回复

多终端环境问题,已经自行解决了

作业三:https://github.com/AmyYJ/AppiumDemo_Android

# 自选页初始状态,添加一只美股
def test_add_us(self):
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()
self.driver.find_element_by_id("recommend_name_one").click()
self.driver.implicitly_wait(10)
stock_name=self.driver.find_element_by_id("action_bar_stock_name").text
print(stock_name)
self.driver.find_element_by_xpath("//*[@text='加自选']")
self.driver.find_element_by_xpath("//*[@text='加自选']")
self.driver.find_element_by_xpath("//*[@text='加自选']").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()

assert 1 == len(self.driver.find_elements_by_xpath("//*[@text='设自选']"))

self.driver.back()

self.driver.find_element_by_xpath("//*[@text='美股']").click()
assert 1 == len(self.driver.find_elements_by_xpath("//*[@text='"+stock_name+"']"))
self.driver.find_element_by_xpath("//*[@text='全部']").click()
assert 1 == len(self.driver.find_elements_by_xpath("//*[@text='"+stock_name+"']"))


#自选页删除一只美股
def test_delete_us(self):
# global stock_name
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()

elements = self.driver.find_elements_by_id("portfolio_stockName")
stock_name=elements[0].text
print("*************"+stock_name)

TouchAction(self.driver).long_press(elements[0]).perform()
self.driver.find_element_by_xpath("//*[@text='删除']").click()

assert 0 == len(self.driver.find_elements_by_xpath("//*[@text='"+stock_name+"']"))
self.driver.find_element_by_xpath("//*[@text='全部']").click()
assert 0 == len(self.driver.find_elements_by_xpath("//*[@text='" + stock_name + "']"))

#批量加入自选
@pytest.mark.parametrize("stockname",["百度","特斯拉","京东","阿里巴巴","哔哩哔哩","拼多多",
"迅雷","大众仓储","苏格兰皇家银行","美国银行","爱奇艺","优信"
"蔚来","58同城","Facebook","摩根大通","腾讯音乐","卡夫亨氏",
"陌陌","AMD","格林电视","众美联","协同制药","Endava"])
def test_add_batch(self,stockname):
self.driver.find_element_by_id("tv_search").click()
self.driver.find_element_by_id("search_input_text").send_keys(stockname)
if len(self.driver.find_elements_by_xpath("//*[@text='下次再说']")) > 0:
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_id("follow_btn").click()

作业三:


/**
* 添加判断和删除判断都在这个方法里面
*/

@Test
public void test_addANDdelete_us() throws InterruptedException {
//循环定位自选按钮并点击
WebElement zixuanEle = driver.findElement(By.xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]"));
getRightEle(zixuanEle);
driver.findElement(By.xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]")).click();
java.lang.Thread.sleep(3000);
//滑动至美股tab页
TouchAction touchAction = new TouchAction(driver);
for (int i = 1;i<=3;i++){
touchAction.longPress(PointOption.point(800,1200))
.moveTo(PointOption.point(50,1200))
.release()
.perform();
java.lang.Thread.sleep(1000);
}
//获取当前页所有推荐的美股名字(把他们存在List里面)
List<WebElement> elements = driver.findElement(By.id("portfolio_recommend_stocks"))
.findElements(By.xpath("//*[contains(@resource-id, 'recommend_name')]"));

List<String> stringList = new ArrayList<>();
for (WebElement ele:elements
) {
stringList.add(ele.getAttribute("text"));
}
for (String str:stringList
) {
System.out.println(str);
}
java.lang.Thread.sleep(1000);
//点击“加入自选股”,把当前页面的所有推荐的美股加入自选股(前提:当前美股tab页下没有添加过股票)
driver.findElement(By.id("add_to_portfolio_stock")).click();

//获取当前页面所有的股票名字,存在List内
List<WebElement> allEles = driver.findElement(By.id("listview"))
.findElements(By.xpath("//*[contains(@resource-id, 'portfolio_stockName')]"));
List<String> stringList2 = new ArrayList<>();
for (WebElement ele:allEles
) {
stringList2.add(ele.getAttribute("text"));
}
for (String str:stringList2
) {
System.out.println(str);
System.out.println("打印完了");
}
//判断推荐页的所有股票名的List和添加后页面的所有股票名List内容是否相等
System.out.println();
Assert.assertEquals(stringList.containsAll(stringList2),true,"stringList not containsAll stringList2");

}

/**
* 循环判断正确坐标的元素
* @param elem
*/

public void getRightEle(WebElement elem) {
List<Point> list = new ArrayList<>();

for (int i = 0; i < 6; i++) {
list.add(elem.getLocation());
if (i > 0) {
if (list.get(i - 1).equals(list.get(i))) {
break;
}
}
}
}

作业四:
ADB相关:


#检查ADB是否存在
2019-02-25 02:26:25:639 [ADB] Checking whether adb is present

#找到两个“build-tools”文件在'/Users/Wangjr/Library/Android/sdk' 这个目录下,(最新的一个)
2019-02-25 02:26:25:657 [ADB] Found 2 'build-tools' folders under '/Users/Wangjr/Library/Android/sdk' (newest first):

#对应上面命令的两个build-tools文件,第一个是最新的
2019-02-25 02:26:25:658 [ADB] /Users/Wangjr/Library/Android/sdk/build-tools/28.0.3
2019-02-25 02:26:25:658 [ADB] /Users/Wangjr/Library/Android/sdk/build-tools/28.0.2

#使用Users/Wangjr/Library/Android/sdk/platform-tools/adb这个目录下的adb
2019-02-25 02:26:25:659 [ADB] Using adb from /Users/Wangjr/Library/Android/sdk/platform-tools/adb

#尝试找一个已连接的安卓设备
2019-02-25 02:26:25:660 [ADB] Trying to find a connected android device

#获取已连接的设备中
2019-02-25 02:26:25:661 [ADB] Getting connected devices...

#一个设备已连接
2019-02-25 02:26:25:672 [ADB] 1 device(s) connected

#设定设备的id022MWW146R006173
2019-02-25 02:26:25:675 [ADB] Setting device id to 022MWW146R006173

#获取系统api版本
2019-02-25 02:26:25:676 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell getprop ro.build.version.sdk'

#当前设备系统api版本:22
2019-02-25 02:26:25:708 [ADB] Current device property 'ro.build.version.sdk': 22

#设备API版本:22
2019-02-25 02:26:25:709 [ADB] Device API level: 22

#通过5037端口来找设备为“022MWW146R006173”的设备下查看是否装了雪球
2019-02-25 02:26:25:711 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell pm list packages com.xueqiu.android'

#通过5037端口找到“022MWW146R006173”设备,等正确连接到设备后立即执行其他命令
2019-02-25 02:26:26:244 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 wait-for-device'

#通过5037端口找到“022MWW146R006173”设备,获取系统的api版本
2019-02-25 02:26:25:676 [ADB] Running '/Users/Wangjr/Library/Android/sdk/plat
form-tools/adb -P 5037 -s 022MWW146R006173 shell getprop ro.build.version.sdk

#当前设备属性'ro.build.version.sdk':22
2019-02-25 02:26:25:708 [ADB] Current device property 'ro.build.version.sdk':
22

#当前设备API版本是22
2019-02-25 02:26:25:709 [ADB] Device API level: 22

#查看设备是否安装了雪球
2019-02-25 02:26:25:711 [ADB] Running '/Users/Wangjr/Library/Android/sdk/plat
form-tools/adb -P 5037 -s 022MWW146R006173 shell pm list packages com.xueqiu.
android'

#通过5037端口找到“022MWW146R006173”设备,等正确连接到设备后立即执行其他命令
2019-02-25 02:26:26:244 [ADB] Running '/Users/Wangjr/Library/Android/sdk/plat
form-tools/adb -P 5037 -s 022MWW146R006173 wait-for-device'

#检查安卓设备是否能响应 adb 命令
2019-02-25 02:26:26:254 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell echo ping'

#获取io.appium.settings的安装状态
2019-02-25 02:26:26:276 [ADB] Getting install status for io.appium.settings

#获取io.appium.settings'包的安装状态
2019-02-25 02:26:26:276 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell dumpsys package io.appium.settings'

#io.appium.settings已安装
2019-02-25 02:26:26:325 [ADB] 'io.appium.settings' is installed

#获取'io.appium.settings’包的信息
2019-02-25 02:26:26:326 [ADB] Getting package info for 'io.appium.settings'

#获取io.appium.settings'包的安装状态
2019-02-25 02:26:26:327 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell dumpsys package io.appium.settings'

#检查aapt是否存在
2019-02-25 02:26:26:375 [ADB] Checking whether aapt is present

#使用/Users/Wangjr/Library/Android/sdk/build-tools/28.0.3/aapt下的aapt
2019-02-25 02:26:26:376 [ADB] Using aapt from /Users/Wangjr/Library/Android/sdk/build-tools/28.0.3/aapt

#io.appium.settings这个包版本比settings_apk-debug.apk的版本要老
2019-02-25 02:26:26:401 [ADB] The installed 'io.appium.settings' package is older than '/usr/local/lib/node_modules/appium/node_modules/_io.appium.settings@2.12.1@io.appium.settings/apks/settings_apk-debug.apk' (5 < 15 or '2.3.0' < '2.12.1')'

#对settings_apk-debug.apk进行升级
2019-02-25 02:26:26:402 [ADB] Executing upgrade of '/usr/local/lib/node_modules/appium/node_modules/_io.appium.settings@2.12.1@io.appium.settings/apks/settings_apk-debug.apk'

#设备API版本22
2019-02-25 02:26:26:403 [ADB] Device API level: 22

#跳过权限授予选项,因为当前API级别22不支持应用程序权限自定义
2019-02-25 02:26:26:403 [ADB] Skipping permissions grant option, since the current API level 22 does not support applications permissions customization

#安装settings_apk-debug.apk
Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 install -r /usr/local/lib/node_modules/appium/node_modules/_io.appium.settings\@2.12.1\@io.appium.settings/apks/settings_apk-debug.apk'

#安装进度,结果升级失败了
2019-02-25 02:26:43:303 [ADB] Install command stdout: [ 11%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:303 [ADB] [ 22%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:303 [ADB] [ 33%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:304 [ADB] [ 45%] /data...debug.apk: 1 file pushed. 9.5 MB/s (581672 bytes in 0.058s)
2019-02-25 02:26:43:304 [ADB] pkg: /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:304 [ADB] Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]
2019-02-25 02:26:43:305 [ADB] Cannot upgrade 'io.appium.settings' because of '[ 11%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:306 [ADB] [ 22%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:306 [ADB] [ 33%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:307 [ADB] [ 45%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:307 [ADB] [ 56%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:308 [ADB] [ 67%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:308 [ADB] [ 78%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:310 [ADB] [ 90%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:310 [ADB] [100%] /data/local/tmp/settings_apk-debug.apk

#推送1个文件。 9.5 MB / s0.058秒内581672字节),因为安装失败了所以就卸了重新装,然后装成功了
2019-02-25 02:26:43:311 [ADB] /usr/local/lib/node_modules/appium/node_modules/_io.appium.settings@2.12.1@io.appium.settings/apks/settings_apk-debug.apk: 1 file pushed. 9.5 MB/s (581672 bytes in 0.058s)
2019-02-25 02:26:43:312 [ADB] pkg: /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:312 [ADB] Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]'. Trying full reinstall
2019-02-25 02:26:43:312 [ADB] Uninstalling io.appium.settings
2019-02-25 02:26:43:313 [ADB] Getting install status for io.appium.settings
2019-02-25 02:26:43:313 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell dumpsys package io.appium.settings'
2019-02-25 02:26:43:360 [ADB] 'io.appium.settings' is installed
2019-02-25 02:26:43:361 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell am force-stop io.appium.settings'
2019-02-25 02:26:44:125 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 uninstall io.appium.settings'
2019-02-25 02:26:45:458 [ADB] 'adb uninstall io.appium.settings' command output: Success
2019-02-25 02:26:45:459 [ADB] io.appium.settings was successfully uninstalled
2019-02-25 02:26:43:312 [ADB] pkg: /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:43:312 [ADB] Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]'. Trying full reinstall
2019-02-25 02:26:43:312 [ADB] Uninstalling io.appium.settings
2019-02-25 02:26:43:313 [ADB] Getting install status for io.appium.settings
2019-02-25 02:26:43:313 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell dumpsys package io.appium.settings'
2019-02-25 02:26:43:360 [ADB] 'io.appium.settings' is installed
2019-02-25 02:26:43:361 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell am force-stop io.appium.settings'
2019-02-25 02:26:44:125 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 uninstall io.appium.settings'
2019-02-25 02:26:45:458 [ADB] 'adb uninstall io.appium.settings' command output: Success
2019-02-25 02:26:45:459 [ADB] io.appium.settings was successfully uninstalled
2019-02-25 02:26:45:459 [ADB] Device API level: 22
2019-02-25 02:26:45:459 [ADB] Skipping permissions grant option, since the current API level 22 does not support applications permissions customization
2019-02-25 02:26:45:460 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 install /usr/local/lib/node_modules/appium/node_modules/_io.appium.settings\@2.12.1\@io.appium.settings/apks/settings_apk-debug.apk'
2019-02-25 02:26:49:702 [ADB] Install command stdout: [ 11%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:49:703 [ADB] [ 22%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:49:703 [ADB] [ 33%] /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:49:703 [ADB] [ 45%] /data...io.appium.settings/apks/settings_apk-debug.apk: 1 file pushed. 4.8 MB/s (581672 bytes in 0.116s)
2019-02-25 02:26:49:703 [ADB] pkg: /data/local/tmp/settings_apk-debug.apk
2019-02-25 02:26:49:704 [ADB] Success

#获取所有'io.appium.settings'进程的ID
2019-02-25 02:26:49:705 [ADB] Getting IDs of all 'io.appium.settings' processes

#授权
2019-02-25 02:26:49:831 [ADB] Granting permissions ["android.permission.SET_ANIMATION_SCALE","android.permission.CHANGE_CONFIGURATION","android.permission.ACCESS_FINE_LOCATION"] to 'io.appium.settings'

#执行下面的命令
2019-02-25 02:26:49:831 [ADB] Got the following command chunks to execute: [["pm","grant","io.appium.settings","android.permission.SET_ANIMATION_SCALE",";","pm","grant","io.appium.settings","android.permission.CHANGE_CONFIGURATION",";","pm","grant","io.appium.settings","android.permission.ACCESS_FINE_LOCATION",";"]]

#获取当前的安卓版本
2019-02-25 02:26:54:255 [ADB] Getting device platform version

#adb获取Android系统属性ro.build.version.release数据来源
2019-02-25 02:26:54:256 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell getprop ro.build.version.release'

#当前设备属性'ro.build.version.release':5.1.1
2019-02-25 02:26:54:293 [ADB] Current device property 'ro.build.version.release': 5.1.1

# 获取安卓设备屏幕尺寸
2019-02-25 02:26:54:294 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell wm size'

#查看设备型号
2019-02-25 02:26:55:264 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell getprop ro.product.model'

#当前的设备是华为P7_L07
2019-02-25 02:26:55:298 [ADB] Current device property 'ro.product.model': HUAWEI P7-L07

#查看手机厂商
2019-02-25 02:26:55:300 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell getprop ro.product.manufacturer'

#手机厂商:华为
2019-02-25 02:26:55:334 [ADB] Current device property 'ro.product.manufacturer': HUAWEI

#获取雪球APP的安装状态
2019-02-25 02:26:55:337 [ADB] Getting install status for com.xueqiu.android

#查看雪球APP的详细信息
2019-02-25 02:26:55:337 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell dumpsys package com.xueqiu.android'

#雪球已经安装了
2019-02-25 02:26:55:385 [ADB] 'com.xueqiu.android' is installed

#关闭雪球
2019-02-25 02:26:55:385 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell am force-stop com.xueqiu.android'

#清除雪球的缓存
2019-02-25 02:26:56:220 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell pm clear com.xueqiu.android'

#设备API版本22
2019-02-25 02:26:57:025 [ADB] Device API level: 22

#查看雪球APP的详细信息
2019-02-25 02:26:57:025 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell dumpsys package com.xueqiu.android'

#将 uiautomator2 server 4724 端口映射到电脑中
2019-02-25 02:26:57:122 [ADB] Forwarding system: 4724 to device: 4724

#使用 adb forward 命令进行映射
2019-02-25 02:26:57:122 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 forward tcp\:4724 tcp\:4724'

#将 AppiumBootstrap.jar 传到安卓设备中
2019-02-25 02:26:57:135 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 push /usr/local/lib/node_modules/appium/node_modules/_appium-android-driver\@4.8.0\@appium-android-driver/bootstrap/bin/AppiumBootstrap.jar /data/local/tmp/'

#尝试kill掉所有的uiautomator进程
2019-02-25 02:26:57:166 [ADB] Attempting to kill all uiautomator processes

#获取uiautomator进程的id
2019-02-25 02:26:57:166 [ADB] Getting IDs of all 'uiautomator' processes

#找出uiaotimator进程PID
2019-02-25 02:26:57:167 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell pidof uiautomator'

#没有找到uiautomator进程
2019-02-25 02:26:57:223 [ADB] No 'uiautomator' process has been found

#正在创建ADB子进行
2019-02-25 02:26:57:224 [ADB] Creating ADB subprocess with args: ["-P",5037,"-s","022MWW146R006173","shell","uiautomator","runtest","AppiumBootstrap.jar","-c","io.appium.android.bootstrap.Bootstrap","-e","pkg","com.xueqiu.android","-e","disableAndroidWatchers",false,"-e","acceptSslCerts",false]

#查看设备屏幕的所有信息
2019-02-25 02:26:58:090 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell dumpsys window'

#设备API版本22
2019-02-25 02:26:58:141 [ADB] Device API level: 22

#启动设备上的雪球APP
2019-02-25 02:26:58:142 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell am start -W -n com.xueqiu.android/.view.WelcomeActivityAlias -S -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000'

#把设备上的雪球APP进程kill
2019-02-25 02:28:40:068 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell am force-stop com.xueqiu.android'

#点击到主页
2019-02-25 02:28:41:301 [ADB] Pressing the HOME button

#怎么点击到主页—>3=KEYCODE_HOME"
2019-02-25 02:28:41:302 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell input keyevent 3'

#尝试杀掉所有uiautomator的进程
2019-02-25 02:28:41:978 [ADB] Attempting to kill all uiautomator processes

#正在获取所有uiautomator进程ID
2019-02-25 02:28:41:979 [ADB] Getting IDs of all 'uiautomator' processes

#怎么获取所有uiautomator进程,命令:adb shell pidof uiautomator
2019-02-25 02:28:41:979 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell pidof uiautomator'

#没有找到uiautomator的进程
2019-02-25 02:28:42:026 [ADB] No 'uiautomator' process has been found

#强制停止io.appium.unlock'
2019-02-25 02:28:42:031 [ADB] Running '/Users/Wangjr/Library/Android/sdk/platform-tools/adb -P 5037 -s 022MWW146R006173 shell am force-stop io.appium.unlock'

作业3:

PS作业中遇到的问题:同时使用unittest与pytest的参数化,启动app会崩溃

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import pytest
from time import sleep
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction

class Test_Xueqiu:

@pytest.fixture(scope="function",autouse=True)
def kaishi(self):
# print("setUp")
caps = {}
caps["platformName"] = "android"
caps["deviceName"] = "192.168.56.103:5555"
caps["appPackage"] = "com.xueqiu.android"
caps["appActivity"] = ".view.WelcomeActivityAlias"
caps["autoGrantPermissions"] = "true"
caps["unicodeKeyboard"] = "true"
self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
self.driver.implicitly_wait(10)

def loaded(self):
sleep(10)
self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()

def test_add_us(self):
self.loaded()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys("pdd")
self.driver.find_element_by_id("follow_btn").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_id("action_close").click()
self.driver.find_element_by_id("iv_close").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()
sleep(1)
assert "拼多多"==self.driver.find_element_by_xpath("//*[@text='拼多多']").text
def test_delete_us(self):
self.loaded()
self.driver.find_element_by_xpath("//*[@text='美股']").click()

element = self.driver.find_element_by_xpath("//*[@text='拼多多']")
TouchAction(self.driver).long_press(element).perform()
self.driver.find_element_by_xpath("//*[@text='删除']").click()
# assert self.driver.find_element_by_xpath("//*[@text='拼多多']")

@pytest.mark.parametrize("is_leap", [
"1", "2", "3", "4", "5"
"6", "7", "8", "9", "10"
"11", "12", "13", "14", "15"
"16", "17", "18", "19", "20"
"21", "22", "23", "24", "25"
"26", "27", "28", "29", "30"
])
def test_add_batch(self, is_leap):
# 参数化添加30只股票

self.loaded()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys(is_leap)
self.driver.find_element_by_id("follow_btn").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_id("action_close").click()

@pytest.mark.parametrize("meigu",["pdd","apple","bidu","jd","yrd","LC","baba","googl","fb","amzn"])
def test_add_ten(self,meigu):
self.test_add_batch(meigu)

def test_exist_in_all(self):
#添加10只美股,当全部股票大于2页的时候断言某个股票同时存在于“美股”与“全部”分类中
self.loaded()
self.driver.find_element_by_xpath("//*[@text='美股']").click()
assert self.driver.find_element_by_xpath("//*[@text='百度']").text=="百度"
self.driver.find_element_by_xpath("//*[@text='全部']").click()
i=0
while i<3:
try:
self.driver.find_element_by_xpath("//*[@text='百度']")

break
except:
self.driver.swipe(564.5, 1905.3, 377, 1070)
i+=1
守护 回复

add_1st = (By.XPATH, "//*[contains(@resource-id,'follow_btn') and @instance=9]") # 每个搜索的第一只股票
@instance=9 是哪里得到的呀?

于静 回复

appium desktop查看控件信息

作业4:
问题: http相关,-->POST 是谁给谁发送请求呢,看日志只是大概看个明白了,但是真正的原理还没弄明白 ,老师可以再说下appium的设计原理 那个图吗

# 提取所有adb相关的命令
awk '$3=="[ADB]"' appium0227.log >adb.log

# 检查adb是否存在
2019-02-27 15:11:49:219 [ADB] Checking whether adb is present

# '在Dsdk目录下找到29build-tools文件夹
2019-02-27 15:11:49:225 [ADB] Found 29 'build-tools' folders under 'D:\android\android-sdk-windows' (newest first):
2019-02-27 15:11:49:225 [ADB] D:/android/android-sdk-windows/build-tools/28.0.3
2019-02-27 15:11:49:225 [ADB] D:/android/android-sdk-windows/build-tools/28.0.2

# 使用sdk目录下的adb执行程序
2019-02-27 15:11:49:230 [ADB] Using adb.exe from D:\android\android-sdk-windows\platform-tools\adb.exe

# 尝试找到一个连接的android设备
2019-02-27 15:11:49:230 [ADB] Trying to find a connected android device

# 获取连接设备
2019-02-27 15:11:49:231 [ADB] Getting connected devices...

# 1个设备已连接
2019-02-27 15:11:49:258 [ADB] 1 device(s) connected
# 设置设备id
2019-02-27 15:11:49:260 [ADB] Setting device id to GWY0217207001917

# 获取安卓设备系统 api 版本(通过端口 5037),并输出api版本号
2019-02-27 15:11:49:261 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell getprop ro.build.version.sdk'
2019-02-27 15:11:49:336 [ADB] Current device property 'ro.build.version.sdk': 26
2019-02-27 15:11:49:336 [ADB] Device API level: 26

# 查看当前设备上是否安装了雪球app
2019-02-27 15:11:49:337 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell pm list packages com.xueqiu.android'
# 等待设备可用
2019-02-27 15:11:49:854 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 wait-for-device'
# 检查命令可执行
2019-02-27 15:11:49:882 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell echo ping'
# 检查appium是否安装
2019-02-27 15:11:49:932 [ADB] Getting install status for io.appium.settings


# 运行 adb shell dumpsys 命令获取包的安装状态
# io.appium.settings 已安装
2019-02-27 15:11:49:932 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell dumpsys package io.appium.settings'
2019-02-27 15:11:50:017 [ADB] 'io.appium.settings' is installed

# 获取io.appium.settings 包的信息
2019-02-27 15:11:50:018 [ADB] Getting package info for 'io.appium.settings'
# 通过命令shell dumpsys package io.appium.settings获取
2019-02-27 15:11:50:018 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell dumpsys package io.appium.settings'
# 检查aapt是否存在
2019-02-27 15:11:50:082 [ADB] Checking whether aapt is present
# 应用文件下的aapt命令执行
2019-02-27 15:11:50:083 [ADB] Using aapt.exe from D:\android\android-sdk-windows\build-tools\28.0.3\aapt.exe

# io.appium.settings版本信息符合要求
2019-02-27 15:11:50:099 [ADB] The version name of the installed 'io.appium.settings' is greater or equal to the application version name ('2.11.0' >= '2.11.0')
# 不需要重新安装或升级 io.appium.settings
2019-02-27 15:11:50:099 [ADB] There is no need to install/upgrade 'C:\Users\21422\AppData\Roaming\npm\node_modules\appium\node_modules\io.appium.settings\apks\settings_apk-debug.apk'

# 查看所有的进程状态
2019-02-27 15:11:50:100 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell ps'
2019-02-27 15:11:50:211 [ADB] Device API level: 26

# 给与io.appium.settings权限
2019-02-27 15:11:50:211 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell appops set io.appium.settings android\:mock_location allow'

# 获取系统默认输入法
2019-02-27 15:11:50:332 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell settings get secure default_input_method'

# 激活系统安装时的输入法
2019-02-27 15:11:50:400 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell ime enable io.appium.settings/.UnicodeIME'

# 设置appium输入法位系统安装时的输入法
2019-02-27 15:11:50:782 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell ime set io.appium.settings/.UnicodeIME'

# 获取设备平台版本
2019-02-27 15:11:51:146 [ADB] Getting device platform version

# 获取设备的android系统版本 版本是8.0.0
2019-02-27 15:11:51:146 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell getprop ro.build.version.release'
2019-02-27 15:11:51:184 [ADB] Current device property 'ro.build.version.release': 8.0.0

# 获取设备的屏幕尺寸
2019-02-27 15:11:51:185 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell wm size'

# 获取设备型号 MHA-AL00
2019-02-27 15:11:51:551 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell getprop ro.product.model'
2019-02-27 15:11:51:604 [ADB] Current device property 'ro.product.model': MHA-AL00

# 获取设备生产厂商 华为
2019-02-27 15:11:51:604 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell getprop ro.product.manufacturer'
2019-02-27 15:11:51:653 [ADB] Current device property 'ro.product.manufacturer': HUAWEI

# 获取雪球app安装状态
2019-02-27 15:11:51:654 [ADB] Getting install status for com.xueqiu.android
# 运行 adb shell dumpsys 命令获取包的安装状态
2019-02-27 15:11:51:654 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell dumpsys package com.xueqiu.android'
# 雪球已安装
2019-02-27 15:11:51:714 [ADB] 'com.xueqiu.android' is installed

# 停止雪球应用
2019-02-27 15:11:51:714 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell am force-stop com.xueqiu.android'

# 清除雪球应该数据
2019-02-27 15:11:51:881 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell pm clear com.xueqiu.android'
2019-02-27 15:11:52:310 [ADB] Device API level: 26
2019-02-27 15:11:52:310 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell dumpsys package com.xueqiu.android'

# 检索请求权限
2019-02-27 15:11:52:383 [ADB] Retrieving requested permissions
# 检索到34个权限
2019-02-27 15:11:52:384 [ADB] Retrieved 34 permission(s) from ["requested"] group(s)
# 检索已授予权限
2019-02-27 15:11:52:384 [ADB] Retrieving granted permissions
# 检索到12个权限
2019-02-27 15:11:52:385 [ADB] Retrieved 12 permission(s) from ["install","runtime"] group(s)
# 已授予雪球权限:
2019-02-27 15:11:52:385 [ADB] Granting permissions ["android.permission.WRITE_EXTERNAL_STORAGE","android.permission.READ_PHONE_STATE","android.permission.ACCESS_FINE_LOCATION","android.permission.ACCESS_COARSE_LOCATION","android.permission.READ_EXTERNAL_STORAGE","android.permission.RECORD_AUDIO","android.permission.CAMERA","android.permission.REQUEST_INSTALL_PACKAGES","android.permission.MOUNT_UNMOUNT_FILESYSTEMS","android.permission.CALL_PHONE"] to 'com.xueqiu.android'
# 分别给予这些权限pm ---pm表示Package Manager , 可以用获取到一些安装在 Android 设备上得应用信息)
2019-02-27 15:11:52:385 [ADB] Got the following command chunks to execute: [["pm","grant","com.xueqiu.android","android.permission.WRITE_EXTERNAL_STORAGE",";","pm","grant","com.xueqiu.android","android.permission.READ_PHONE_STATE",";","pm","grant","com.xueqiu.android","android.permission.ACCESS_FINE_LOCATION",";","pm","grant","com.xueqiu.android","android.permission.ACCESS_COARSE_LOCATION",";","pm","grant","com.xueqiu.android","android.permission.READ_EXTERNAL_STORAGE",";","pm","grant","com.xueqiu.android","android.permission.RECORD_AUDIO",";","pm","grant","com.xueqiu.android","android.permission.CAMERA",";","pm","grant","com.xueqiu.android","android.permission.REQUEST_INSTALL_PACKAGES",";","pm","grant","com.xueqiu.android","android.permission.MOUNT_UNMOUNT_FILESYSTEMS",";","pm","grant","com.xueqiu.android","android.permission.CALL_PHONE",";"]]
#
2019-02-27 15:11:52:385 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell pm grant com.xueqiu.android android.permission.WRITE_EXTERNAL_STORAGE \; pm grant com.xueqiu.android android.permission.READ_PHONE_STATE \; pm grant com.xueqiu.android android.permission.ACCESS_FINE_LOCATION \; pm grant com.xueqiu.android android.permission.ACCESS_COARSE_LOCATION \; pm grant com.xueqiu.android android.permission.READ_EXTERNAL_STORAGE \; pm grant com.xueqiu.android android.permission.RECORD_AUDIO \; pm grant com.xueqiu.android android.permission.CAMERA \; pm grant com.xueqiu.android android.permission.REQUEST_INSTALL_PACKAGES \; pm grant com.xueqiu.android android.permission.MOUNT_UNMOUNT_FILESYSTEMS \; pm grant com.xueqiu.android android.permission.CALL_PHONE \;'


# 正在将 uiautomator2 server 4724 端口映射到电脑中
# 重定向tcp端口(由于使用的默认端口,这里实际没有变化)
2019-02-27 15:11:55:661 [ADB] Forwarding system: 4724 to device: 4724
2019-02-27 15:11:55:662 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 forward tcp\:4724 tcp\:4724'

# AppiumBootstrap.jar 传到安卓设备中
2019-02-27 15:11:55:688 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 push C\:\\Users\\21422\\AppData\\Roaming\\npm\\node_modules\\appium\\node_modules\\appium-android-driver\\bootstrap\\bin\\AppiumBootstrap.jar /data/local/tmp/'

# 正在试图杀死所有的uiautomator进程
2019-02-27 15:11:55:732 [ADB] Attempting to kill all uiautomator processes
# 正在获取所有uiautomator的进程
2019-02-27 15:11:55:732 [ADB] Getting all processes with uiautomator

# 输出所有进程 ps表示进程
2019-02-27 15:11:55:732 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell ps'
# 没找到uiautomator 进程
2019-02-27 15:11:55:856 [ADB] No 'uiautomator' process has been found

# 创建adb子进程
2019-02-27 15:11:55:856 [ADB] Creating ADB subprocess with args: ["-P",5037,"-s","GWY0217207001917","shell","uiautomator","runtest","AppiumBootstrap.jar","-c","io.appium.android.bootstrap.Bootstrap","-e","pkg","com.xueqiu.android","-e","disableAndroidWatchers",false,"-e","acceptSslCerts",false]

# 此处是appium用来判断是否锁屏的,检查返回的mShowingLockscreenmShowingLockscreen=true,锁屏,需要解锁)
2019-02-27 15:11:56:319 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell dumpsys window'
2019-02-27 15:11:56:383 [ADB] Device API level: 26

# 启动雪球APP
2019-02-27 15:11:56:384 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell am start -W -n com.xueqiu.android/.view.WelcomeActivityAlias -S -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000'

# 恢复手机输入法为百度输入法
2019-02-27 15:12:37:628 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell ime set com.baidu.input_huawei/.ImeService'

# 停止雪球应用
2019-02-27 15:12:38:035 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell am force-stop com.xueqiu.android'

# 按下home keyevent指的是android对应的keycode,比如home键的keycode=3back键的keycode=4.
2019-02-27 15:12:38:170 [ADB] Pressing the HOME button
2019-02-27 15:12:38:171 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell input keyevent 3'

# 正在试图杀死所有的uiautomator进程
# 获取所有uiautomator的进程
# 输出所有进程 ps表示进程
# 没找到uiautomator 进程
2019-02-27 15:12:38:586 [ADB] Attempting to kill all uiautomator processes
2019-02-27 15:12:38:586 [ADB] Getting all processes with uiautomator
2019-02-27 15:12:38:586 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell ps'
2019-02-27 15:12:38:692 [ADB] No 'uiautomator' process has been found

# 强制关闭unlock App
2019-02-27 15:12:38:696 [ADB] Running 'D:\android\android-sdk-windows\platform-tools\adb.exe -P 5037 -s GWY0217207001917 shell am force-stop io.appium.unlock'

作业三

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
import pytest

class TestXueqiuDemo(object):

@pytest.fixture(scope="function", autouse=True)
def setUp(self):
caps = {}
caps['platformName']='android'
caps['deviceName']='Samsung Galaxy S7'
caps['appPackage']='com.xueqiu.android'
caps['appActivity']='.view.WelcomeActivityAlias'
caps['autoGrantPermissions']=True

self.driver = webdriver.Remote('HTTP://localhost:4723/wd/hub',caps)
self.driver.implicitly_wait(10)
def loaded(self):
locations = ["x", "y"]
while locations[-1] != locations[-2]:
element = self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
locations.append(element.location)
print(locations)
def test_add_us(self):
self.loaded()
self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys("pdd")

if len(self.driver.find_elements_by_id("follow_btn")) > 0:
self.driver.find_element_by_id("follow_btn").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_id("action_close").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()

assert 1 == len(self.driver.find_elements_by_xpath(
"//*[contains(@resource-id, 'portfolio_stockName') and @text='拼多多']"))
def test_delete_us(self):
self.loaded()
self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
element = self.driver.find_element_by_xpath("//*[contains(@resource-id, 'portfolio_stockName') and @text='拼多多']")
TouchAction(self.driver).long_press(element).perform()
self.driver.find_element_by_xpath("//*[@text='删除']").click()
assert 0 == len(self.driver.find_elements_by_xpath(
"//*[contains(@resource-id, 'portfolio_stockName') and @text='拼多多']"))
@pytest.mark.parametrize("name", [
("pdd"),("bd"),("ymx"),("jd"),("blbl"),
("dzcc"),("albb"),("oppo"),("dzdp"),("xdf"),
("sg"),("wy"),("zsyh"),("gldq"),("sh"),("wy"),
("byd"),("dfcf"),("zzyh"),("zgpa"),("dftx"),
("zgrb"),("zxzq"),("zghd"),("jsrj"),("lczg")
])
def test_add_batch(self,name):
self.loaded()
self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys(name)
if len(self.driver.find_elements_by_id("follow_btn")) > 0:
self.driver.find_element_by_id("follow_btn").click()
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
self.driver.find_element_by_id("action_close").click()
def test_exist_in_all(self):
self.loaded()
self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()
isvisale = True
while isvisale:
try:
self.driver.find_element_by_xpath("//*[contains(@resource-id, 'portfolio_stockName') and @text='拼多多']")
self.driver.find_element_by_xpath("//*[@text='全部']").click()
isvisable_all = True
while isvisable_all:
try:
self.driver.find_element_by_xpath(
"//*[contains(@resource-id, 'portfolio_stockName') and @text='拼多多']")
except:
self.driver.swipe(start_x=695, start_y=2238, end_x=695, end_y=575,duration=1000)
isvisable_all = True
else:
isvisable_all = False

except:
self.driver.swipe(start_x=695, start_y=2238, end_x=695, end_y=575,duration=1000)
isvisale = True
else:
isvisale = False

手机耗电量,结果{'level': 1, 'state': 5} ,是什么意思??谷歌没找到答案,问问大家有知道的么?

作业三

3.1

def loaded(self):
list1 = ["x", "y"]
while list1[-2] != list1[-1]:
list1.append(self.driver.find_element_by_xpath
("//*[contains(@resource-id, 'tab_name') and @text='自选']").location)

def test_add_us(self):
self.loaded()
self.driver.find_element_by_xpath("//*[contains(@resource-id, 'tab_name') and @text='自选']").click()
self.driver.find_element_by_xpath("//android.widget.TextView[@text='美股']").click()
self.driver.find_element_by_id("recommend_name_one").click()
self.driver.find_element_by_id("//android.widget.ImageView[contains(@resource-id, 'floating_action_image_view_id')]/following::android.widget.TextView[@text='加自选']")
try:
self.driver.find_element_by_id("md_buttonDefaultNegative").click()
except Exception as e:
print(e)

3.2

def test_delete_us(self):
self.loaded()
self.driver.find_element_by_xpath("//*[contains(@resource-id, 'indicator')]//*[@text='美股']").click()
TouchAction(self.driver).long_press(self.driver.find_element_by_id("portfolio_whole_item")).perform()
self.driver.find_element_by_xpath("//*[@text='删除']").clcik()
assert 1 == len(self.driver.find_elements_by_id("recommend_name_one"))
self.driver.find_element_by_xpath("//*[contains(@resource-id, 'indicator')]//*[@text='全部']").click()
assert 1 == len(self.driver.find_elements_by_id("recommend_name_one"))

3.3

@pytest.mark.parametrize('keyword', ['阿里巴巴', '中国人寿', '百度'])
def test_add_batch(self, keyword):
self.loaded()
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]"
).click()
self.driver.find_element_by_id("action_create_cube").click()
self.driver.find_element_by_id("search_input_text").send_keys(keyword)
before = self.driver.find_element_by_id("add_attention"). \
find_element_by_class_name("android.widget.TextView").get_attribute("resourceId")
if before == "com.xueqiu.android:id/follow_btn":
self.driver.find_element_by_id("follow_btn").click()
try:
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()
except Exception as e:
print(e)
assert before != self.driver.find_element_by_id("add_attention"). \
find_element_by_class_name("android.widget.TextView").get_attribute("resourceId")

3.4

def search(self, text):
list1 = ["x", "y"]
mark = 0
while (list1[-2] != list1[-1]) & (mark != 1):
list2 = self.driver.find_elements_by_id("portfolio_stockName")
list1.append(list2[-1].text)
for i in list2:
if i.text == text:
mark = 1
self.driver.swipe(start_x=500, start_y=900, end_x=500, end_y=300, duration=1000)
assert mark == 1

def test_exist_in_all(self):
self.loaded()
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]"
).click()
self.search("中国人寿")
self.driver.find_element_by_xpath("//*[contains(@resource-id,'indicator')]//*[@text='美股']").click()
self.search("中国人寿")

作业3

# 添加一只美股,判断是否添加成功 test_add_us
# 然后删除一只美股,判断删除成功 test_delete_us

#方法封装 ,进入自选
def loaded_zixuan(self):
locations = ["x", "y"]
while locations[-1] != locations[-2]:
element = self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]")
locations.append(element.location)

def test_add_us(self):
self.loaded_zixuan()
self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()
if len(self.driver.find_elements_by_id("add_to_portfolio_stock")) > 0:
self.driver.find_element_by_xpath(
"//*[@selected='true' and contains(@resource-id, 'recommend_select_two')]").click()
self.driver.find_element_by_xpath(
"//*[@selected='true' and contains(@resource-id, 'recommend_select_three')]").click()
self.driver.find_element_by_xpath(
"//*[@selected='true' and contains(@resource-id, 'recommend_select_four')]").click()
self.driver.find_element_by_xpath(
"//*[@selected='true' and contains(@resource-id, 'recommend_select_five')]").click()
self.driver.find_element_by_xpath(
"//*[@selected='true' and contains(@resource-id, 'recommend_select_six')]").click()

self.driver.find_element_by_id("add_to_portfolio_stock").click()

assert 1 == len(self.driver.find_elements_by_id("portfolio_stockName"))


# 定位到元素,长按点击删除
element = self.driver.find_element_by_id("portfolio_stockName")
TouchAction(self.driver).long_press(element, None, None, 10000).perform()

self.driver.find_element_by_xpath("//*[@text='删除' and contains(@resource-id, 'md_title')]").click()
assert 1 == len(self.driver.find_elements_by_id("add_to_portfolio_stock"))

作业三

import pytest
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction

STOCKS = [
"百度", "阿里巴巴", "腾讯", "美团", "今日头条",
"拼多多", "饿了么", "京东", "滴滴出行", "中国平安",
"中国联通", "中国移动", "Facebook", "Google", "大疆",
"雅虎", "微软", "高通", "小米", "格力",
"oppo", "vivo手机", "苹果", "美的", "恒大",
"蚂蚁金服", "网易", "陌陌", "中国人保", "京东方"
]


class TestXueqiu:
@pytest.fixture(scope="function", autouse=True)
def base_config(self):
caps = {}
caps["platformName"] = "Android"
caps["deviceName"] = "huawei"
caps["appActivity"] = ".view.WelcomeActivityAlias"
caps["noReset"] = True
caps["appPackage"] = "com.xueqiu.android"
caps["autoGrantPermissions"] = True
caps["unicodeKeyboard"] = True
caps["resetKeyboard"] = True

self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
self.driver.implicitly_wait(6)

def add_stock(self, stockName):
'''
添加股票
:return:
'''
self.driver.find_element_by_id("tv_search").click()
self.driver.find_element_by_id(
"search_input_text").send_keys(stockName)
if len(self.driver.find_elements_by_id("follow_btn")):
self.driver.find_element_by_id("follow_btn").click()

def find_stock(self, stockName):
'''
递归查找股票
:param stockName: 股票名
:return:
'''
screen_width = self.driver.get_window_size()["width"]
screen_height = self.driver.get_window_size()["height"]
stocks = self.driver.find_elements_by_id("portfolio_stockName")
stocklist = []
for stock in stocks:
stocklist.append(stock.text)
if stockName in stocklist:
return stockName
else:
self.driver.swipe(
1 / 2 * screen_width,
1 / 2 * screen_height,
1 / 2 * screen_width,
1 / 7 * screen_height,
duration=1000)
return self.find_stock(stockName)

def test_add_us(self):
'''
添加一只美股,判断是否添加成功
:return:
'''
self.add_stock("汽车之家")
self.driver.find_element_by_id("action_close").click()
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()
assert self.driver.find_elements_by_xpath("//*[@text='汽车之家']")

def test_delete_us(self):
'''
然后删除一只美股,判断删除成功
:return:
'''
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
self.driver.find_element_by_xpath("//*[@text='美股']").click()
element = self.driver.find_element_by_xpath("//*[@text='汽车之家']")
if element:
TouchAction(self.driver).long_press(element).perform()
self.driver.find_element_by_xpath("//*[@text='删除']").click()
assert 0 == len(
self.driver.find_elements_by_xpath("//*[@text='汽车之家']"))

@pytest.mark.parametrize("stocks", STOCKS)
def test_add_batch(self, stocks):
'''
利用参数化或者数据驱动添加30只股票
:param stocks:
:return:
'''
self.add_stock(stocks)

def test_exist_in_all(self):
'''
当全部股票大于2页的时候断言某个股票同时存在于“美股”与“全部”分类中
:return:
'''
self.driver.find_element_by_xpath(
"//*[@text='自选' and contains(@resource-id, 'tab_name')]").click()
tag_stock = "百度"
in_all_bar = self.find_stock(tag_stock)
self.driver.find_element_by_xpath("//*[@text='美股']").click()
in_us_bar = self.find_stock(tag_stock)
assert in_all_bar and in_us_bar

作业 3(下)
from appium import webdriver
from appium.webdriver import WebElement
from selenium.common.exceptions import NoSuchElementException
import pytest


def find(tag: str, value: str) -> WebElement:
if driver.find_element_by_id('content').location['x'] > 7:
driver.find_element_by_id('md_buttonDefaultNegative').click()
if tag.lower() == "id":
return driver.find_element_by_id(value)
elif tag.lower() == "xpath":
return driver.find_element_by_xpath(value)


def switch_select():
for i in range(7):
del i
if find("xpath", '//*[@text="自选"]/..').location['y'] > 777:
find("xpath", '//*[@text="自选"]/..').click()
break


def swipe_up():
size = driver.get_window_size()
driver.swipe(size['width'] / 2, size['height'] / 4 * 3,
size['width'] / 2, size['height'] / 4, )


def swipe_down():
size = driver.get_window_size()
driver.swipe(size['width'] / 2, size['height'] / 4,
size['width'] / 2, size['height'] / 4 * 3, )


@pytest.fixture(scope="module")
def test_start_stop():
desired_caps = {
"platformName": "Android",
"deviceName": "phone",
"app": "D:\\com.xueqiu.android_11.15_200.apk",
"appPackage": "com.xueqiu.android",
"appActivity": ".view.WelcomeActivityAlias",
"autoGrantPermissions": True,
"unicodeKeyboard": True,
"resetKeyboard": True,
}
global driver
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
driver.implicitly_wait(3)
yield
driver.quit()


@pytest.fixture(scope="module")
def test_search_stock(test_start_stop):
switch_select()
find("id", 'action_create_cube').click()
yield
find("id", 'action_close').click()


@pytest.mark.parametrize('stock_name', [
'谷歌C', '谷歌A', '阿里巴巴', '阿里健康', '阿里影业', '腾讯控股',
'腾讯音乐', '苹果', '亚马逊', '微软', '京东', '特斯拉', '哔哩哔哩',
'拼多多', '百事', '好时', '可口可乐', '沃尔玛', '汽车之家'
])
def test_add_batch(test_search_stock, stock_name):
find("id", "search_input_text").send_keys(stock_name)
try:
find("xpath", '//*[contains(@resource-id, "item_con")]/android.widget.RelativeLayout[1]'
'//*[contains(@resource-id, "follow_")]').click()
except NoSuchElementException:
print('stock has been added')
find("id", "search_input_text").clear()


def test_exist_in_all(test_start_stop):
switch_select()
last_name = driver.find_elements_by_id('portfolio_stockName')[-1].text
for x in range(5): swipe_up()
if len(driver.find_elements_by_xpath(f'//*[@text={last_name}]')) == 0:
find("xpath", '//*[@text="美股"]').click()
assert find("xpath", '//*[@text="阿里巴巴"]').is_displayed()
find("xpath", '//*[@text="全部"]').click()
for y in range(5):
if find("id", 'container_view').location['x'] == 0:
for z in range(5): swipe_down()
assert find("xpath", '//*[@text="阿里巴巴"]').is_displayed()
return
assert 0

welephant 回复

不要作为职业发展主方向。测试的重心仍然是围绕基础的用户体验、业务逻辑、代码质量。大数据测试、AI测试和白盒测试、精准化测试很像,不过是专题测试中的一个分支而已。地位并没有特别的高。在阿里以及其他的大公司里的确也存在独立的大数据测试团队,但是最后的发展都不理想。

Jared_YJ 回复
  • beforeClass只会执行一次。所以不判空也是可以的
  • findElement尽量使用比较有明确指向的定位符,可以让别人看懂
  • 滑动封装思路不错
  • sleep尽量少用,使用显式等待或者隐式等待,默认隐式等待6-10s,超过阈值的使用显式等待
  • xpath定位可以再进一步封装,今天会讲
  • 判断元素等待,今天也会将改进方法
作业2

def test_alibaba_search(self):
WebDriverWait(self.driver, 10,0.5).until(
lambda x: x.find_element_by_xpath("//*[@text='自选' and contains(@resource-id,'tab_name')]"))

local=[]
for i in range(1, 5):
element = self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id,'tab_name')]")
print(element.location)
local.append(element.location)
print(element.get_attribute("text"))

if local[-1]== local[-2]:

self.driver.find_element_by_xpath("//*[@text='自选' and contains(@resource-id,'tab_name')]").click()

# 点击搜索
self.driver.find_element_by_id("action_create_cube").click()


# 点击搜索阿里巴巴
WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_id("search_input_text"))
self.driver.find_element_by_id("search_input_text").send_keys("阿里巴巴")

befor = self.driver.find_element_by_id("add_attention") \
.find_element_by_class_name("android.widget.TextView") \
.get_attribute("resourceId")

if befor=="com.xueqiu.android:id/follow_btn":
self.driver.find_element_by_id("follow_btn").click()

after=self.driver.find_element_by_id("add_attention") \
.find_element_by_class_name("android.widget.TextView") \
.get_attribute("resourceId")
self.driver.find_element_by_xpath("//*[@text='下次再说']").click()

assert befor != after

#点击取消按钮
self.driver.find_element_by_id("action_close").click()

self.driver.find_element_by_id("portfolio_whole_item").\
find_element_by_id("portfolio_stockName").\
get_attribute("text") == "阿里巴巴"


panfeng 回复
  • 元素定位直到进行封装非常不错,已经接近po的思想了
  • 弹框的封装还不够优雅
  • 自选的等待需要封装
  • 尽量避免使用绝对路径
守护 回复
  • find element返回的是element,不是boolean
  • 白名单的思路处理还是对的,但是实现方式不够优雅
50Floor has been deleted
cookie 回复

ANDROID_HOME需要在appium启动之前设置。appium desktop需要你关闭掉所有的命令行进程再启动才会生效。

MacBook-Pro-2:appium seveniruby$ grep aapt appium.log
2018-03-04 13:40:27:083 - info: [ADB] Checking whether aapt is present
2018-03-04 13:40:27:085 - info: [ADB] Using aapt from /usr/local/opt/android-sdk/build-tools/27.0.3/aapt
2018-03-04 13:40:28:100 - info: [ADB] Checking whether aapt is present
2018-03-04 13:40:28:102 - info: [ADB] Using aapt from /usr/local/opt/android-sdk/build-tools/27.0.3/aapt
木头 回复
  • sleep不推荐使用
  • 适当封装提升代码可读性
国风 回复

pytest兼容unittest,但是运行的时候unittest无法解析pytest。尽量使用相同的体系,完全采用pytest或者完全采用unitest

54Floor has been deleted
于静 回复

instance是表示一个元素在一个界面中相同class的元素里排行第多少个,从0开始计数。如果界面存在弹框,可能会让instance发生变化。

Set the search criteria to match the widget by its instance number. The instance value must be 0 or greater, where the first instance is 0. For example, to simulate a user click on the third image that is enabled in a UI screen, you could specify a a search criteria where the instance is 2, the className(String) matches the image widget class, and enabled(boolean) is true. The code would look like this: new UiSelector().className("android.widget.ImageView") .enabled(true).instance(2);
小九 回复

更细节的分析以后的课程会讲

test-h 回复
  • 适当封装代码逻辑,减少用例中代码逻辑成分
  • 不要使用绝对坐标,改成百分比
小九 回复

待查api,这个结果的确跟以前不一样了。

Author only
60Floor has been deleted
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up