其实Appium自动化测试的原理,不仅仅可以用于做自动化测试,实际上还可以用于更多的app操作,用来完成一些重复性的动作,比如,如果开了一个网店,就需要往店铺里上传一些商品信息,可实际上上传商品是非常重复的操作,上传图片,填写商品信息,再保存,再上传下一个商品....利用appium+python,可以实现这一系列的操作,轻松无压力。
编写代码前的准备工作,和前面的appium自动化测试相差无几。另外,需要将产品信息事前编辑好,并保存在csv文件中。将产品图片拷贝到设备中,分文件夹保存(一个文件夹最好只存一个产品的图片,以数字命名),与csv中的产品信息一一对应。此外,可以按照appium自动化测试的框架来编写代码,思路清晰明确。
以下代码展示的是上传商品的具体操作,此外可以自己添加一些辅助功能(可以添加在common_Fun里,参考之前的代码),例如打开APP时,检测有没有登录好账号(没有就登录账号,因为上传是需要登录的),关闭升级弹窗,关闭广告等等。
from common.desired_caps import appium_desired, logger
from common.common_Fun import Common,By
from selenium.common.exceptions import NoSuchElementException
from time import sleep
import csv
class UploadView(Common):
#主菜单按钮
mainmenu_Btn=(By.ID, 'com.xunmeng.merchant:id/tv_tab')
#弹窗通知关闭按钮
pop_close=(By.CLASS_NAME,'android.widget.Image')
#商品界面的元素
issue_Btn = (By.XPATH,'//*[@class="android.view.View" and @text="发布商品"]') #发布商品按钮
#发布界面元素
input_Box1 = (By.XPATH, '//*[@class="android.widget.EditText" and @index="1"]') #商品标题输入框
input_Box2 = (By.XPATH, '//*[@class="android.widget.EditText" and @index="2"]') #拼单价输入框
input_Box3 = (By.XPATH, '//*[@class="android.widget.EditText" and @index="5"]') #单买价输入框
input_Box4 = (By.XPATH, '//*[@class="android.widget.EditText" and @index="0"]') #库存输入框
image_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="商品图"]') #选择商品图片按钮
property_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="所有属性"]') #所有属性按钮
create_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="创建"]') #创建按钮
#所有属性页面相关元素
people_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="适用人群"]')
height_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="鞋帮高度"]')
bottom_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="鞋底材质"]')
top_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="鞋面材质"]')
tie_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="闭合方式"]')
save_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="保存"]')
#相册选择的元素
photo_album = (By.XPATH, '//*[@class="android.view.View" and @text="相册"]') #相册方式
allpic_Btn = (By.ID, 'com.xunmeng.merchant:id/mTvTitle') #全部照片
#照片的元素
photo = (By.ID, 'com.xunmeng.merchant:id/iv_unchecked') #相册里的照片
apply_Btn = (By.ID, 'com.xunmeng.merchant:id/button_apply') #确认上传图片按钮
continue_Btn = (By.XPATH, '//*[@class="android.view.View" and @text="继续添加新商品"]')
#商品信息
info_file = '../data/product_info.csv'
with open(info_file, 'r', encoding='gbk') as file:
data = csv.reader(file)
a = list(data)
#关闭弹窗广告
def close_ad(self):
try:
pop_ad=self.find_Element(*self.pop_close)
except NoSuchElementException:
logger.info('no pop ad')
else:
pop_ad.click()
#上传图片
def upload_pic(self,m):
logger.info('choose pic and upload')
self.find_Element(*self.image_Btn).click()
self.find_Element(*self.photo_album).click()
self.find_Element(*self.allpic_Btn).click()
sleep(2)
self.driver.find_element_by_xpath(f'//*[@text="{m}"]').click()
sleep(3)
#用下面的XPATH参数便找不到对应的元素,可能不能用元素id做参数
# self.driver.find_element_by_xpath(f'//*[@id="com.xunmeng.merchant:id/album_name" and @text="{m}"]').click()
photo_list = self.find_Elements(*self.photo)
for pic in photo_list:
pic.click()
self.find_Element(*self.apply_Btn).click()
logger.info('pic upload ok')
#上传商品标题以及库存信息等
def upload_textinfo(self,n):
text_info=self.get_csv_data(self.info_file,n)
sleep(1)
self.find_Element(*self.input_Box1).click()
self.find_Element(*self.input_Box1).send_keys(text_info[0]) #商品名称
sleep(0.5)
self.find_Element(*self.input_Box2).click()
self.find_Element(*self.input_Box2).send_keys(text_info[4]) #拼单价
self.find_Element(*self.input_Box3).click()
self.find_Element(*self.input_Box3).clear()
self.find_Element(*self.input_Box3).send_keys(text_info[5]) #单买价
self.find_Element(*self.input_Box4).click()
self.find_Element(*self.input_Box4).send_keys(text_info[6]) #库存
self.find_Element(*self.property_Btn).click() #进入所有属性
self.find_Element(*self.people_Btn).click() #进入适用人群
self.driver.find_element_by_xpath(f'//*[@class="android.view.View" and @text="{text_info[8]}"]').click()
self.find_Element(*self.height_Btn).click() #进入鞋帮高度
self.driver.find_element_by_xpath(f'//*[@class="android.view.View" and @text="{text_info[9]}"]').click()
self.find_Element(*self.tie_Btn).click() #进入闭合方式
self.driver.find_element_by_xpath(f'//*[@class="android.view.View" and @text="{text_info[13]}"]').click()
self.find_Element(*self.save_Btn).click() #保存
def upload(self):
self.find_Elements(*self.mainmenu_Btn)[0].click()
sleep(1)
self.tap(106,660)
sleep(2)
self.close_ad()
self.find_Element(*self.issue_Btn).click()
#开始上传
logger.info('============start upload==============')
#在这里用循环的方式,依次上传文字信息和图片
for i in range(3,len(self.a)+1):
self.upload_textinfo(i)
self.swipe_down()
self.upload_pic(i-2)
self.find_Element(*self.create_Btn).click()
sleep(2)
if i == len(self.a):
logger.info('Upload Done!')
else:
self.find_Element(*self.continue_Btn).click()
sleep(1)
if __name__ == '__main__':
drv = appium_desired()
x = UploadView(drv)
x.upload()
通过这个项目的练习实践,进一步熟悉了appium自动化的原理,了解并使用了不同的元素定位方式(元素定位方式主要是受APP的影响),锻炼了代码编写的逻辑思维。
不过,由于PDD平台的复杂性,上传商品时所选择的类别不同,会导致其对应的商品属性页有较大的变化,所以此代码还存在一定的不完整性,日后会逐渐完善。以上。