• 每日打卡


    每日打卡-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 逐个搜索每一个关键词,成功后在结果列写入成功。

    参考答案

  • 相关阅读:
    Codeforces 512E
    UOJ #36 -【清华集训2014】玛里苟斯(线性基+暴搜)
    Codeforces 1188E
    洛谷 P7163
    C++ Boost库 操作日期与时间
    C/C++ 搜索缝隙并插入ShellCode
    线性代数学习之正交性,标准正交矩阵和投影
    洛谷 P5851 [USACO19DEC]Greedy Pie Eaters P(区间dp)
    洛谷 [NOIP2009 普及组] 道路游戏(dp)
    洛谷 P2890 [USACO07OPEN]Cheapest Palindrome G(区间dp)
  • 原文地址:https://www.cnblogs.com/superhin/p/13894991.html
Copyright © 2020-2023  润新知