自动化测试第五节-编写Selenium自动化脚本

使用Selenium IDE录制
The new Selenium IDE is designed to record your interactions with websites to help you generate and maintain site automation, tests, and remove the need to manually step through repetitive takes. Features 
include:
* Recording and playing back tests on Firefox and Chrome.
* Organizing tests into suites for easy management.
* Saving and loading scripts, for later playback.

Selenium IDE作为火狐浏览器的扩展插件,通过添加附加组件下载,下载后直接启动录制,操作浏览器即可,录制好的脚本可以导出为Python文件作为参考。

1.实现百度搜索-线性脚本

from selenium import webdriver
driver=webdriver.Chrome()
driver.get("https://www.baidu.com/")
driver.maximize_window()
driver.implicitly_wait(20)
driver.find_element_by_id('kw').send_keys("软件测试")
driver.find_element_by_id('su').click()
driver.quit()

2.参数化实现百度搜索-数据驱动

from selenium import webdriver

# 创建一个数组用于存放搜索的关键字
search_text = ['自动化测试', '性能测试', '接口测试']

# 通过for循环来遍历数组,数组元素作为每次搜索的关键字
for text in search_text:
    driver=webdriver.Chrome()
    driver.get("https://www.baidu.com/")
    driver.maximize_window()
    driver.implicitly_wait(20)
    driver.find_element_by_id('kw').send_keys(text)
    driver.find_element_by_id('su').click()
    driver.quit()

3.增加断言验证

# coding=utf-8
from selenium import webdriver
driver=webdriver.Chrome()
driver.get("https://www.baidu.com/")
driver.maximize_window()
driver.implicitly_wait(20)
driver.find_element_by_id('kw').send_keys(text)
driver.find_element_by_id('su').click()
driver.get_screenshot_as_file('G:\\Desktop\\test\\img\\baidu.png')
driver.quit()

断言验证存在问题,每运行一次脚本,新脚本产生的截图文件会覆盖旧的脚本文件,通过添加获取当前时间来改造一下,改造后如下:

import time
from selenium import webdriver
# 创建一个数组用于存放搜索的关键字

search_text = ['自动化测试', '性能测试', '接口测试']

# 通过for循环来遍历数组,数组元素作为每次搜索的关键字
for text in search_text:
    driver=webdriver.Chrome()
    driver.get("https://www.baidu.com/")
    driver.maximize_window()
    driver.implicitly_wait(20)
    driver.find_element_by_id('kw').send_keys(text)
    driver.find_element_by_id('su').click()
    time.sleep(2)
    picture_time = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time()))
    print(picture_time)
    try:
        picture_url=driver.get_screenshot_as_file('G:\\Desktop\\test\\img\\'+ picture_time +'.png')
        print("%s:截图成功!!!" % picture_url)
    except BaseException as msg:
        print(msg)
    driver.quit()

4.实现保宁通添加活动脚本

from time import sleep
from selenium import webdriver

driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(20)
driver.get('http://10.1.2.14:9000/login')
driver.find_element_by_css_selector('body > div > div > div > form > div:nth-child(4) > button').click()
driver.find_element_by_xpath('/html/body/div/div[2]/div/ul/li[6]/a').click()
driver.find_element_by_xpath("/html/body/div/div[2]/div/ul/li[6]/dl/dd[1]/a").click()
sleep(2)
driver.switch_to.frame(driver.find_element_by_xpath('/html/body/div/div[3]/iframe'))
driver.find_element_by_xpath('//*[@id="title"]').send_keys('标题1')
driver.find_element_by_xpath('//*[@id="meetingPersonForm"]/div[2]/div/div/div/input').click()
driver.find_element_by_xpath('//*[@id="meetingPersonForm"]/div[2]/div/div/dl/dd[2]').click()
driver.find_element_by_name('file').send_keys(r'E:\autotest\baidu\autotest\img\baidu.png')
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
driver.switch_to.frame('ueditor_0')
body_string = """正文测试内容"""
driver.find_element_by_tag_name('body').send_keys(body_string)
sleep(2)
driver.switch_to.parent_frame()
sleep(2)
driver.find_element_by_xpath('//*[@id="meetingPersonForm"]/div[8]/div/button').click()

5.通过Unittest框架实现XXX添加活动脚本

from time import sleep
from selenium import webdriver
import unittest

class Test_ADD(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(20)
        print('\n ***初始化浏览器***')

    def tearDown(self):
        self.driver.quit()
        print('\n ***退出浏览器***')

    def test_addhuodong(self):
        driver = self.driver
        driver.implicitly_wait(20)
        driver.get('http://10.1.2.14:9000/')
        driver.find_element_by_css_selector('body > div > div > div > form > div:nth-child(4) > button').click()
        driver.find_element_by_xpath('/html/body/div/div[2]/div/ul/li[6]/a').click()
        driver.find_element_by_xpath("/html/body/div/div[2]/div/ul/li[6]/dl/dd[1]/a").click()
        sleep(2)
        driver.switch_to.frame(driver.find_element_by_xpath('/html/body/div/div[3]/iframe'))
        driver.find_element_by_xpath('//*[@id="title"]').send_keys('标题1')
        driver.find_element_by_xpath('//*[@id="meetingPersonForm"]/div[2]/div/div/div/input').click()
        driver.find_element_by_xpath('//*[@id="meetingPersonForm"]/div[2]/div/div/dl/dd[2]').click()
        driver.find_element_by_name('file').send_keys(r'E:\autotest\baidu\autotest\img\baidu.png')
        driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
        driver.switch_to.frame('ueditor_0')
        body_string = """正文测试内容"""
        driver.find_element_by_tag_name('body').send_keys(body_string)
        sleep(2)
        driver.switch_to.parent_frame()
        sleep(2)
        driver.find_element_by_xpath('//*[@id="meetingPersonForm"]/div[8]/div/button').click()
        sleep(5)
        ele=driver.find_element_by_xpath('/html/body/div[2]/div/div/div/div/div[2]/div[1]/div[2]/table/tbody/tr[1]/td[3]/div').text
        print(ele)
        self.assertEqual(ele,'标题1')
        print("测试执行结束")

    if __name__ == '__main__':
        unittest.main()

自动化测试第四节-其他关键字和DatabaseLibrary扩展库的使用

Robotframework关于Log的各种方法

关键字用法备注
LogLog ${data}等同于Print,可以把${data}的值打印在RF的log文件中查看
Log to consoleLog to console ${data}可以把${data}的值打印在运行的console口,但是在RF的log文件中无法看见
Log ManyLog many @{data}如果是一个列表的话,可以通过该关键字进行打印
CommentComment xxxx可以在log中显示脚本的注释

其中我们在DatabaseLibrary库里,想要打印完整的查询语句返回的列表结构,需要用到Log Many关键字。

弹窗的处理 Handle Alert

弹窗
    dakaichrome    https://www.w3school.com.cn/tiy/t.asp?f=hdom_alert    gc
    Select Frame    id=iframeResult
    Click Element    xpath=/html/body/input
    Handle Alert    action=DISMISS

Select选择框的处理 Select From List By Label/Value/Index

下拉框
    dakaichrome    https://www.w3school.com.cn/tiy/t.asp?f=eg_html_select    gc
    Select Frame    id=iframeResult
    Select From List By Value    xpath=/html/body/select    audi
    Select From List By Label    xpath=/html/body/select    Audi
扩展库
DatabaseLibrary
pip install robotframework-databaselibrary    安装RF对应的数据库库
pip install PyMySQL      MySQL数据库驱动安装
DatabaseLibrary库常用关键字
Connect To Database 连接数据库
Connect To Database Using Custom Params 使用自定义参数连接数据库
Disconnect From Database 断开数据库连接
Query 单个查询
Row Count 返回查询结果的行数
Execute Sql String 执行sql脚本
Execute Sql Script 执行sql文件
Check If Exists In Database 判断是否有返回结果
数据库连接
连接之前 确保对应数据库的驱动已经安装。
连接数据库有两种写法
Connect To Database
   Connect To Database    pymysql    demo    root    123456    localhost    3306
    #查询
    @{result}    Query    select * from student;
    Log Many    @{result}
    Disconnect From Database

Connect To Database Using Custom Params

     Connect To Database Using Custom Params    pymysql    database='demo', user='root', password='123456', host='127.0.0.1', port=3306
    #查询
    @{result}    Query    select * from student;
    Log Many    @{result}
    Disconnect From Database

注意的是,连接上数据库使用完之后,一定要关闭连接

Disconnect From Database

数据库增删改查语句

#查询
SELECT * FROM information WHERE id=148;
#删除
DELETE FROM information WHERE id=148;
#更新
UPDATE information SET title = '软件测试yyds' WHERE id = 148;
#新增
INSERT INTO information (id, title) VALUES (148, '标题');

数据库执行脚本

数据库的脚本
    Connect To Database Using Custom Params    pymysql    database='test1', user='root', password='', host='127.0.0.1', port=3306
    Log    ${EXECDIR}
    Log    ${CURDIR}
    Execute Sql Script    ${EXECDIR}/test1.sql
    Disconnect From Database

存储过程

创建存储过程实现传入学生学号和姓名,插入到学生表中,批量创建测试数据。

#创建存储过程
delimiter //
create procedure add_stu()
begin
declare num int;
set num=1;
while num <= 100 do
insert into student(st_id,st_name) values(num,concat("张三",num));
set num=num+1;
end while;
end //
#调用存储过程
CALL add_stu();

RF里调用存储过程

调用存储过程
    Connect To Database Using Custom Params    pymysql    database='baoning', user='root', password='123456', host='10.1.2.14', port=3307
    Execute Sql String    CALL add_stu();

RF中Suite和Cases里的Setup和Teardown

数据库操作
    [Setup]    Connect To Database    pymysql    baoning    root    123456    10.1.2.14    3307
    Comment    Connect To Database    pymysql    baoning    root    123456    10.1.2.14    3307
 
    @{information}    Query    select * from information where id = 64;
    Log Many    @{information}
    Comment    Execute Sql String    delete from information where id =149;
    Execute Sql String    UPDATE information SET title = '软件测试yyds2' WHERE id = 64
    Log Many    @{information}
    Comment    Disconnect From Database
    [Teardown]    Disconnect From Database
Setup:测试执行之前做的事
Teardown:测试执行之后做的事

执行用例的顺序:Setup-->用例脚本-->Teardown

Suite setup/teardown
  进入和退出这个suite执行用例前后必须执行且只分别执行一次
Test setup/teardown
  如果suite内的用例本身没有 setup/teardown,才执行
Robotframework中各个级别的Setup和 Teardown执行顺序以及范围
suite 级别的Setup\Teardown是不会被覆盖的,但test级别的Setup\Teardown 会被覆盖覆盖顺序是test case -> test suite -> Project/Directory
当TestCase有自己的Setup或Teardown时,则会选择执行自己的,抛弃上级的当Test Suite和Test Case都没指定其Setup\Teardown时,就执行Project/Directory的当某个TestCase没有 Setup或Teardown,就执行上一级的;如果另一个Case有的话,就执行自己对应的Setup或Teardown
当TestCase有自己的 Setup或Teardown 时,则会选择执行自己的,抛弃上级的当Test Suite和Test Case都没指定其Setup\Teardown时,就执行Project/Directory的当某个TestCase没有 Setup或Teardown,就执行上一级的;如果另一个Case有的话,就执行自己对应的Setup或Teardown
层级关系可以参考HTML里css的三种引入方式及优先级
1.就近原则
2.理论上:行内>内嵌>链接>导入
Unittest框架
unittest 是python 的单元测试框架,unittest 单元测试提供了创建测试用例,测试套件以及批量执行的方案,unittest在安装pyhton以后就直接自带了,直接import unittest 就可以使用。
TestFixturesetUp(前置条件),tearDown(后置条件),用于初始化测试用例以及清除和释放资源
TestRunner运行器,一般通过runner来调用suite去执行测试
TestSuite测试套件,也就是上面的测试用例集
TestCase测试用例,通过继承unittest.TestCase,实现用例的继承,在UnitTest中,一个testcase的实例就是一个测试用例。测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown),(注:测试用例都是通过开头以tes来识别的)。

HTML报告生成

数据驱动

@ddt
class Baidu1(unittest.TestCase):
    def setUp(self):
     self.driver=webdriver.Chrome()
     self.url="http://www.baidu.com/"
     self.driver.implicitly_wait(5)
     # self.verificationErrors = []
     # self.accept_next_alert = True
    def tearDown(self):
        self.driver.quit()
        # self.assertEqual([], self.verificationErrors)
    # @unittest.skip("skipping")
    @data("测试1","测试2","测试3")
    def test_baidu1(self,value):
        self.driver.get(self.url)
        self.driver.find_element_by_id("kw").clear()
        self.driver.find_element_by_id("kw") .send_keys(value)
        self.driver.find_element_by_id("su") .click()
        time.sleep(5)

Selenium实现保宁通的添加活动

import time
from time import sleep
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(20)
driver.get('http://10.1.2.14:9000/login')
driver.maximize_window()
driver.find_element_by_css_selector('body > div > div > div > form > div:nth-child(4) > button').click()
driver.find_element_by_xpath('/html/body/div/div[2]/div/ul/li[5]/a').click()
driver.find_element_by_xpath("/html/body/div/div[2]/div/ul/li[5]/dl/dd[1]/a").click()
sleep(2)
driver.switch_to.frame(driver.find_element_by_xpath('/html/body/div/div[3]/iframe'))
driver.find_element_by_id("title").send_keys('标题1')
driver.find_element_by_name('file').send_keys(r'D:\Desktop\123.jpg')
driver.find_element_by_xpath('//*[@id="activityForm"]/div[4]/div[1]/div/div/input').click()
driver.find_element_by_xpath('//*[@id="activityForm"]/div[4]/div[1]/div/dl/dd[3]').click()
driver.find_element_by_id('startTime').send_keys(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
driver.find_element_by_id('endTime').send_keys(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
driver.switch_to.frame('ueditor_0')
body_string = """正文测试内容"""
driver.find_element_by_tag_name('body').send_keys(body_string)
driver.switch_to.parent_frame()
driver.find_element_by_class_name('layui-btn').click()

自动化测试第三节-页面元素处理,数据类型和用户关键词

等待
隐式等待:等待某个元素出现,等到出现后才进入下一步操作,其中可以设置超时时间
显示等待:强制等待,常见的就是sleep关键字,等待固定时间后执行下一步操作,或者抛出异常
关键词:
Set Browser Implicit Wait    设置浏览器隐式等待
Wait Until Element Is Visible     等待直到查找的元素可见
Sleep    强制等待
Frame框架
网页结构里面遇到frame框架时,虽然可以看到所要定位的元素,但是不能点击,原因是因为元素在框架里。我们需要切换到对应框架去选择元素。可以把框架看成两室一厅的房间,进入访问页面的时候,我们所在的是房间的客厅,当我们要进入卧室时,我们需要打开门进入房间,就相当于切换了网页的frame/iframe框架,注意切换进入卧室后,需要退出才能回到客厅。
关键词:
Select Frame  选择框架
Unselect Frame  取消选择框架
文件上传
网页上遇到需要上传文件时,可以使用该关键词,如上传头像,上传附件或者图片等。注意在填写文件路径时,由于编译问题,需要在路径上加入双斜杠,如正常文件路径为
D:\Desktop\image.jpg,需要改为D:\\Desktop\\image.jpg
关键词:
Choose File  选择文件
富文本框处理
富文本框本质上就是对html页面进行编辑,所以我们用input方法无法输入,换作Press Key方法去向富文本编辑框输入文字
示例:
    Select Frame    id=ueditor_0
    Press Key    xpath=/html/body    正文内容
验证自动化脚本是否成功执行?
需要运用到断言来验证,断言在测试里是一个非常重要的概念,在我们的自动化,性能,接口测试里都会有所涉及,断言的核心其实就是我们实际输出和预期输出之间的比较,是否是符合我们的期望的。比如我们可以断言网页是否打开成功,可以通过成功打开网页的一些标志如页面标题,网页里的特殊文本等。或者用图片来进行断言。
断言Assert 
对比  预期输出 - 预期输出
关键词:
Should Contain 
例子:
以百度为例,验证打开百度后显示的标题是不是"百度一下,你就知道"
断言百度
    Open Browser    https://www.baidu.com/    chrome
    Maximize Browser Window
    Set Browser Implicit Wait    20
    ${t}    Get Title
    Log To Console    ${t}
    Should Contain    ${t}    百度一下,你就知道

断言百度页面新闻字样
    Open Browser    https://www.baidu.com/    chrome
    Maximize Browser Window
    Set Browser Implicit Wait    20
    ${news}    Get Text    xpath=//*[@id="s-top-left"]/a[1]
    Log To Console    ${news}
    Should Contain    ${news}    新闻
其他验证方式
1.截图-OCR
2.文本验证
加法
    ${x}    set variable    1
    ${y}    set variable    2
    ${z}    evaluate    ${x} + ${y}
    Log    ${z}
添加资讯脚本
    Open Browser    http://10.1.2.14:9000/login    chrome
    Maximize Browser Window
    Set Browser Implicit Wait    20
    Click Button    xpath=/html/body/div/div/div/form/div[4]/button
    Click Element    xpath=/html/body/div/div[2]/div/ul/li[6]/a
    Click Element    xpath=/html/body/div/div[2]/div/ul/li[6]/dl/dd[1]/a
    Select Frame    xpath=/html/body/div/div[3]/iframe
    Wait Until Element Is Visible    name=title
    Input Text    name=title    测试2
    Click Element    xpath=//*[@id="meetingPersonForm"]/div[2]/div/div/div/input
    Click Element    xpath=//*[@id="meetingPersonForm"]/div[2]/div/div/dl/dd[2]
    Choose File    name=file    C:\\Users\\admin\\Desktop\\yelp_bug.jpg
    Execute Javascript    window.scrollTo(0,1000)
    Select Frame    id=ueditor_0
    Press Key    xpath=/html/body    正文内容
    Unselect Frame
    Select Frame    xpath=/html/body/div/div[3]/iframe
    Click Button    xpath=//*[@id="meetingPersonForm"]/div[8]/div/button
    ${tt}    Get Text    xpath=/html/body/div[1]/span
    Should Contain    ${tt}    资讯表管理
    Capture Page Screenshot
    Close Browser
基础数据类型
1.变量
定义:是计算机语言中能储存计算结果或能表示值抽象概念。变量可以通过变量名访问。
赋值:${x1}= set variable 123
运算:${x3}= evaluate ${x1} + ${x2}
应用:获取网页的文本,然后断言

2.数组
定义:是有序的元素序列。用于区分数组的各个元素的数字编号称为下标。
赋值:@{list}=  create list 1 2
取值:${list[0]}   list   list[0]     list[1]
应用:切换网页窗口句柄时,可以用数组;调用接口传参数的时候,可以用数组。

3.字典
数据字典:可以根据键,得到值;也可以更新键的值,key-value键值对结构
赋值:&{map}=  create dictionary  aa=AA bb=BB
取值:${map[‘aa’]}
应用:Json格式解析之后就是字典
用户关键字(User Keyword)
自定义封装关键字
实现加法运算
#定义一个变量x,给他赋值1		
${x}=	set variable	1
#定义一个变量y,给他赋值2		
${y}=	set variable	2
#求x+y的和赋值给z		
${z}=	evaluate	${x}+${y}
#将z的值打印到控制台		
log to console	variable:${z}	

1.封装加法运算

调用封装好的加法plus plus 5 6 2.封装浏览器初始化操作三步

调用封装好的浏览器方法

    dakaichrome    https://www.baidu.com/    gc

调用封装好的切换窗口方法qiehuanwindow 1
其他脚本切换新闻窗口Edit

Text Edit

新闻
    dakaichrome    https://www.baidu.com/    chrome
    Capture Page Screenshot
    qiehuanwindow    1
    Capture Page Screenshot
    Get Window Titles
    Get Title
    Click Element    //*[@id="channel-all"]/div/ul/li[2]/a
    Capture Page Screenshot
    Close Browser

变量

数组/列表角标[1]表示取列表里的第二个值

自动化测试第二节-关键词驱动

我们在创建Robotframework项目的时候,按照以下文件结构来
-项目文件夹(project)
  -用例集(test suite)
  -测试用例(test case)


关键词驱动:关键字驱动脚本是比较复杂的数据驱动技术的逻辑扩展,封装了各种基本操作,每个操作由相应的函数实现,开发脚本时不需要关心这些基础函数,而用一系列关键字指定执行的任务本节课使用的关键词,具体的用法请通过Tools-Search Keywords(F5)查看对应类库的关键词名称以及对应用法。

Open Browser  打开浏览器
Maximize Browser Window   最大化窗口
Set Browser Implicit Wait   设置浏览器隐式等待
Sleep   等待
Click Element    点击元素
Click Button    点击按钮
Input Text    输入文本
Get Window Handles    获取窗口句柄
Select Window   选择窗口
Capture Page Screenshot   截屏
Execute Javascript      在脚本里执行javascript脚本


其中Javascript脚本,我们用window.scrollTo(x,y)(滚动到哪儿),window.scrollBy(x,y)(每次滚多少)两个方法来实现页面翻页,其中参数x,y为网页的坐标,我们可以通过F12打开Console,输入脚本调试滚动的值。

自动化测试用例:
关键项:输入,步骤,结果
回归测试:重点是有效等价类,核心的用例。
线性脚本,按照自动化测试的流程执行。

元素 element   获取 点击 操作
定位器 locator 
常见定位标签id,name,class,tag,link,partial_link,xpath,css
其中xpath获取方式:
以Chrome浏览器为例,选中要查看的元素,选中元素点击鼠标右键,点击检查元素。

找到右边对应的Elments对应元素的位置,点击鼠标右键,选择Cpoy-Copy Xpath,粘贴到locator参数位置即可,如果执行脚本的时候找不到该元素,则在前面加一个xpath=

其他Locator用法如下:

定位器示例说明描述
identifierClick Element | identifier=my_elementMatches by @id or @name attribute匹配 id 或 name 属性
idClick Element | id=my_elementMatches by @id attribute匹配 id 属性
nameClick Element | name=my_elementMatches by @name attribute匹配 name 属性
xpathClick Element | xpath=//div[@id=’my_element’]Matches with arbitrary XPath expression匹配 Xpath 表达式
domClick Element | dom=document.images[56]Matches with arbitrary DOM express匹配 DOM表达式
linkClick Element | link=My LinkMatches anchor elements by their link text匹配锚点的链接文字
partial linkClick Element | partial link=y LinMatches anchor elements by their partial link text匹配锚点的部分链接文字
cssClick Element | css=div.my_classMatches by CSS selector匹配 CSS
jqueryClick Element | jquery=div.my_classMatches by jQuery/sizzle selector匹配jQuery/sizzle选择器
sizzleClick Element | sizzle=div.my_classMatches by jQuery/sizzle selector匹配jQuery/sizzle选择器
tagClick Element | tag=divMatches by HTML tag name匹配元素的HTML tag 名称
default*Click Link | default=page?a=bMatches key attributes with value after first ‘=’匹配第一个=后面的关键属性
百度搜索测试脚本
1.打开浏览器     Open Browser
2.输入百度的网址   Open Browser
3.点击输入框     Click Element 
4.输入"软件测试"    Input Text
5.点击"百度一下"按钮    Click Button
*** Settings ***
Library           Selenium2Library
*** Test Cases ***
BaiduSearch
    Open Browser    https://www.baidu.com/    chrome
    Maximize Browser Window
    Set Browser Implicit Wait    20
    Click Element    id=kw
    Input Text    name=wd    软件测试
   Click Button    xpath=//*[@id="su"]
   Close Browser


问题1:Ride运行过程中日志输出中文乱码解决方案1.找到python目录:C:\python37\Lib\site-packages\robotide\contrib\testrunner下的testrunnerplugin.py文件。2.修改第565行,把 encoding[‘SYSTEM’]) 改为 encoding[‘OUTPUT’])3.重启RIDE客户端,重新运行脚本

问题2:选择元素后发现定位不到元素所在位置

1.检查页面是否加载完成,如果没有可以在获取元素之前设置等待时间,同样用于网页初始化设置时
2.检查元素是否可见,元素可能需要前置条件触发才会显示,如果下拉框或者元素在web底部
3.Xpath描述错误原因,或者选择定位器错误
4.新开了网页窗口,需要切换窗口句柄
未完待续....

自动化测试第一节-自动化测试环境准备

1.Python环境准备首先,需要安装python环境,推荐python3.7,最低3.5+安装过程中需要勾选添加到PATH

安装好以后,通过命令行python检查是否安装成功,如果没有成功返回响应,检查电脑是否有额外安装的python目录,通过控制面板-程序和功能查看

2.相关依赖包安装通过cmd命令窗口输入pip install 包名在线安装对应的依赖库pip install robotframework==3.1.2 pip install robotframework-ride==1.7.3.1pip install robotframework-seleniumlibrary==3.2.0pip install selenium如果在线安装失败,可以通过https://pypi.org/地址下载对应库的离线文件,通过python命令安装,比如支持窗口运行的ride客户端,输入关键词检索

找到对应的库

下载离线包

解压对应包,在该包名目录下通过Shift+鼠标右键打开命令窗口(PowerShell窗口),输入python setup.py install进行安装

安装完成后,可以通过pip list安装命令查看已经安装的库和相关的包

RIDE启动报错解决pip uninstall Pypubsubpip install Pypubsub==3.3.03.RIDE窗口运行安装完成正常情况会提示在桌面创建一个图标,双击图标运行即可。如果没有创建成功,可以进入到python安装目录下的Script目录下,通过在该目录下Shift+鼠标右键打开命令窗口(PowerShell窗口),输入python ride.py进行启动,如我的python安装在C盘根目录下,则进入对应目录操作

运行成功后,可以点击Tools-Create RIDE Desktop Shortcut生成桌面图标。

4.浏览器驱动的安装浏览器驱动由各个厂家提供,操作不同浏览器自动化需要安装对应浏览器对应版本的浏览器驱动程序,也就是对应浏览器的driver,常见的浏览器driver如下

浏览器名对应驱动名下载地址
谷歌浏览器chromedriverhttp://npm.taobao.org/mirrors/chromedriver/
火狐浏览器geckodriverhttps://github.com/mozilla/geckodriver/releases
Edge浏览器IEDriverServerhttps://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

注意,在下载的时候我们要查看浏览器驱动和浏览器版本是否对应,以谷歌浏览器为例,浏览器版本在右上角设置-帮助-关于Google Chrome查看。

我电脑的谷歌版本为93,则在对应浏览器驱动页面下载的时候也下载对应的版本即可

下载好后,因为还需要配置驱动的PATH,则我们可以直接将浏览器驱动放在Python的安装路径下,因为Python路径已经配置过,就可以成功运行Selenium脚本了。5.WebDriver调用Selenium实现浏览器访问原理

6.打开浏览器,访问百度通过Robotframework实现先导入Selenium2Library库,在运用Open Browser关键词实现,由于框架为关键词驱动,可以通过Tools-Search Keywords(F5)查看不同类库的关键词名称以及对应用法。

运行脚本,可以点击菜单栏的运行按钮,或者切换到Run界面运行,运行成功后可以查看相应的结果和日志信息。

通过Pycharm编写Selenium脚本实现


from selenium import webdriver driver = webdriver.Chrome() driver.get("https://www.baidu.com/")

如果不能运行,需要检查一下环境是否包含所需要的配置和依赖库。

图片的故事

摩天楼顶上的午餐:是一张著名的黑白照片,于1932年美国纽约洛克菲勒中心的RCA大楼施工时拍摄。

15块石头:无论从哪个角度,肯定有一个石头以上的石头躲在另外的石头后

八月杂谈

好久没有写文字了,最近发生太多事情,杂七杂八的太多,今天准备写一些自己的理解和观点。

最近正在进行的奥运会属实精彩,虽然说已经经历过很多届了,但是传统的味道还是没有改变,原来只喜欢看奥运会,单纯的看奥运会,现在喜欢除了看奥运会以外,还喜欢看看选手背后的一些故事。

比如东京这场奥运会,开幕式和部分选手已经被喷烂了,最开始属于是深有感触,但是越来越疯狂的攻击,甚至于是人身攻击网暴让我觉得事态发展非常不好,有些过了,我敢说很多乱喷的人可能连一场完整的比赛都没有看完过,而是别人分享的一些文字图片便跟上节奏了,不管对不对,就想搞个大新闻批判一番。所以我觉得现在网上的戾气太重了,不仅仅是在奥运会这个事儿上,还有鸿星尔克捐款的事儿上一样,感觉好多听风就是雨,攻击其他品牌,其他个人,节奏跟的飞起,各种搞道德绑架,各种乌烟瘴气让我觉得很窒息,也很迷惑。总结一点就是,现在太多人缺乏独立思考能力了,甚至于是懒得思考,把别人的观点拿来即用,真“拿来主义”了属于是。这样我觉得甚是不好,道德一直都是约束自己而非他人的,未知全貌,不予置评。殊不知很多时候自己的口嗨,给别人带来多大伤害。真的,不要当键盘侠,净化网络环境,人人有责。

当然除了这些之外,自己也很有收获,个人的发展,也要靠历史的进程推动。我现在越来越觉得反思,定位自己的重要性了。很多时候,并不是说你能力不行怎么样,而是要看你站在怎样的角度去看问题,比如,承认自己是一个很普通的人,并好好生活,能做到这件事,我觉得也是非常了不起了。最近授人以鱼的模型已经思考到第五层了,即授人以鱼不如授人以渔,授人以渔不如授人以欲,授人以欲不如授人以遇,授人以遇不如授人以域。其中这个域就是自我定位,之前我一直觉得你学习什么,你从事怎样的工作,这是最好的。但其实并不然,适合自己才是最好的。那什么是适合自己呢,说实话我也常常在思考什么才是适合自己的。这个问题太复杂了,因为每个人的定位真的很不一样。就拿我自己来说,不说别的,生活方面还是可以说是衣食无忧了吧,但是对于有的人来说。可能连吃饭都成问题,就更不用说发展了。还有的人不仅仅是他一个人要吃饭,他的背后可能有整个家庭需要照顾,所以真的是井蛙不可以语于海者,拘于虚也;夏虫不可以语于冰者,笃于时也。了解了更多,我才知道很多残酷的实事。这就是为什么我现在很喜欢看纪录片,尤其是小人物的纪录片,比如何苦导演拍的《最后的棒棒》,竹内亮导演的《我住在这里的理由》还有张尧导演《一个人的一天》,还有如《高考》,《出路》等等,甚至于带篮子陈义拍的《粉丝的一天》,我也觉得甚是好看,纪录片让我知道,不是说鸿鹄之志才是梦想,能够成为一个普通人,好好生活真的是一件很不错的事。所以了解这些后,回过头来看这些问题就很好理解了,我们想要好的生活,就必须要正视自己,找准好自己的定位和所处的环境,并且制定一个切实可行而且能够达到的目标努力奋斗,不管什么时代努力奋斗是必不可少的。”从来就没有什么救世主,也不靠神仙皇帝,要创造人类的幸福,全靠我们自己!”愿诸君共勉。

还有对于女性的一些看法,我向来是尊重女性的,但是有一说一,女生在职场或者说是某些地方确实会受到歧视和不尊重,比如知道有些女生连卫生巾都用不上的时候我真的是大为震惊,在淘宝买散装卫生巾的还被说不卫生等等,有何不食肉糜那味儿了,真的条件艰苦的我都不敢想象。反观一些女生,比如说长大了找个好老公嫁了什么的话,我是一直很反对的,对于女性来说,不应该谈论的只有婚姻或者说是生育工具,而是能够真正的作为独立女性,为自己的梦想,为自己喜欢的事情事业发热发光的。独立的前提就是要能够欣赏自己,尊重自己,思考自己,武装自己。有一些言论我也是非常的感觉到不适,像张口闭口就是我男朋友怎样,我老公怎样的,我很是反感,他在怎样也是他,不是你。现在可以是你的男朋友或者老公,可能很快就不是了,如果不提升自己,那么最后吃亏的也是自己。我想说的就是,女同胞们也能有自己的爱好,自己的理想,为自己奋斗的勇气。而不是你的男朋友,你的老公,你的孩子。如果一直依附于他物,很快就会被社会淘汰,你的安全感只能是自己给自己。

说到这里,我又想起一个事儿,就是有个小镇做题家谈论怎么远离愚昧的父母的一个话题,我看完简直不敢相信自己的眼睛,真的能够说出这些话的人到底是怎样长这么大的,真的是白眼狼了。不管怎么说,父母无论怎样也是我们最亲的人,而为了追求自己的幸福而抛弃自己的父母家庭,我觉得这种人是真的坏透了,不能说是精致的利己主义者了,应该说是贪婪的利己主义者了,专门利己,毫不利人,把父母拒之门外,简直是冠冕堂皇的坏人。不说他人,说说我自己吧,我对父母怎么样呢,谈不上非常好吧,但是不得不说,和父母的交流沟通还是比较频繁到位的,基本都是每周四五个电话,不管是嘘寒问暖,还是杂七杂八的,都会给父母说。其实父母的期盼真的是希望你能够过好生活,即便上面那位小镇做题家抛弃父母,父母肯定是不会记你仇的,但是无论如何,人不能忘记自己的根,忘记自己的人性。俗话说“子不嫌母丑,狗不嫌家贫”,能够说出抛弃父母过好自己小日子这样话的人,非蠢即坏,是群众里的坏人。

以上,一点微小的收获,谢谢大家。

Bobby

2021.8.5

JAVA项目在Linux服务器环境下部署

现在有一个需求:需要把一个war包部署在可以公网访问的服务器上,以用于安卓app的后台支持。

所以第一步,我们需要准备一个云服务器,这里推荐阿里云的云翼计划,24岁以下的实名用户可以获得9.5元一个月的学生服务器,很不错地址为https://promotion.aliyun.com/ntms/act/campus2018.html

服务器好了之后,我们还需要准备项目运行的一些基本环境,Tomcat服务,数据库和JAVA环境,首先我们先准备数据库环境,然后是JAVA环境,最后是Tomcat.

数据库准备

数据库的话,可以安装Xampp集成包来使用,这样会方便一些,xampp在官网即可下载,选择For Linux版本即可https://www.apachefriends.org/index.html

下载好后,我们通过运用Xftp工具连接远程数据库,把相应的包拖过去即可。

 

完成后,首先在根目录下找到安装包,并通过Xshell连接到服务器,给予安装包可执行权限

# chmod 777 xampp-linux-x64-5.6.14-0-installer.run

然后运行安装即可

./xampp-linux-x64-5.6.14-0-installer.run

安装完成后,启动/停止xampp

# /opt/lampp/lampp start/stop

卸载xampp

# /opt/lampp/lampp stop

# rm -rf /opt/lampp

如果提示服务启动OK,则成功启动,启动失败的话需要检查服务器端口是否被其他程序占用,Apache默认端口为80,Mysql默认端口为3306。

启动完成后,我们可以通过Navicat或HeidiSQL远程连接数据库,如果这时候出现数据库连接不上的话,则是因为Mysql数据库未授予远程连接权限,需要给其他IP地址授权处理以下。

通过Xshell登陆数据库(密码默认为空)

1.执行MySQL mysql -u root -p空密码(登录MySQL)

2.执行use mysql;(跳到系统的mysql库)

3.执行update user set host = ‘%’ where user = ‘root’;(设置root用户的访问IP为全部而不只是本地)

4.执行FLUSH PRIVILEGES;(这一步很重要,实时刷新权限生效)

完成后即可远程连接数据库,连接上后记得给数据库设置一个密码

JAVA环境准备

Java环境配置时主要注意安装的文件路径和环境变量的设置

首先在官网下载对应版本的安装包,注意是linux版本64位后缀为tar.gz的包

https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

下载完成后,先进入linux系统里的local文件夹下,创建一个名为文件夹,并进入

cd usr/local/
mkdir kencery
cd kencery/
进入后,然后按照之前的方式运用Xftp工具将压缩包拖到linux服务器上的该目录下
然后解压我们下载好的jdk文件,并重命名文件,完成后进入该文件夹
 tar -zxv -f  jdk-8u11-linux-x64.tar.gz   //解压文件
 mv jdk-8u11-linux-x64  javajdk //将文件重命名为javajdk
 cd javajdk //进入重命名好的目录
接下来配置java的环境变量
输入

vim /etc/profile

进入文档查看,按i进入编辑模式,将下面一段配置输入到底部

JAVA_HOME=/usr/local/kencery/javajdk
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar
export PATH JAVA_HOME CLASSPATH
写完之后我们按键盘(ESC)按钮退出,然后按(:wq)保存并且关闭Vim。
配置完成之后,最重要的一步就是使文件立即生效:命令如下:
source /etc/profile
如果生效,此时我们输入java -version就能查看到返回java版本的提示

Tomcat准备

同样我们在官网上下载tomcat,https://tomcat.apache.org/download-80.cgi,下载的时候要注意一下项目的支持问题,老一点的项目下载9可能会出一些问题,我这里下载的是apache-tomcat-8.5.43.tar.gz

下载完成后,以同样的方式拖到Linux服务器里,先在local文件夹下创建一个tomcat文件,再将压缩包拖到该文件夹下,然后再解压。

mkdir /usr/local/tomcat     //在local下新建tomcat文件夹

mv apache-tomcat-8.5.43 /usr/local/tomcat/  //将下载好的压缩包移动到新建的文件夹下

tar -zxvf apache-tomcat-8.5.43.tar.gz  //解压当前文件在该文件夹下

 

完成后,我们进入解压好的目录下的webapps目录下,将我们打包好的war包通过xftp工具拖动到该目录下

完成后,我们回到bin目录下,启动tomcat服务即可

cd /usr/local/tomcat/apache-tomcat-8.5.43/bin

./startup.sh     //启动服务

./shutdown.sh    //关闭服务

Tips:在启动tomcat之前,还需要确定war包里面的数据库连接信息和当前设置数据库的连接信息一致(包括地址,端口,账号,密码等),并确保本机数据库服务已经启动

 

以上

Bobby

2019.7.30

 

 

 

 

2019年4月好书推荐-《孤独六讲》

“美学的本质或许就是孤独”

第一次接触美学这个词,竟然是在讲孤独。说起孤独,我会想到什么呢,日常琐事,或许就是自己与自己生活吧。想起一句话,他有属于他自己的孤独,所谓的心心相通,都只是一场误会而已。

本月Bobby好书推荐,《孤独六讲》,看完之后,希望有进一步的理解。

 

数据库设计-E-R图与概念模型

数据库设计的三个步骤:

1.概念模型

2.数据模型

3.物理模型

1、图书借阅管理系统数据库要求提供下述服务:

(1)可随时查询书库中现有书籍的品种、数量与存放位置。所有各类书籍均可由书号惟一标识。

(2)可随时查询书籍借还情况,包括借书人单位、姓名、借书证号、借书日期和还书日期。

约定:任何人可借多种书,任何一种书可为多个人所借,借书证号具有惟一性。

(3)当需要时,可通过数据库中保存的出版社的电报编号、电话、邮编及地址等信息向相应出版社增购有关书籍。

约定,一个出版社可出版多种书籍,同一本书仅为一个出版社出版,出版社名具有惟一性。

1.2数据建模:

E-R图设计步骤

第一步:抽象实体:借书人,图书,出版社

第二步:确定实体的属性:借书人:借书证号,姓名,单位

第三步:确定实体的联系:借阅,出版

第四步:确定实体之间的关系:1:1;1:n;m:n

满足上述需求的E-R图如图:

E-R图转换成关系模型

第一步:将实体转换为关系模型(罗列属性,并用下划线标识主码)

借书人(借书证号,姓名,单位)

图书(书号,书名,数量,位置)

出版社(出版社名,电报编号,电话,邮编,地址)

第二步:将联系转换为关系模型(罗列属性,如果属性不具有明显的主码,则从对应的实体提取主码)

借阅(借书日期,还书日期)

第三步:梳理关系

1:1:候选码(两边选其一)

1:n:n端码(多的端的主码作为关系的码)

m:n:组合码(两端为共同主键)

第四步:合并关系(实体与联系):前提条件:实体和联系有相同的码

1:1:联系合并到其中一个实体中

1:n:联系合并到n端的实体中

m:n:不能合并

关系模型如下:

借书人(借书证号,姓名,单位)

图书(书号,书名,数量,位置,出版社名)

出版社(出版社名,电报编号,电话,邮编,地址)

借阅(借书证号,书号,借书日期,还书日期)

(完)