每日打卡


每日打卡-01-字符串填空

起止時間: 2020/10/19 09:00 ~ 2020/11/21 23:59
知識點參考 https://www.cnblogs.com/superhin/p/13837611.html

  1. 編寫一個函數,輸入一個text參數,將函數參數放入字符串 "//*[text()='所傳text參數']"指定位置中,並打印這個字符串
  2. 定義一個多行文本
tpl = '''
<html>
<head><meta charset="UTF-8"><title>title變量位置</title></head>
<body>
<h1>report_name變量位置</h1>
<div>開始時間:start_at變量位置  運行時間:duration變量位置 秒</div>
<div>總數:testRuns變量位置  通過:successes變量位置 失敗:failures變量位置 異常: errors變量位置</div>
</body>
<html>'''

已知變量

title="測試報告"
report_name="接口測試報告"
start_at="2020-09-10 10:00:00"
duration=3
testRuns=20
successes=15
failures=4
errors=1

把上述變量渲染到tpl模板變量中,並將得到的包含數據的字符串按保存文本文件的方式,以utf-8編碼的格式保存為一個名稱為report.html的文件。


參考答案

# 1
def xpath(text):
    return f'//*[text()="{text}"]

# 2
tpl = '''
<html>
<head><meta charset="UTF-8"><title>{title}</title></head>
<body>
<h1>{report_name}</h1>
<div>開始時間:{start_at}  運行時間:{duration} 秒</div>
<div>總數:{testRuns} 通過:{successes} 失敗:{failures} 異常: {errors}</div>
</body>
<html>'''

title="測試報告"
report_name="接口測試報告"
start_at="2020-09-10 10:00:00"
duration=3
testRuns=20
successes=15
failures=4
errors=1

html  = tpl.format(title=title, report_name=report_name, start_at=start_at, duration=duration,
                               testRuns=testRuns, successes=successes, failures=failures, errors=errors)

with open('report.html, 'w', encoding='utf-8') as f:
    f.write(html)

每日打卡-02-列表和字典解包

起止時間: 2020/10/20 09:00 ~ 2020/11/21 23:59
知識點:https://www.cnblogs.com/superhin/p/13837849.html

  1. 有一個變量
search_ipt_loc = ('id', 'kw')

和函數

def find_element(by, value):
    print(f'通過{by}={value}定位元素')

怎樣調用find_element函數將search_ipt_loc中的數據傳入?

  1. 有一個字典
db_conf = {'host': '127.0.0.1', 'port': 3306, 'user': 'test', 'password': '11111', 'db': 'abc'}

和函數

def connect(host,port,user,password,db):
    print(f'連接數據{host}成功')

怎么調用函數把db_conf中的數據傳入?


參考答案

search_ipt_loc = ('id', 'kw')

def find_element(by, value):
    print(f'通過{by}={value}定位元素')

db_conf = {'host': '127.0.0.1', 'port': 3306, 'user': 'test', 'password': '11111', 'db': 'abc'}

def connect(host,port,user,password,db):
    print(f'連接數據{host}成功')

find_element(*search_ipt_loc)
connect(**db_conf)

每日打卡-03-使用對象在方法間共享屬性

起止時間: 2020/10/21 09:00 ~ 2020/11/21 23:59
知識點:https://www.cnblogs.com/superhin/p/13841854.html

  1. 設計一個名為Page的類,需要傳入一個名為driver的參數。其中包含以下3個方法。
    (1)統一定位方法
def find_element(by, value):
   ...

by參數的選擇是"id","name","class name", "tag name", "link text", "partial link text", "xpath", "css selector"
value是具體對應的元素屬性或定位表達式字符串
當by=id時使用find_element_by_id方法定位,依次類推
並返回定位到的元素
(2)元素點擊方法

def click(by, value):
    ...

使用by,value調用上面封裝的find_element方法得到元素,然后進行點擊
(3)元素輸入方法

def type(by, value, text):
   ...

使用by,value調用上面封裝的find_element方法得到元素, 然后輸入text的值

完成后,在類下使用以下腳本進行測試

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

baidu = Page(driver)
baidu.type('id', 'kw', '簡書 韓志超')
baidu.click('id', 'su')

sleep(3)
driver.quit()

參考答案

from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement


class Page(object):
    def __init__(self, driver: WebDriver):
        self.driver = driver

    def find_element(self, by: str, value: str) -> WebElement:
        method_map = {
            'id': self.driver.find_element_by_id,
            'name': self.driver.find_element_by_name,
            'class name': self.driver.find_element_by_class_name,
            'tag name': self.driver.find_element_by_tag_name,
            'link text': self.driver.find_element_by_link_text,
            'partial link text': self.driver.find_element_by_partial_link_text,
            'xpath': self.driver.find_element_by_xpath,
            'css selector': self.driver.find_element_by_css_selector,
        }
        if by not in method_map:
            raise ValueError('不支持該定位方法')
        func = method_map.get(by)
        element = func(value)
        return element

    def click(self, by: str, value: str) -> None:
        print(f'點擊元素{by}={value}')
        self.find_element(by, value).click()

    def type(self, by: str, value: str, text: str) -> None:
        print(f'元素{by}={value}中輸入{text}')
        send_key = self.find_element(by, value)
        send_key.send_keys(text)


if __name__ == '__main__':
    from selenium import webdriver
    from time import sleep

    driver = webdriver.Chrome()
    driver.get("https://www.baidu.com")
    baidu = Page(driver)
    baidu.type("id", "kw", "簡書 韓志超")
    baidu.click("id", "su")

    sleep(3)
    driver.quit()

每日打卡04-使用CSV數據

起止時間: 2020/10/22 09:00 ~ 2020/11/21 23:59
知識點:https://www.cnblogs.com/superhin/p/11495956.html

  1. 假設我們爬取到一批數據
movies = [
('肖申克的救贖','Tim Robbins', 'https://xiaoshenke.html'),
('霸王別姬','張國榮', 'https://bawangbieji.html'),
('阿甘正傳','Tom Hanks', 'https://aganzhengzhuan.html'),
]

將其保存為一個movie.csv文件,並加上標題行movie,player,url
2. 假設我們有一個data.csv文件,內容如下

a,b,excepted
1,2,3
0,0,0
-1,-1,-1
6,0.3,6.3

另外有一個函數

def add(a,b):
    return a+b

編寫一個測試函數,讀取csv中的每行數據,將add(a,b)的返回結果與每行的excepted對比,如果成打印成功
失敗則打印失敗。


參考答案

import csv

# 1
movies = [
('肖申克的救贖','Tim Robbins', 'https://xiaoshenke.html'),
('霸王別姬','張國榮', 'https://bawangbieji.html'),
('阿甘正傳','Tom Hanks', 'https://aganzhengzhuan.html'),
]

header = ('movie','player','url')
with open('movie.csv', 'w', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerow(header)
    writer.writerows(movies)

# 2
def add(a, b):
    return a + b

with open('data.csv', encoding='utf-8') as f:
    data = csv.reader(f)
    for a, b, excepted in data:
        a, b, excepted = float(a), float(b), float(excepted)
        if add(a, b) == excepted:
            print(f'{a}+{b}={excepted} 通過')
        else:
            print(f'{a}+{b}={excepted} 不通過')

每日打卡-05-兩數之和問題

起止時間: 2020/10/23 09:00 ~ 2020/11/21 23:59
知識點:時間復雜度指需要Operate操作的次數的量級
完全遍歷一個長度為n的列表則時間復雜度為O(n)。
如果雙重循環

for i in range(n):
    for j in range(n):
     ....

則時間復雜度是O(n^2)

  1. 假設我們有一個列表
    l=[1,2,3,4,5,6,7,8] 數據不重復,目標值為6,要求找出數組中兩個元素之和等於目標 的數組下標。
    要求時間復雜度小於O(n^2)

參考答案

注意,不要使用雙重循環,暴力加和來和target對比,正確的做法是單層循環,然后查找target與當前值的差,是否存在於列表中。
但是由於列表的in查詢時間復雜度是O(n),即隱含了一層循環,這樣效率其實和雙重循環是一樣的,都是O(n^2)。
這里就可以使用哈希來優化查詢差值是否在列表中操作,將O(n)降為O(1),因此總體的效率就會變成O(n^2)->O(n)。

l = [1,2,3,4,5,6,7,8]
set1 = set(list1)   # 使用集合已方便查找
target = 6

result = []
for a in list1:
    b = target - a
    if a < b < target and b in set1:   # 在集合中查找,為避免重復,判斷a為較小的那個值
        result.append((list1.index(a), list1.index(b)))   # 列表index取下標的操作為O(1) 
print(result)

每日打卡-06-列表字典推導式

起止時間: 2020/10/26 11:08 ~ 2020/10/31 23:59
知識點:https://www.cnblogs.com/superhin/p/13877327.html

  1. 數據篩選
    假設一個活動列表接口數據如下
res = {
    'code': 0,
    'msg': '成功',
    'datas': [
        {'activityName': '雙11折扣', 'activityId': 12543, 'start_time': '20201020', 'end_time': '20201120', 'state': 1},
        {'activityName': '今日折扣', 'activityId': 23413, 'start_time': '20201020', 'end_time': '20201021', 'state': 2},
        {'activityName': '大減價', 'activityId': 13265, 'start_time': '20201019', 'end_time': '20201120', 'state': 0},
        {'activityName': '每日促銷', 'activityId': 19876, 'start_time': '20201020', 'end_time': '20201121', 'state': 0},
        {'activityName': '新用戶優惠', 'activityId': 15801, 'start_time': '20201020', 'end_time': '20201220', 'state': 1},
    ]
 }

已知state=0為未開始,1為進行中,2為以結束,使用列表推導式得到當前所有進行中的activityId列表,要求每個activityId轉為字符串形式。

  1. Cookies格式轉化
    假設我們需要通過登錄接口繞過Selenium登錄操作,我們需要使用requests發送登錄接口,得到響應中的cookies然后再使用driver.add_cookie方法添加的瀏覽器中。
    接口返回的cookies是一個字典格式,如{'Token', 'abcdefg', 'SessionID': '1234567'}
    而selenium添加cookie時需要這樣的格式,{'name': 'Token': 'value': 'abcdefg'}{'name': 'SessionID': 'value': '123456'}
    使用推導式實現完成轉換
cookies = {'Token':'abcdefg', 'SessionID': '1234567'} 
# 轉為
cookies = [{'name': 'Token': 'value': 'abcdefg'},{'name': 'SessionID': 'value': '123456'}]

參考答案

# 1
res = {
    'code': 0,
    'msg': '成功',
    'datas': [
        {'activityName': '雙11折扣', 'activityId': 12543, 'start_time': '20201020', 'end_time': '20201120', 'state': 1},
        {'activityName': '今日折扣', 'activityId': 23413, 'start_time': '20201020', 'end_time': '20201021', 'state': 2},
        {'activityName': '大減價', 'activityId': 13265, 'start_time': '20201019', 'end_time': '20201120', 'state': 0},
        {'activityName': '每日促銷', 'activityId': 19876, 'start_time': '20201020', 'end_time': '20201121', 'state': 0},
        {'activityName': '新用戶優惠', 'activityId': 15801, 'start_time': '20201020', 'end_time': '20201220', 'state': 1},
    ]
 }

activity_ids = [str(item.get('activityId') for item in res.get('datas', [])]

# 2
cookies = {'Token':'abcdefg', 'SessionID': '1234567'} 

cookies = [{'name': key, 'value': value} for key, value in cookies.items()]

每日打卡-07-路徑組裝和獲取環境變量

起止時間: 2020/10/27 08:56 ~ 2020/11/27 23:59
知識點:https://www.cnblogs.com/superhin/p/13880748.html

  1. 有一個項目結構如下
autotest/
    data/
        data.csv
    testcases/
        baidu.py

在baidu.py中如何組裝出項目的根路徑以及data.csv文件的路徑

  1. 在系統中(Win 環境變量設置, Mac sudo vim ~/.bash_profilesource ~/.bash_profile)手工添加兩個環境變量
USER=admin
PASSWORD=123456

並在baidu.py中讀取出來這兩個變量的值


參考答案

import os
# 1
base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)
data_file = os.path.join(base_dir, 'data', 'data.csv')

# 2
user = os.getenv('USER')
password = os.getenv('PASSWORD')

每日打卡-08-Python類中的不同方法

起止時間: 2020/10/28 12:23 ~ 2020/11/27 23:59
知識點:https://www.cnblogs.com/superhin/p/13884123.html

  1. Python類中有哪幾種方法,分別怎么調用?

參考答案

3種,類方法,實例方法,靜態方法,類方法使用類名調用,
實例方法需要創建實例使用實例調用,靜態方法使用類名或者實例都可以調用。

每日打卡-09-使用ini配置文件

起止時間: 2020/10/29 12:23 ~ 2020/11/27 23:59
知識點:https://www.cnblogs.com/superhin/p/13883802.html

  1. 手工新建一個配置文件config.ini,內容如下
[user]
name=admin
password=123456
is_admin=true

[mysql]
host=10.10.10.10
port=3306
db=apitest
user=root
password=123456

讀取mysql段的配置,並得到一個字典變量

db_conf={'host': '10.10.10.10', 'port': 3306, 'db': 'apitest', 'user': 'root', 'password': '123456'}

注意:port需要是整型


參考答案

from configparser import ConfigParser

conf = ConfigParser()
conf.read('/Users/superhin/項目/示例/data.ini')

db_conf = dict(conf['mysql'])
db_conf['port'] = int(db_conf['port'])
print(db_conf)

每日打卡-10-二分查找

起止時間: 2020/10/30 22:08 ~ 2020/11/27 23:59
知識點:二分查找是一種比較快的查找算法,首先需要序列有序。
思想是先用序列中間數和目標值對比,如果目標值小,則從前半部分(小於中間數)重復此查找,否則從后半部分重復此查找,直到目標值左右兩邊沒有值。

    1. 已知一個列表
l = [0, 9, 8, 1, 10, 2, 5, 3, 11, 6, 13, 100, 24]
l.sort()  # 對列表進行排序

此時l=[0, 1, 2, 3, 5, 6, 8, 9, 10, 11, 13, 24, 100]
編寫一個二分查找算法,查找排序后l中8的索引。


參考答案

l = [0, 1, 2, 3, 5, 6, 8, 9, 10, 11, 13, 24, 100]


def bin_find(l, target):
    low, high = 0, len(l) - 1  # low, high是兩個游標, 通過不斷地逼近來找到該數字
    while low < high:
        mid = (high + low) // 2   # 取中間數索引, 注意是 low + high

        if target > l[mid]:   # 如果目標值比中間數大,移動下游標
            print(target, '>', l[mid])
            low = mid
        elif target < l[mid]:  # 如果目標比中間數小,移動上游標
            print(target, '<', l[mid])
            high = mid
        else:
            print('找到了, 索引', mid)
            return mid
    print('未找到')

bin_find(l, 8)

每日打卡-11-高效的集合操作

起止時間: 2020/11/02 09:48 ~ 2020/12/02 23:59
知識點:https://www.cnblogs.com/superhin/p/13913335.html

  1. 100w條數據,使用列表和集合哪個查詢效率比較高?為什么?
  2. 為什么Redis查詢很快?
  3. 在A-B測試中,假設A桶返回的數據為
{'code': 0, 'msg': 'success', 'data': [{'productId': 123, 'productName': 'lv包'},{'productId': 321, 'productName': 'prada包'},{'productId': 542, 'productName': 'gucci包'},{'productId': 412, 'productName': 'fendi包'},{'productId': 631, 'productName': 'ysl包'},{'productId': 221, 'productName': 'mcm包'},{'productId': 541, 'productName': 'penko包'}]}

B桶數據為

{'code': 0, 'msg': 'success', 'data': [{'productId': 123, 'productName': 'lv包'},{'productId': 321, 'productName': 'proda包'},{'productId': 541, 'productName': 'gucci包'},{'productId': 412, 'productName': 'fendi包'},{'productId': 631, 'productName': 'ysl包'},{'productId': 121, 'productName': 'mcm包'},{'productId': 541, 'productName': 'penko包'}]}

利用集合操作快速找出A桶和B桶的數據差異。


參考答案

  1. 集合查詢效率高,因為集合是基於哈希算法的,無論數據量多少,查詢只需要一次操作。
  2. Redis是存儲與內存中的基於哈希算法的key-value鍵值對,無論數據量多少,單次查詢只需要一次操作。
  3. 代碼如下
res_a = {'code': 0, 'msg': 'success', 'data': [{'productId': 123, 'productName': 'lv包'}, {'productId': 321, 'productName': 'prada包'}, {'productId': 542, 'productName': 'gucci包'}, {
    'productId': 412, 'productName': 'fendi包'}, {'productId': 631, 'productName': 'ysl包'}, {'productId': 221, 'productName': 'mcm包'}, {'productId': 541, 'productName': 'penko包'}]}

res_b = {'code': 0, 'msg': 'success', 'data': [{'productId': 123, 'productName': 'lv包'}, {'productId': 321, 'productName': 'proda包'}, {'productId': 541, 'productName': 'gucci包'}, {
    'productId': 412, 'productName': 'fendi包'}, {'productId': 631, 'productName': 'ysl包'}, {'productId': 121, 'productName': 'mcm包'}, {'productId': 541, 'productName': 'penko包'}]}


# 將 res_a['data']中, 每一項字典,如{'productId': 123, 'productName': 'lv包'},改為可哈希的元祖(123, 'lv包')格式
data_a = [(item['productId'], item['productName']) for item in res_a['data']]
data_b = [(item['productId'], item['productName']) for item in res_b['data']]

data_a = set(data_a)  # 轉為集合
data_b = set(data_b)

print('A桶有-B桶無', data_a - data_b)
print('B桶有-A桶無', data_b - data_a)

打印結果

A桶有-B桶無 {(321, 'prada包'), (221, 'mcm包'), (542, 'gucci包')}
B桶有-A桶無 {(541, 'gucci包'), (121, 'mcm包'), (321, 'proda包')}

每日打開-12-使用Yaml文件

起止時間: 2020/11/03 09:18 ~ 2020/12/03 23:59
JSON是一種非常流行的數據格式,支持多種數據類型並支持嵌套,並可以快速轉為Python中的字典或列表類型。
然而由於JSON格式嚴格、不支持注釋。因此有了更簡潔強大的YAML格式,YAML兼容JSON格式,表述起來非常簡潔易用,因此成為很多開發者歡迎。
知識點:<https://www.cnblogs.com/superhin/p/11503756.html?
安裝方式: pip install pyyaml
假設我們想將一個用例描述為如下,一個用例,有用例名稱,並包含多個步驟,每個步驟都包含command操作、target目標、value值三個屬性,command支持open/click/type三種操作,taget和value允許為空,其中
target支持'id=,' 'name=', 'class name'='', 'css selector=', ....等八種。
已百度搜索為例,我們可以用字典描述為
{
'case_name': '百度搜索',
'steps': [
{'command': 'open', 'target': 'https://www.baidu.com/', 'value': ''},
{'command': 'type', 'target': 'id=kw', 'value': '雙11'},
{'command': 'click', 'target': 'id=su', 'value': ''}
]
}

  1. 按yaml格式,手動將數據保存為一個yaml文件,並用Python讀取出來。
  2. 解析並使用Selenium執行該條用例。

參考答案

  1. 格式如下
# 文件名: yaml_case.yaml
case_name: 百度搜索
steps:
  - command: open
    target: https://www.baidu.com/
    value:
  - command: type
    target: id=kw
    value: 雙11
  - command: click
    target: id=su
    value:
  1. 代碼如下
import yaml
from selenium import webdriver


# 定義三個操作函數, 並保持參數簽名統一
def do_open(driver, target, value=None):
    print('打開頁面', target)
    driver.get(target)


def do_type(driver, target, value):
    print(f'在 {target} 輸入 {value}')
    elm_loc = target.split('=')  # 分割得到定位方式和定位器
    driver.find_element(*elm_loc).send_keys(value)


def do_click(driver, target, value=None):
    print(f'點擊 {target}')
    elm_loc = target.split('=')
    driver.find_element(*elm_loc).click()


# 使用字典做動作映射
command_map = {
    'open': do_open,  # 上面定義的do_open函數
    'type': do_type,  # 上面定義的do_type函數
    'click': do_click,  # 上面定義的do_click函數
}


def run_yaml(driver, yaml_file):
    # 加載yaml數據,並轉為字典格式
    with open(yaml_file, encoding='utf-8') as f:
        data = yaml.safe_load(f)

    print('執行用例', data.get('case_name'))
    for step in data.get('steps', []):
        # 讀取每個步驟的 comnand, target, value字段的值
        command, target, value = step.get('command'), step.get('target'), step.get('value')
        # 獲取對應的操作函數
        func = command_map.get(command)
        # 執行函數
        func(driver, target, value)


# 測試一下
if __name__ == "__main__":
    driver = webdriver.Chrome()
    yaml_file = '/Users/superhin/項目/示例/yaml_case.yaml'
    run_yaml(driver, yaml_file)

每日打卡-13-使用日志

起止時間: 2020/11/04 11:32 ~ 2020/12/04 23:59
知識點:https://www.cnblogs.com/superhin/p/13924876.html

  1. 使用Selenium打開https://www.zhipin.com/,搜索框輸入 "測試工程師",並按回車,城市點擊 "北京",
    定位出首頁所有的職位鏈接。
    要求每一步操作前輸出INFO級的日志,同時輸出到屏幕和文件run.log中,最后運行后,日志輸出如下。
    2020/11/04 11:31:49 [INFO] 啟動瀏覽器
    2020/11/04 11:31:51 [INFO] 打開BOSS直聘
    2020/11/04 11:31:53 [INFO] 搜索框輸入測試工程師並回車
    2020/11/04 11:31:54 [INFO] 點擊北京
    2020/11/04 11:31:54 [INFO] 定位所有標題連接
    2020/11/04 11:31:54 [INFO] 標題個數: 30
    2020/11/04 11:31:54 [INFO] 退出瀏覽器

注意日志格式和不要輸出Selenium自帶的DEBUG日志。


參考答案

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import logging

cli_handler = logging.StreamHandler()  # 輸出到屏幕的日志處理器
file_handler = logging.FileHandler(filename='run.log', mode='a', encoding='utf-8')  # 輸出到文件的日志處理器

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s [%(levelname)s] %(message)s',
                    datefmt='%Y/%m/%d %H:%M:%S',
                    handlers=[cli_handler, file_handler]   # 添加兩個日志處理器
                    )
logging.info('啟動瀏覽器')
dr = webdriver.Chrome()
dr.implicitly_wait(10)
logging.info('打開BOSS直聘')
dr.get('https://www.zhipin.com/')
logging.info('搜索框輸入測試工程師並回車')
dr.find_element('name', 'query').send_keys('測試工程師'+Keys.ENTER)
logging.info('點擊北京')
dr.find_element('link text', '北京').click()
logging.info('定位所有標題連接')
links = dr.find_elements('css selector', 'span.job-name>a')
logging.info(f'標題個數: {len(links)}')
logging.info('退出瀏覽器')
dr.quit()

每日打卡-14-使用Cookies繞過登錄

起止時間: 2020/11/05 09:06 ~ 2020/12/04 23:59
知識點:https://www.cnblogs.com/superhin/p/11481803.html

  1. 使用接口請求獲取cookies,直接繞過商之翼系統的登錄,直接訪問,添加分類鏈接
    http://39.104.14.232/newecshop/admin/category.php?act=add,然后添加一個名為'某某某的分類'的商品分類

參考答案

import requests
from selenium import webdriver
from time import sleep

base_url = 'http://****'
username = '****'
password = '****'

login_url = base_url + '/newecshop/admin/privilege.php'   # 登錄接口地址
admin_url = base_url + '/newecshop/admin'  # 后台登錄頁地址
add_category_url = base_url + '/newecshop/admin/category.php?act=add'  # 添加分類頁面地址



# 獲取cookie
data = dict(username=username,password=password, act='signin')
res = requests.post(login_url, data=data, allow_redirects=False)
esscp_id = res.cookies.get('ECSCP_ID')
cookie = dict(name='ECSCP_ID',value=esscp_id)
print('cookie' ,cookie)


# 通過添加cookie繞過登錄
driver = webdriver.Chrome()
driver.get(admin_url)
driver.add_cookie(cookie)

driver.get(add_category_url)  # 需要打開兩次
driver.find_element('name', 'cat_name').send_keys('hzc_分類1')  # 輸入分類名稱
driver.find_element('css selector', 'input[type=submit]').click()  # 點擊確定

sleep(3)
driver.quit()

每日打卡-15-使用Docker及Zalenium

起止時間: 2020/11/06 09:06 ~ 2020/12/04 23:59
知識點:https://www.cnblogs.com/superhin/p/13857584.html

  1. 安裝Docker並安裝Zalenium,使用Zalenium提供的Selenium Grid服務運行一條商之翼登錄的用例,並查看錄像。
    請提交代碼及截圖。

實踐題目-無參考答案

每日打卡16-理解Python中的裝飾器

起止時間: 2020/11/09 11:37 ~ 2020/12/09 23:59
知識點:https://www.cnblogs.com/superhin/p/13947725.html
以下三個練習完成一項即可提交。

  1. 編寫一個基礎裝飾器info(func),在運行函數前,打印一條信息
    print('調用->{func.name}') # func是函數對象func.__name__可以獲取函數名稱
    並裝飾以下函數。
@info
def  add(a, b):
    return a + b

add(1,2)
  1. 編寫一個可以打印函數參數的裝飾器info(func),在函數運行前,打印一條信息
print('調用->add 參數: {args} {kwargs}') 
  1. 編輯一個帶參數的裝飾器custom_info(verbosity=1):
    verbosity默認為1時,在函數運行前打印
print('調用->{func.__name__}') 

當verbosity為2時,在函數運行前打印

print('調用->{func.__name__} 參數: {args} {kwargs}')   # args kwargs 代表被裝飾的函數參數

當verbosity>2時,在函數運行前打印

print('調用->{func.__name__} 參數: {args} {kwargs}') 

在函數運行后打印

print('調用->{func.__name__} 結果: {result}')   # result代表函數結果

並裝飾函數

@custom_info(3)
def  add(a, b):
    return a + b

add(1,2)

查看結果。


參考答案

  1. 代碼如下
def info(func):
    print(f'調用->{func.__name__}')
    return func
  1. 代碼如下
def info(func):
    def new_func(*args, **kwargs):
        print(f'調用->{func.__name__} 參數: {args} {kwargs}')
        return func(*args, **kwargs)
    return new_func
  1. 代碼如下
def custom_info(verbosity=1):
    def info(func):
        def new_func(*args, **kwargs):
            if verbosity == 1:
                print(f'調用->{func.__name__}')
            elif verbosity > 1:
                print(f'調用->{func.__name__} 參數: {args} {kwargs}')

            result = func(*args, **kwargs)
            if verbosity > 2:
                print(f'調用->{func.__name__} 結果: {result}')

            return result
        return new_func
    return info

每日打卡17-練習日期控件操作

起止時間: 2020/11/10 09:17 ~ 2020/12/09 23:59
知識點:https://www.cnblogs.com/superhin/p/13950534.html

  1. 下載群文件中的,time.zip

鏈接: https://pan.baidu.com/s/1ZA8JsV86S-i4uPD9PRgw8w 密碼: lee4

並解壓,使用瀏覽器打開其中的date.html,並復制出地址。
使用Selenium輸入活動的開始時間和結束時間。


參考答案

from selenium import webdriver
from time import sleep


url = 'file:///Users/superhin/Downloads/Time/date.html'

dr = webdriver.Chrome()
dr.get(url)

js = '''
document.querySelector("input[name='act_start_time']").removeAttribute("readonly");
document.querySelector("input[name='act_stop_time']").removeAttribute("readonly");
'''

dr.execute_script(js)
sleep(.5)

dr.find_element('name', 'act_start_time').send_keys('2020-11-16 00:00')
dr.find_element('name', 'act_stop_time').send_keys('2020-11-27 00:00')

dr.find_element('xpath', '//body').click()  # 空白處點擊,以關閉日期彈框

sleep(5)
dr.quit()

每日打卡18-使用JSON文件

起止時間: 2020/11/11 09:17 ~ 2020/12/09 23:59
知識點:https://www.cnblogs.com/superhin/p/11502830.html

  1. 假設我們用例中需要用到登錄用戶及商品的數據,規划如下
user:   # 登錄用戶數據
  username: admin
  password: 66666

goods:  # 商品相關數據
  new_goods_001: # 新商品數據001
    goods_name: hzc_dell電腦
    cat_name: 電腦
    shop_price: 3999

轉為字典即

{'goods': {'new_goods_001': {'cat_name': '電腦',
                             'goods_name': 'hzc_dell電腦',
                             'shop_price': 3999}},
 'user': {'password': '66666', 'username': 'admin'}}

手動將其保存為一個名為data.json的文件,編寫腳本,讀取其中的數據並還原成字典格式,然后提取並打印出其中的用戶名和密碼。


參考答案
data.json內容

{
  "goods": {
    "new_goods_001": {
      "cat_name": "電腦",
      "goods_name": "hzc_dell電腦",
      "shop_price": 3999
    }
  },
  "user": {
    "password": "66666",
    "username": "admin"
  }
}

讀取腳本

import json

with open('data.json', encoding='utf-8') as f:
    data = json.load(f)

print('用戶名', data['user']['username'])
print('密碼', data['user']['password'])

每日打卡19-使用Python發送郵件

起止時間: 2020/11/12 09:35 ~ 2020/12/09 23:59
知識點:https://www.cnblogs.com/superhin/p/13950653.html

  1. 登錄自己的qq郵箱並開通smtp服務,使用Python腳本發送一封郵件到superhin@126.com,郵件主題中寫上自己的名字。

參考答案

import smtplib  # 用於建立smtp連接
from email.mime.text import MIMEText

smtp_server = 'smtp.qq.com'
smtp_user = '***@qq.com'
smtp_password = '****'

def send_email(subject, body, receiver):
    msg = MIMEText(body, 'plain', 'utf-8')
    msg['From'], msg['To'], msg['Subject'] = smtp_user, receiver, subject

    smtp = smtplib.SMTP_SSL(smtp_server)
    smtp.login(smtp_user, smtp_password)
    smtp.sendmail(smtp_user, "接收郵件地址2", msg.as_string())
    smtp.quit()

send_email('某某某', '每日打卡19', 'superhin@126.com')

每日打卡20-為Pytest添加額外參數和配置項

起止時間: 2020/11/13 09:35 ~ 2020/12/09 23:59
知識點:https://www.jianshu.com/p/9a03984612c1
添加自定義選項和配置

  1. 新建一個空白的pytest項目,使用conftest.py中def pytest_addoption(config) 鈎子方法,為Pytest添加一個命令行參數 --name,添加一個配置項age
  2. 利用def pytest_terminal_summary(config) 鈎子方法,在最后運行時輸出 參數 name和age的信息。
    如,新建pytest.ini
[pytest]
age = 12

運行pytest --name=kevin,執行最后打印,我是kevin,年齡12


參考答案
目錄中新建conftest.py,內容如下

def pytest_addoption(parser):
    """Pytest初始化時添加選項的方法"""
    parser.addoption("--name", help='自定義參數name')
    parser.addini('age', help='自定義配置age')

def pytest_terminal_summary(config):
    """Pytest生成報告時的命令行報告運行總結方法"""
    name = config.getoption("--name")
    age = config.getini('age')
    print(f'我是{name},年齡{age}')

運行pytest --name=kevin后顯示

======================== test session starts ===========================
platform darwin -- Python 3.7.7, pytest-5.4.3, py-1.8.1, pluggy-0.13.1
rootdir: /Users/superhin/項目/示例/pytest_demo, inifile: pytest.ini
plugins: metadata-1.10.0, html-2.1.1
collected 0 items                                                                                                                                                                                                  

我是kevin,年齡12
=======================no tests ran in 0.01s ============================

每日打卡21-Python操作Excel

起止時間: 2020/11/16 11:40 ~ 2020/12/16 23:59
知識點:https://www.cnblogs.com/superhin/p/11503933.html

  1. 新建Excel文件數據格式如下
    關鍵詞 結果
    Python自動化
    Selenium
    接口測試
    Appium
    Postman
  2. 使用Selenium+百度 逐個搜索每一個關鍵詞,成功后在結果列寫入成功。
  3. (可選)使用Appium+Baidu App 逐個搜索每一個關鍵詞,成功后在結果列寫入成功。

參考答案


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM