282.继承的介绍

"""
定义动物类,动物有姓名和年龄属性,具有吃和睡的行为
定义猫类,猫类具有动物类的所有属性和方法,并且具有抓老鼠的特殊行为
定义狗类,狗类具有动物类的所有属性和方法,并且具有看门的特殊行为
定义哮天犬类,哮天犬类具有狗类的所有属性和方法,并且具有飞的特殊行为
"""
class Animal:
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    def eat(self):
        print(f"{self.name}正在吃东西")
        
    def sleep(self):
        print(f"{self.name}正在睡觉")

class Cat(Animal):

    def catch_mouse(self):
        print(f"{self.name}正在抓老鼠")

class Dog(Animal):

    def watch_door(self):
        print(f"{self.name}正在看门")

class XiaoTianQuan(Dog):

    def fly(self):
        print(f"{self.name}正在飞") 

c1 = Cat("小花",2)
c1.eat()
c1.catch_mouse()

xtq = XiaoTianQuan("哮天犬",3)
xtq.eat()
xtq.watch_door()
xtq.fly() 
283.父类方法重写

#覆盖式重写
class Animal:
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    def eat(self):
        print(f"{self.name}正在吃东西")
        
    def sleep(self):
        print(f"{self.name}正在睡觉")

class Cat(Animal):

    def eat(self):
        print(f"{self.name}正在吃鱼")

    def catch_mouse(self):
        print(f"{self.name}正在抓老鼠")

c1 = Cat("小花",2)
c1.eat()
c1.sleep()

#扩展式重写
class Animal:
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    def eat(self):
        print(f"{self.name}正在吃东西")
        
    def sleep(self):
        print(f"{self.name}正在睡觉")

class Cat(Animal):

    def eat(self):
        super().eat()
        print(f"{self.name}正在吃鱼")

    def catch_mouse(self):
        print(f"{self.name}正在抓老鼠")

c1 = Cat("小花",2)
c1.eat()
c1.sleep()
284.继承的练习
"""
需求
编写 Person 类,类中有属性 name、age,人类有个方法睡觉(抱着枕头睡)。
编写一个程序员类继承人类,程序员类有一个睡觉方法(抱着电脑睡):
获取一个程序员对象,调用睡觉。
"""
class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def sleep(self):
        print(f"{self.name}抱着枕头睡")

class programer(Person):
    def sleep(self):
        print(f"覆盖式重写:{self.name}抱着电脑睡")
    
class programer1(Person):
    def sleep(self):
        print(f"扩展式重写:{self.name}抱着电脑睡")
        super().sleep()

p1 = programer1("小明",20)
p1.sleep() #扩展式重写:小明抱着电脑睡

p2 = programer("小红",21)
p2.sleep() #覆盖式重写:小红抱着电脑睡

285.多态的演示

class Dog:
    def game(self):
        print("在地上玩")

class XiaoTianQuan(Dog):
    def game(self):
        print("天上玩")

d1 = Dog()
d2 = XiaoTianQuan()

class Person:
    def play_with_dog(self,name): #不同的对象调用相同的方法产生不同的结果
        name.game()

p1 = Person()
p1.play_with_dog(d1)
p1.play_with_dog(d2)
286.面向对象特征总结

287.类属性和类方法

288.类属性和类方法案例

注意:类方法存在的意义就是为了修改和更新类属性

#定义一个工具类
#在类中封装一个show_tool_count的类方法,输出使用当前这个类,创建的对象个数

class Tools:
    #类属性:工具栏可以创建不同的工具对象,而统计的数据不针对某一个工具数量,是所有工具类创建的对象的数量
    tool_count = 0

    def __init__(self):
        Tools.tool_count += 1 #此行Tools不能替换为cls,因为只有在类方法里才有cls等价于类名,除了类方法里,cls等价于类名,其他地方只能用类名去调用


    @classmethod
    def show_tool_count(cls):
        print(f"当前创建了{cls.tool_count}个工具对象")

t1 = Tools()
t2 = Tools()
t3 = Tools()
Tools.show_tool_count() #输出:当前创建了1个工具对象
289.python_day04总结
290.私有属性和私有方法介绍

class woman():
    def __init__(self,name,age):
        self.name = name
        self.__age = age #私有属性
    
    def __eat(self):
        #私有方法
        print(f"{self.name}喜欢吃吃吃")
        
w1 = woman("小红",20)

print(w1.age) #报错:私有属性不能直接调用
w1.__eat() #报错:私有方法不能直接调用
#只在内部用不对外公开的就属性方法可以定义为私有属性和私有方法
#总结:初始管理员账号密码应该私有,链接数据库的方法应该私有

del方法作用是删除某个对象,无需自己定义,会自动执行

dir可以查看创建对象后这个对象能用哪些属性和方法

dir() 函数输出的内容是一个包含字符串的列表,它列出了对象所有可见的名称(包括属性、方法、继承的成员等)。但列表中的名称能否“直接使用”,需要根据命名规则来区分:

1. 普通名称(可以直接使用)
列表中那些没有下划线前缀的名称(如你之前代码中的 name),通常是对象的公开属性和普通方法,你可以直接通过 对象.属性名 的方式调用。

2. 以双下划线开头和结尾的名称(内置特殊方法)
如 __init____str____class__ 等。这些被称为“魔术方法”或协议方法,它们通常由 Python 解释器在特定情况下自动调用,一般不建议也不需要在日常业务代码中直接调用。

3. 以双下划线开头的名称(私有属性/方法)
这些名称在 dir() 中已经发生了名称修饰(如 _woman__eat)。虽然你可以通过这个修饰后的名字强制调用它们,但这违背了面向对象封装的初衷,在实际开发中强烈不建议这样做。

4. 以单下划线开头的名称(受保护属性/方法)
如 _name。这在 Python 中是一种约定俗成的规范,表示该属性或方法是“受保护的”(内部使用)。虽然技术上可以直接调用,但按照开发规范,不建议在类的外部直接使用它们。

总结建议
在使用 dir() 探索对象时,建议重点关注那些没有下划线前缀的普通名称,它们才是你在日常编程中应该直接调用的有效方法和属性。

class woman():
    def __init__(self,name,age):
        self.name = name
        self.__age = age #私有属性
    
    def __eat(self):
        #私有方法
        print(f"{self.name}喜欢吃吃吃")
        
w1 = woman("小红",20)

# print(w1.age) #报错:私有属性不能直接调用
# w1.__eat() #报错:私有方法不能直接调用
#只在内部用不对外公开的就属性方法可以定义为私有属性和私有方法
#总结:初始管理员账号密码应该私有,链接数据库的方法应该私有
print(dir(w1))
#左侧两个下划线为私有的,左右都有两个下划线的是内置的
"""
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_woman__age', '_woman__eat', 'name']

"""
"""
名称修饰机制:在 Python 中,当类中的属性或方法名以双下划线 __ 开头(且不以双下划线结尾)时,Python 解释器在编译阶段会自动将其重命名为 _类名__属性名 的格式。
实际名称改变:在你的代码中,类名是 woman,私有方法是 __eat。因此,Python 解释器自动将其重命名为了 _woman__eat。
输出结果印证:你通过 dir(w1) 打印出的对象属性列表中,已经包含了 _woman__eat,这正是被重命名后的私有方法。同理,私有属性 __age 也被重命名为了 _woman__age。
"""
#非要访问私有方法或属性,可以通过对象名._类名__属性名或对象名._类名__方法名来访问
w1._woman__eat() #访问私有方法
print(w1._woman__age)
291.私有属性和私有方法练习

class LoginPage(object):

    def __input_username(self):
        self.username = input("请输入用户名:")
    
    def __input_password(self):
        self.password = input("请输入密码:")
    
    def login(self):
        self.__input_username()
        self.__input_password()
        print("登录成功")

292.pytest框架介绍

什么是框架:为解决一类事情的功能集合

pytest能做自动化测试

293.pytest实现测试脚本

人工测试用例:编号标题、模块、优先级、前置条件、测试步骤、测试数据、预期结果

#E:\****\work\test_study\scripts\test_calc.py
from api.calc import add

class TestCalc:
    #测试计算函数的类
    #测试用例
    def test_01_add(self):
        #测试数据

        #调用函数
        result = add(1,2)
        #打印结果
        print(f"计算结果是{result}")

TestCalc().test_01_add()
#E:\****\work\test_study\api\calc.py
def add(a,b):
    #加法函数
    return a+b
294.pytest测试脚本执行

(gp) PS E:\****\work\test_study> pytest -s scripts\test_calc.py

-s的含义是允许在测试执行过程中显示代码中的 print() 语句输出内容。

295.pytest脚本其他执行

296.pytest执行多条用例

297.pytest执行用例失败

298.python脚本的断言

299.传统风格前后置处理1
#pytest控制某一行测试命令  ::测试类::测试名
pytest -s .\scripts\test_calc.py::TestCalc::test_03_add

通过配置文件来控制测试用例执行范围:

[pytest]
#添加命令行参数
addopts = -s
#文件搜索路径
testpaths = ./scripts #相对路径
#文件名称
python_files = test*.py
#类方法
python_classes = Test*
#方法名称
python_functions = test*
300.传统风格前后置处理2

在软件测试中,测试用例的前置操作(Preconditions)和后置操作(Postconditions)是确保测试能够顺利执行、结果准确且环境稳定的关键组成部分。

1. 前置操作(前置条件)

前置操作是指在执行测试用例之前必须满足的条件或完成的准备工作。它定义了测试用例的起点,就像建房子前必须先打好地基一样。如果没有明确的前置条件,测试可能会因为与核心功能无关的原因(如缺少测试数据、未登录等)而失败。

前置操作通常涵盖以下几个方面:

  • 用户相关条件:确保存在正确类型的用户。例如,测试登录功能前,系统中必须存在一个已注册且拥有有效邮箱和密码的用户账户。
  • 系统相关条件:确认系统本身处于正确状态。例如,应用程序服务器正在运行,或者特定的功能开关(如“启用支付网关”)已开启。
  • 数据相关条件:准备测试所需的现有数据。例如,测试订单取消功能前,测试用户必须存在一个状态为“待处理”的订单。
  • 环境相关条件:涉及测试的执行环境。例如,测试设备上已部署了特定版本的移动应用,或测试环境可通过VPN访问。

2. 后置操作(后置条件)

后置操作是指在测试用例执行之后系统需要达到的状态,或需要执行的清理与恢复操作。它的主要作用是保证系统在测试后恢复到稳定状态,防止当前测试对其他功能或后续测试造成干扰。

后置操作通常包括:

  • 状态验证:确认测试结束后系统处于预期的状态。例如,测试支付功能后,订单状态应更新为“已支付”,用户账户余额相应减少,且交易日志记录成功。
  • 数据与环境清理:恢复测试前的环境,保持测试环境的“干净”。例如,退出当前登录账号、删除测试创建的订单并恢复库存至初始值、清除浏览器缓存,或关闭性能测试工具以释放服务器资源。

3. 在自动化测试框架中的应用

在实际的自动化测试开发中(例如使用 Python 的 Pytest 框架),前置和后置操作通常通过特定的机制来实现:

  • Setup / Teardown:在测试用例执行前进行环境初始化(如打开浏览器、连接数据库),执行后进行资源清理(如关闭浏览器、删除数据)。
  • Fixture(固定装置):Pytest 等框架提供的强大机制,用于替代传统的 setup/teardown,实现更灵活的前后置管理和资源共享,支持从函数级、类级到模块级等不同粒度的控制。

综上所述,前置操作确保了测试“能够正确开始”,而后置操作确保了测试“能够干净地结束”。两者结合,极大地提升了测试的有效性、可重复性和结果的一致性。

模块级别基本上用不到,常见的是方法级别和类级别

from api.calc import add

#模块方法只需要了解即可
def setup_module():
    """模块方法:前置模块方法"""
    print("打开计算器...")

def teardown_module():
    """模块方法:后置模块方法"""
    print("关闭计算器...") 



class TestCalc:

    # def setup_method(self):
    #     """前置方法:方法级别,在每个测试方法执行之前执行"""
    #     print("打开计算器...")

    # def teardown_method(self):
    #     """后置方法:方法级别,在每个测试方法执行之后执行"""
    #     print("关闭计算器...")

    # def setup_class(cls):
    #     """前置方法:类级别,在每个类中的测试方法执行之前执行"""
    #     print("类级别:打开计算器...")

    # def teardown_class(cls):
    #     """后置方法:类级别,在每个类中的测试方法执行之后执行"""
    #     print("类级别:关闭计算器...") 


    def test_01_add(self):
        #测试数据
        #调用函数
        result = add(1,2)
        print(f"计算结果是:{result}")
        assert 3 == result 

    def test_02_add(self):
        #测试数据
        #调用函数
        result = add(-1,2)
        print(f"计算结果是:{result}")
        assert 1 == result 

    def test_03_add(self):
        #测试数据
        #调用函数
        result = add(0.1,0.2)
        print(f"计算结果是:{result}")
        assert 0.2 == result 

    def test_04_add(self):
        #测试数据
        #调用函数
        result = add(1,"a")
        print(f"计算结果是:{result}")
        assert "1a" == result 
301.fixture机制前后置

方法级别前后置主要是针对于每条测试用例前后分别执行

类级别是整个测试类前后分别执行

细粒度到每个测试步骤上,也就是每个步骤上都可以加前后置测试

装饰器的作用:不改变当前函数代码的基础上增加额外的功能

import pytest
from api.calc import add

@pytest.fixture(scope = "class") #括号里如果不写的话默认就是function
def pre_op():
    """前后置函数"""
    print("打开计算器")
    yield "正在计算中...."
    print("关闭计算器")

class TestCalc:

    def test_01_add(self,pre_op):
        #测试数据
        #调用函数pre_op
        result = add(1,2)
        print(f"计算结果是:{result}")
        assert 3 == result 

    def test_02_add(self,pre_op):
        #测试数据
        #调用函数
        result = add(-1,2)
        print(f"计算结果是:{result}")
        assert 1 == result 
#pytest.ini
[pytest]
#添加命令行参数
addopts = -s
#文件搜索路径
testpaths = ./scripts #相对路径
#文件名称
python_files = test*ex.py
#类方法
python_classes = Test*
#方法名称
python_functions = test*
302.conftest实现前后置

conftest.py放在哪里:如果想让整个模块都共享这个前后置,就放在项目下。只在当前测试模块或测试用例用,那就放在测试目录下,一般习惯性放在项目下

conftest.py专门存放前后置的代码实现

304.allure测试报告应用

305.测试报告常见问题
306.python_day05总结

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐