pytest自动化测试框架Allure功能特性介绍

news2024/11/26 15:42:01

前言

Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息
从dev/qa的角度来看,Allure报告简化了常见缺陷的统计:失败的测试可以分为bug和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与TMS和BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。
从管理者的角度来看,Allure提供了一个清晰的“大图”,其中包括已覆盖的特性、缺陷聚集的位置、执行时间轴的外观以及许多其他方便的事情。allure的模块化和可扩展性保证了您总是能够对某些东西进行微调,使Allure更适合您,那么今天我们就来说说如何使报告更加详细的显示我们需要的信息,以及allure与jenkins的集成

生成报告

pytest框架编写的项目如何生成测试报告,这里将不再讲解,具体过程可以参考:

注意:python使用的allure插件为allure-pytest

测试代码

为了大家能够快速的认识allure的所有功能特性,附上完整的测试代码

"""
------------------------------------
@Time : 2019/8/28 19:50
@Auth : linux超
@File : conftest.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
import pytest
import allure



@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
    outcome = yield
    report = outcome.get_result()
    report.nodeid = report.nodeid.encode("utf-8").decode("unicode_escape")  # 解决乱码


@allure.step("打开浏览器")
def fixture_step():
    pass


@pytest.fixture
def init_url():
    fixture_step()
    yield True

"""
------------------------------------
@Time : 2019/9/4 21:05
@Auth : linux超
@File : test_allure_feature.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
import pytest
import allure
import os


def login(username=None, password=None):
    """模拟登录"""
    user = "linux超"
    pwd = "123456"
    if user == username and pwd == password:
        return {"code": 1001, "msg": "登录成功", "data": None}
    elif "" == password or password is None and username:
        return {"code": 1002, "msg": "密码不能为空", "data": None}
    elif "" == username or username is None and password:
        return {"code": 1003, "msg": "用户名不能为空", "data": None}
    else:
        return {"code": 1004, "msg": "用户名或密码错误", "data": None}


@allure.step("输入用户名")
def input_username(user):
    print("输入用户名")
    return user


@allure.step("输入密码")
def input_password(pwd):
    print("输入密码")
    return pwd


login_success_data = [
    # 测试数据
    {
        "case": "用户名正确, 密码正确",
        "user": "linux超",
        "pwd": "123456",
        "expected": {"code": 1001, "msg": "登录成功", "data": None}
    }
]

login_fail_data = [
    {
        "case": "用户名正确, 密码为空",
        "user": "linux超",
        "pwd": "",
        "expected": {"code": 1002, "msg": "密码不能为空", "data": None}
    },
    {
        "case": "用户名为空, 密码正确",
        "user": "",
        "pwd": "linux超哥",
        "expected": {"code": 1003, "msg": "用户名不能为空", "data": None}
    },
    {
        "case": "用户名错误, 密码错误",
        "user": "linux",
        "pwd": "linux",
        "expected": {"code": 1004, "msg": "用户名或密码错误", "data": None}
    }
]

username_none = [
    {
        "case": "缺省用户名参数",
        "pwd": "123456",
        "expected": {"code": 1003, "msg": "用户名不能为空", "data": None}
    }
]
password_none = [
    {
        "case": "缺省密码参数",
        "user": "linux超",
        "expected": {"code": 1002, "msg": "密码不能为空", "data": None}
    }
]
# 改变输出结果
ids_login_success_data = [
    "测试{}用户名:{}密码{}期望值{}".
        format(data["case"], data["user"], data["pwd"], data["expected"]) for data in login_success_data
]
ids_login_fail_data = [
    "测试{}用户名:{}密码{}期望值{}".
        format(data["case"], data["user"], data["pwd"], data["expected"]) for data in login_fail_data
]
ids_username_none = [
    "测试{}密码{}期望值{}".
        format(data["case"], data["pwd"], data["expected"]) for data in username_none
]
ids_password_none = [
    "测试{}用户名:{}期望值{}".
        format(data["case"], data["user"], data["expected"]) for data in password_none
]


@allure.feature("登录模块")
class TestLogin(object):

    @allure.severity(allure.severity_level.BLOCKER)
    @allure.story("测试登录成功")
    @allure.title("登录成功场景-{data}")
    @pytest.mark.parametrize("data", login_success_data, ids=ids_login_success_data)
    def test_login_success(self, data):
        """测试登录成功"""
        user = input_username(data["user"])
        pwd = input_password(data["pwd"])
        result = login(user, pwd)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("测试登录失败")
    @pytest.mark.parametrize("data", login_fail_data, ids=ids_login_fail_data)
    def test_login_fail(self, data):
        """测试用户名或密码错误"""
        user = input_username(data["user"])
        pwd = input_password(data["pwd"])
        result = login(user, pwd)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.MINOR)
    @allure.story("测试用户名参数缺失")
    @pytest.mark.parametrize("data", username_none, ids=ids_username_none)
    def test_username_none(self, data):
        """测试缺省用户名"""
        pwd = input_password(data["pwd"])
        result = login(password=pwd)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.MINOR)
    @allure.story("测试密码参数缺失")
    @pytest.mark.parametrize("data", password_none, ids=ids_password_none)
    def test_password_none(self, data):
        """测试缺省密码"""
        user = input_username(data["user"])
        result = login(username=user)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.MINOR)
    @allure.story("测试初始化地址")
    @allure.testcase("https://www.cnblogs.com/linuxchao/", "测试用例地址")
    def test_init_url(self, init_url):
        flag = init_url
        assert flag is True

    @allure.severity(allure.severity_level.NORMAL)
    @allure.story("测试失败用例与用例中添加附件")
    @allure.link("https://www.cnblogs.com/linuxchao/", name="bug链接")
    @allure.description("这是一个一直执行失败的测试用例")
    def test_failed(self):
        """你也可以在这里添加用例的描述信息,但是会被allure.description覆盖"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

    @allure.severity(allure.severity_level.TRIVIAL)
    @allure.story("测试broken用例")
    @allure.issue("https://www.cnblogs.com/linuxchao/", "错误链接")
    def test_broken(self):
        """broken"""
        with open("broken.json", "r", encoding='utf8') as f:
            f.read()

    @allure.severity(allure.severity_level.TRIVIAL)
    @allure.story("测试无条件跳过测试用例")
    @pytest.mark.skip(reason="无条件跳过")
    def test_skip(self):
        """skip"""
        pass


if __name__ == '__main__':
    pytest.main(["-vsq",
                 "--alluredir", "./allure-results", ])
    os.system(r"allure generate --clean ./allure-results -o ./allure-report")

"""
------------------------------------
@Time : 2019/8/28 19:45
@Auth : linux超
@File : test_allure_fixture.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
import pytest
import os
import allure


def function_scope_step():
    print("function_scope_step")


def class_scope_step():
    print("class_scope_step")


def module_scope_step():
    print("module_scope_step")


def session_scope_step():
    print("session_scope_step")


def step_inside_test_body():
    print("step_inside_test_body")


@pytest.fixture(params=[True, False], ids=['param_true', 'param_false'])
def function_scope_fixture_with_finalizer(request):
    if request.param:
        print('True')
    else:
        print('False')

    def function_scope_finalizer():
        function_scope_step()

    request.addfinalizer(function_scope_finalizer)


@pytest.fixture(scope='class')
def class_scope_fixture_with_finalizer(request):
    def class_finalizer_fixture():
        class_scope_step()

    request.addfinalizer(class_finalizer_fixture)


@pytest.fixture(scope='module')
def module_scope_fixture_with_finalizer(request):
    def module_finalizer_fixture():
        module_scope_step()

    request.addfinalizer(module_finalizer_fixture)


@pytest.fixture(scope='session')
def session_scope_fixture_with_finalizer(request):
    def session_finalizer_fixture():
        session_scope_step()

    request.addfinalizer(session_finalizer_fixture)


@allure.severity(allure.severity_level.BLOCKER)
@allure.feature("fixture场景")
class TestClass(object):

    def test_with_scoped_finalizers(self,
                                    function_scope_fixture_with_finalizer,
                                    class_scope_fixture_with_finalizer,
                                    module_scope_fixture_with_finalizer,
                                    session_scope_fixture_with_finalizer):
        step_inside_test_body()


if __name__ == '__main__':
    pytest.main(["-vsq",
                 "--alluredir", "./allure-results", ])
    os.system(r"allure generate --clean ./allure-results -o ./allure-report")

[
  {
    "name": "Ignored tests",
    "matchedStatuses": ["skipped"]
  },
  {
    "name": "Infrastructure problems",
    "matchedStatuses": ["broken", "failed"],
    "messageRegex": ".*bye-bye.*"
  },
  {
    "name": "Outdated tests",
    "matchedStatuses": ["broken"],
    "traceRegex": ".*FileNotFoundException.*"
  },
  {
    "name": "Product defects",
    "matchedStatuses": ["failed"]
  },
  {
    "name": "Test defects",
    "matchedStatuses": ["broken"]
  }
]

Browser=Chrome
Browser.Version=63.0
Stand=Production
ApiUrl=127.0.0.1/login
python.Version=3.6

"""
------------------------------------
@Time : 2019/9/3 14:21
@Auth : linux超
@File : run.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : 28174043@qq.com
@GROUP: 878565760
------------------------------------
"""
import pytest
import os


if __name__ == '__main__':
    pytest.main(["-sq",
                 "--alluredir", "./allure-results"])
    os.system(r"allure generate --clean allure-results -o allure-report")

目录结构

Allure特性

Environment

在Allure报告中添加环境信息,通过创建environment.properties或者environment.xml文件,并把文件存放到allure-results(这个目录是生成最后的html报告之前,生成依赖文件的目录)目录下

environment.properties

Browser=Chrome
Browser.Version=63.0
Stand=Production
ApiUrl=127.0.0.1/login
python.Version=3.6

或者

environment.xml

<environment>
    <parameter>
        <key>Browser</key>
        <value>Chrome</value>
    </parameter>
    <parameter>
        <key>Browser.Version</key>
        <value>63.0</value>
    </parameter>
    <parameter>
        <key>Stand</key>
        <value>Production</value>
    </parameter>
        <parameter>
        <key>ApiUrl</key>
        <value>127.0.0.1/login</value>
    </parameter>
        <parameter>
        <key>python.Version</key>
        <value>3.6</value>
    </parameter>
</environment>

执行run.py查看报告

Categories

测试报告默认统计两种类型的测试用例结果,失败的用例和故障测试用例,我们可以自定义添加用例的统计类型,同样需要在allure-results目录下新建categories.json文件

[
  {
    "name": "Ignored tests",
    "matchedStatuses": ["skipped"]
  },
  {
    "name": "Infrastructure problems",
    "matchedStatuses": ["broken", "failed"],
    "messageRegex": ".*bye-bye.*"
  },
  {
    "name": "Outdated tests",
    "matchedStatuses": ["broken"],
    "traceRegex": ".*FileNotFoundException.*"
  },
  {
    "name": "Product defects",
    "matchedStatuses": ["failed"]
  },
  {
    "name": "Test defects",
    "matchedStatuses": ["broken"]
  }
]

执行run.py查看报告

Fixtures and Finalizers

Fixtures和Finalizers是pytest在测试开始和测试结束调用的方法,allure会自动跟踪每一个fixture的调用,并且详细显示会调用哪些fixture和参数,而且会保留正确的调用顺数

测试代码

test_allure_html.py

def function_scope_step():
    print("function_scope_step")


def class_scope_step():
    print("class_scope_step")


def module_scope_step():
    print("module_scope_step")


def session_scope_step():
    print("session_scope_step")


def step_inside_test_body():
    print("step_inside_test_body")


@pytest.fixture(params=[True, False], ids=['param_true', 'param_false'])
def function_scope_fixture_with_finalizer(request):
    if request.param:
        print('True')
    else:
        print('False')

    def function_scope_finalizer():
        function_scope_step()

    request.addfinalizer(function_scope_finalizer)


@pytest.fixture(scope='class')
def class_scope_fixture_with_finalizer(request):
    def class_finalizer_fixture():
        class_scope_step()

    request.addfinalizer(class_finalizer_fixture)


@pytest.fixture(scope='module')
def module_scope_fixture_with_finalizer(request):
    def module_finalizer_fixture():
        module_scope_step()

    request.addfinalizer(module_finalizer_fixture)


@pytest.fixture(scope='session')
def session_scope_fixture_with_finalizer(request):
    def session_finalizer_fixture():
        session_scope_step()

    request.addfinalizer(session_finalizer_fixture)


class TestClass(object):

    def test_with_scoped_finalizers(self,
                                    function_scope_fixture_with_finalizer,
                                    class_scope_fixture_with_finalizer,
                                    module_scope_fixture_with_finalizer,
                                    session_scope_fixture_with_finalizer):
        step_inside_test_body()

执行run.py查看报告

@allure.step

pytest支持使用@allure.step修饰某些测试用例中需要的函数,使测试用例在allure报告中能够更加详细的显示测试过程

测试代码

test_allure_feature.py文件中修改如下代码

@allure.step("输入用户名")  
def input_username():
    print("输入用户名")


@allure.step("输入密码")
def input_password():
    print("输入密码")

执行run.py查看报告

conftest.py

@allure.step修饰的测试步骤还支持在conftest.py文件中定义,作为fixture的步骤,现在我们在项目目录下新建conftest.py文件,写入如下代码

执行run.py查看报告

allure.attach

使用allure.attach可以给报告中添加文件,图片,log,html代码等等。 我们修改test_allure_feature.py中如下用例, 并在用例所在目录添加attach.png图片

  def test_failed(self):
        """failed"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

执行run.py查看报告

@allure.description

如果你想在报告中展示测试用例的描述信息,那么你可以使用@allure.description(string)或者@allure.description_html(html代码)修饰你的测试用例,test_allure_feature.py文件修改如下代码

 @allure.description("这是一个一直执行失败的测试用例")
    def test_failed(self):
        """你也可以在这里添加用例的描述信息,但是会被allure.description覆盖"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

执行run.py查看报告

@allure.title

使用allure.title(title)可以重命名测试用例在allure报告中的名称,test_allure_feature.py文件修改如下代码

  @allure.title("登录成功场景-{data}")
    @pytest.mark.parametrize("data", login_success_data, ids=ids_login_success_data)
    def test_login_success(self, data):
        """测试登录成功"""
        user = input_username(data["user"])
        pwd = input_password(data["pwd"])
        result = login(user, pwd)
        assert result == data["expected"]

@allure.link

@allure.testcase

@allure.issue

这三种特性都可以给测试用例添加一个链接,test_allure_feature.py文件修改如下代码

  @allure.testcase("https://www.cnblogs.com/linuxchao/", "测试用例地址")
    def test_init_url(self, init_url):
        flag = init_url
        assert flag == True

    @allure.link("https://www.cnblogs.com/linuxchao/", name="bug链接")
    @allure.description("这是一个一直执行失败的测试用例")
    def test_failed(self):
        """你也可以在这里添加用例的描述信息,但是会被allure.description覆盖"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

    @allure.issue("https://www.cnblogs.com/linuxchao/", "错误链接")
    def test_broken(self):
        """broken"""
        with open("broken.json", "r", encoding='utf8') as f:
            f.read()

执行run.py查看报告

 

 

@allure.feature

@allure.story

feature和story被称为行为驱动标记,因为使用这个两个标记,通过报告可以更加清楚的掌握每个测试用例的功能和每个测试用例的测试场景

在test_allure_feature.py文件中的测试类使用@allure.feature修饰, 测试方法使用@allure.story修饰

执行run.py查看报告

 以上两种标记不仅仅能够在测试报告中显示,而且还可以使用命令执行指定的测试模块或者场景

@allure.severity

此标记用来标识测试用例或者测试类的级别,分为blocker,critical,normal,minor,trivial5个级别,下面们把测试用例按级别标记,并查看一下测试报告

总结

以上就是所有的allure-pytest插件在pytest中支持的大部分功能特性,也许整理的不是很详细,所以如果你想详细的了解具体的特性在报告中的效果,还需自己动手尝试一下,附上本文参考链接

这可能是B站最详细的pytest自动化测试框架教程,整整100小时,全程实战!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1167181.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# list<T>去重

文章目录 C# list<T>去重值类型去重List<object>object is intobject is decimalobject is charobject is boolobject is string List<int>List<string> 引用类型去重 C# list去重 值类型去重 List object is int //object is intList<object&g…

【华为数通HCIP | 网络工程师】821-BGP高频题、易错题(1)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;喜欢编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️ 零…

如何进行有效的成本控制?

如何进行有效的成本控制&#xff1f; 接下来我会通过一些例子为大家深入浅出的讲讲生产制造业是如何进行成本控制的&#xff0c;下面用到的图片和系统都来自简道云的生产管理系统 这也是我们公司目前正在用的生产管理系统&#xff0c;是我们团队自己搭建的&#xff0c;在这里…

经典二叉树试题(一)

文章目录 一、相同的树1、题目介绍2、思路讲解3、代码演示 二、对称二叉树1、题目介绍2、思路讲解3、代码演示 三、二叉树的最大深度1、题目介绍2、思路讲解3、代码演示 四、左子树之和1、题目介绍2、思路讲解3、代码演示 五、平衡二叉树1、题目介绍2、思路讲解3、代码演示 六、…

使用C++的QT框架实现五子棋

最近有点无聊正好想玩五子棋&#xff0c;那就实现一下这个游戏吧&#xff0c;网上的五子棋逻辑又长又复杂&#xff0c;我这个逻辑还是蛮简单的&#xff0c;展示如下 这是一个简单的五子棋&#xff0c;今天就了解一下这个游戏的思路&#xff0c;使用的是QT框架&#xff0c;只要思…

企业寄件平台一站式管理教程

企业寄件管理平台的诞生&#xff0c;有两大影响因素&#xff1a; 1、企业寄件管理在企业管理体系中越发重要 随着互联网和快递业的发展&#xff0c;企业对外业务开始依托网络、快递。因公寄件在企业中已经是常事&#xff0c;这几年疫情的影响下&#xff0c;越发明显。寄合同、…

活动回顾|OpenTiny 参与线下大会:共创开源未来,助力低代码技术创新

前言 10月下旬 OpenTiny 社区有幸参与了中国开源年会 COSCon’23及华为云开发者日南京站活动。中国开源年会 COSCon’23活动于2023年10月28日至29日在成都菁蓉汇举行&#xff0c;以“科技向善”为指引&#xff0c;旨在推动开源技术和社区的发展&#xff0c;加强产学研合作&…

基于单片机的无线报警系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、整体设计方案二、 系统的总体方案论证与设计2.1系统的功能要求2.2 系统的技术要求2.3 系统的方案论证及设计2.3.…

PHP进销存ERP系统源码

PHP进销存ERP系统源码 系统介绍&#xff1a; 扫描入库库存预警仓库管理商品管理供应商管理。 1、电脑端手机端&#xff0c;手机实时共享&#xff0c;手机端一目了然。 2、多商户Saas营销版 无限开商户&#xff0c;用户前端自行注册&#xff0c;后台管理员审核开通 3、管理…

更快更准 | YOLOv3算法超详细解析(包括诞生背景+论文解析+技术原理等)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。YOLOv3是一种基于深度学习的目标检测算法&#xff0c;它可以快速而准确地在图像中检测出多个目标。它是由Joseph Redmon和Ali Farhadi在2018年提出的&#xff0c;是YOLO&#xff08;You Only Look Once&#xff09;系列算法…

写了上千篇文章总结出来的高质量文章内容要点

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f34a; 1. 确定文章主题&#x1f34a; 2. 确定目标读者&#x1f34a; 3. 研究资料和信息&#x1f34a; 4. 制定写作计划&#x1f34a; 5. 确定文章结构&#x1f389; 5.1引言&#x1f389; 5.2主体&#x1f389; 5.…

学习笔记|正负偏态的转换方法|对数转换|正态得分法|适用条件|《小白爱上SPSS》课程:加餐 | 如何将非正态分布数据转换为正态分布的?手把手教你SPSS操作

目录 学习目的软件版本原始文档将非正态分布数据转换为正态分布一、正负偏态的转换方法&#xff08;一&#xff09;正偏态数据转换方法&#xff08;二&#xff09;负偏态数据转换方法 三、正态性检验&#xff08;一&#xff09;操作如下&#xff08;二&#xff09;结果解读四、…

CTF工具PDF隐写神器wbStego4open安装和详细使用方法

wbStego4open安装和详细使用方法 1.wbStego4open介绍&#xff1a;2.wbStego4open下载&#xff1a;3.wbStego4open原理图&#xff1a;4.wbStego4open使用教程&#xff1a;第一步&#xff1a;第二步&#xff1a;第三步&#xff1a;第四步&#xff1a;第五步&#xff1a; 5.wbSteg…

电脑版WPS怎么将更新目录加到快速访问栏

效果 步骤 开启首页的“标签”、快速访问、在最近置顶展示然后选择好目录点击右边的设置 》 添加标签选中“快速访问”&#xff0c;确定并关闭完成 相关 WPS怎样设置快速访问工具栏 WPS怎样设置快速访问工具栏-百度经验WPS怎样设置快速访问工具栏,WPS怎样设置快速访问工具栏…

实现dialog在页面随意拖拽

实现dialog在页面随意拖拽 1.先建一个文件如图所示&#xff1a; 文件名:dialog-directive.js 文件内容&#xff1a; import Vue from vue // v-dialogDrag: 弹窗拖拽Vue.directive(dialogDrag, {bind(el, binding, vnode, oldVnode) {// 获取拖拽内容的头部const dialogHeade…

中国联通携手华为助力长城精工启动商用5G-A柔性产线

[中国&#xff0c;河北&#xff0c;2023年11月3日] 近日&#xff0c;中国联通携手华为助力精诚工科汽车系统有限公司保定自动化技术分公司&#xff08;简称长城精工自动化&#xff09;启动5G-A超高可靠性超低时延柔性产线的商用阶段。 在河北保定精工自动化工厂&#xff0c;5G…

java入门,java数据结构二叉树结构

一、前言 树结构是计算机各种存储和查询算法的基本结构。但是在学习这个数据结构的时候&#xff0c;很少人知道它有什么运用&#xff0c;因为在学的时候&#xff0c;也是纯数学的讲解。博主当时学的时候也是云里雾里&#xff0c;最经典的就是严蔚敏和吴伟民的那本《C语言数据结…

python自动化运维——模拟键盘鼠标重复性操作Pyautoui

一、程序样式展示 将程序与cmd.xls文件放在同一文件夹&#xff0c;每一步的截图也放在当前文件夹 通过图片在屏幕上面进行比对&#xff0c;找到点击处进行自动化操作 自动化rpa测试 二、核心点 1.Pyautoui模块&#xff1a;主要针对图片进行定位pyautogui.locateCenterOnScree…

重新理解数字化采购:一场企业内的数字化战役

在显性的采购商品成本之外&#xff0c;越来越多企业开始发现采购环节里高昂的供应链隐性成本&#xff0c;这些成本几乎分布在链条和经营的每个节点&#xff1a;供应商管理、物流履约&#xff0c;售前、售后以及最前端的系统对接搭建等等。 换言之&#xff0c;若想做好数字化采…

智能电表瞬时电量是什么意思?

智能电表已经成为我们进行能源管理的重要工具。其中&#xff0c;瞬时电量这一概念逐渐走进大众视野。那么&#xff0c;智能电表瞬时电量究竟是什么意思&#xff1f;它对我们的生活和能源管理又有哪些影响呢&#xff1f;下面&#xff0c;小编就来为大家介绍一下瞬时电量&#xf…