范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Pythonpytest

  目录 快速入门简单示例setup和teardown配置文件 进阶跳过用例标记预期失败参数化 固件什么是固件作用域预处理和后处理 常用插件pytest测试报告插件allure控制用例执行顺序失败重试并发执行pytest-sugarpytest-cov 常见问题 返回测试目录 快速入门#
  pytest是Python的单元测试框架,同自带的unittest框架类似,但pytest框架使用起来更简洁,效率更高。
  pytest特点 入门简单易上手,文档支持较好。 支持单元测试和功能测试。 支持参数化。 可以跳过指定用例,或对某些预期失败的case标记成失败。 支持重复执行失败的case。 支持运行由unittest编写的测试用例。 有很多第三方插件,并且可自定义扩展。 方便和支持集成工具进行集成。
  安装 pip install pytest
  测试 C:UsersAnthony>pytest --version This is pytest version 5.2.2, imported from c:python36libsite-packagespytest.py
  在测试之前要做的准备
  我的演示脚本处于这样一个的目录中: M:py_tests # 我的是M盘的 py_tests 目录,所有操作都在 py_tests 目录内完成      scripts            test_case_dir1            test_case_02.py    # 用例脚本文件            __init__.py         test_allure_case.py   # 脚本文件         test_case_01.py   # 脚本文件         __init__.py      report         report.html   # pytest-html生成的用例报告         assets  # allure的依赖目录         result  # allure生成的用例数据         allure_html   # allure生成的用例报告目录     |      index.html  # allure生成的最终的html类型的测试报告        case_set.py      demo0.py   # 用例脚本文件      demo1.py   # 用例脚本文件      pytest.ini  # 配置文件      __init__.py
  踩坑:你创建的pytest脚本名称中不允许含有 .  ,比如1.简单上手.py  ,这样会报错。当然,可以这么写1-简单上手.py  简单示例#
  demo1.py :import pytest  def test_case01():     print("执行用例01.......")     assert 0  # 断言失败  def test_case02():     print("执行用例02.......")     assert 1  # 断言成功      def custom_case03():     print("执行用例03.......")     assert 1  # 断言成功      if __name__ == "__main__":     pytest.main(["-s", "demo1.py"])     # pytest.main("-s demo1.py")
  上例中,当我们在执行(就像Python解释器执行普通的Python脚本一样)测试用例的时候, pytest.main(["-s", "demo1.py"]) 中的传参需要是一个元组或者列表(我的pytest是5.2.2版本),之前的版本可能需要这么调用pytest.main("-s demo1.py") ,传的参数是str的形式,至于你使用哪种,取决于报不报错:TypeError: `args` parameter expected to be a list or tuple of strings, got: "-s demo1.py" (type: )
  遇到上述报错,就是参数需要一个列表或者元组的形式,而我们使用的是str形式。
  上述代码正确的执行结果是这样的: ===================================================== test session starts ====================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests collected 2 items                                                                                                                 demo1.py 执行用例01....... F执行用例02....... .  =========================================================== FAILURES =========================================================== _________________________________________________________ test_case01 __________________________________________________________      def test_case01():         print("执行用例01.......") >       assert 0  # 断言失败 E       assert 0  demo1.py:11: AssertionError ================================================= 1 failed, 1 passed in 0.13s ==================================================
  大致的信息就是告诉我们: collected 2 items :本次执行中,收集了2个用例。完了开始执行用例, . 表示执行成功,F 表示执行失败。脚本中的第一个用例执行失败;第二个用例执行成功;但是第三个也就是 custom_case03 并没有执行,由此我们知道,pytest只识别以test_  开头的用例。
  pytest.main(["-s", "demo1.py"])参数说明 -s ,在控制台中输出print的结果,有些情况下,ptest不会展示print的输出,所以使用-s 参数来实现。demo1.py 是要执行的脚本名称。
  除了上述的函数这种写法,也可以有用例类的写法: import pytest  class TestCase(object):      def test_case01(self):         """ 用例 01 """         print("执行用例01.......")         assert 0  # 断言失败      def test_case02(slef):         """ 用例 02 """         print("执行用例02.......")         assert 1  # 断言成功  if __name__ == "__main__":     pytest.main(["-s", "demo1.py"])
  用法跟unittest差不多,类名要以 Test 开头,并且其中的用例方法也要以test 开头,然后执行也一样。
  执行结果: M:py_tests>python demo1.py ========================================================== test session starts =========================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests collected 2 items                                                                                                                           demo1.py 执行用例01....... F执行用例02....... .  ================================================================ FAILURES ================================================================ __________________________________________________________ TestCase.test_case01 __________________________________________________________  self =       def test_case01(self):         """ 用例 01 """         print("执行用例01.......") >       assert 0  # 断言失败 E       assert 0  demo1.py:49: AssertionError ====================================================== 1 failed, 1 passed in 0.12s =======================================================
  那么,你这个时候可能会问,我记得unittest中有setup和teardown的方法,难道pytest中没有嘛?你怎么提都不提?稳住,答案是有的。
  接下来,我们来研究一下pytest中的setup和teardown的用法。 setup和teardown#
  我们知道,在unittest中,setup和teardown可以在每个用例前后执行,也可以在所有的用例集执行前后执行。那么在pytest中,有以下几种情况: 模块级别,也就是在整个测试脚本文件中的用例集开始前后,对应的是:setup_moduleteardown_module 类级别,在类中的所有用例集执行前后,对应的是:setup_classteardown_class 在类中呢,也可以在进一步划分,在每一个方法执行前后,对应:setup_methodteardown_method 函数级别,在用例函数之前后,对应:setup_functionteardown_function
  来一一看看各自的用法。
  模块级别setup_module/teardown_module import pytest   def setup_module():     """ 模块级别的 setup,在该脚本内所有用例集执行之前触发执行 """     print("模块级别的 setup.....")  def test_case01():     print("执行用例01.......")     assert 0  # 断言失败  def test_case02():     print("执行用例02.......")     assert 1  # 断言成功  def teardown_module():     """ 模块级别的 teardown,在该脚本内所有用例集执行之后触发执行 """     print("模块级别的 teardown.....")  if __name__ == "__main__":     pytest.main(["-s", "demo1.py"])
  执行结果: M:py_tests>python demo1.py ========================================================== test session starts =========================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests collected 2 items                                                                                                                           demo1.py 模块级别的 setup..... 执行用例01....... F执行用例02....... .模块级别的 teardown.....   ================================================================ FAILURES ================================================================ ______________________________________________________________ test_case01 _______________________________________________________________      def test_case01():         print("执行用例01.......") >       assert 0  # 断言失败 E       assert 0  demo1.py:16: AssertionError ====================================================== 1 failed, 1 passed in 0.12s =======================================================
  类级别的setup_class/teardown_class import pytest  class TestCase(object):      def setup_class(self):         """ 类级别的 setup,在该类中内用例集执行之前触发执行 """         print("类级别的 setup.....")      def teardown_class(self):         """ 类级别的 teardown,在该类中内用例集执行之后触发执行 """         print("类级别的 teardown.....")      def test_case01(self):         """ 用例 01 """         print("执行用例01.......")         assert 0  # 断言失败      def test_case02(slef):         """ 用例 02 """         print("执行用例02.......")         assert 1  # 断言成功  if __name__ == "__main__":     pytest.main(["-s", "demo1.py"])
  执行结果: M:py_tests>python demo1.py ========================================================== test session starts =========================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests collected 2 items                                                                                                                           demo1.py 类级别的 setup..... 执行用例01....... F执行用例02....... .类级别的 teardown.....   ================================================================ FAILURES ================================================================ __________________________________________________________ TestCase.test_case01 __________________________________________________________  self =       def test_case01(self):         """ 用例 01 """         print("执行用例01.......") >       assert 0  # 断言失败 E       assert 0  demo1.py:53: AssertionError ====================================================== 1 failed, 1 passed in 0.10s =======================================================
  类中方法级别的setup_method/teardown_method import pytest  class TestCase(object):      def setup_method(self):         """ 类中方法级别的 setup,在该类中内每个用例执行之前触发执行 """         print("类中方法级别的 setup.....")      def teardown_method(self):         """ 类中方法级别的 teardown,在该类中内每个用例执行之后触发执行 """         print("类中方法级别的 teardown.....")      def test_case01(self):         """ 用例 01 """         print("执行用例01.......")         assert 0  # 断言失败      def test_case02(slef):         """ 用例 02 """         print("执行用例02.......")         assert 1  # 断言成功  if __name__ == "__main__":     pytest.main(["-s", "demo1.py"])
  执行结果: M:py_tests>python demo1.py ========================================================== test session starts =========================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests collected 2 items                                                                                                                           demo1.py 类中方法级别的 setup..... 执行用例01....... F类中方法级别的 teardown..... 类中方法级别的 setup..... 执行用例02....... .类中方法级别的 teardown.....   ================================================================ FAILURES ================================================================ __________________________________________________________ TestCase.test_case01 __________________________________________________________  self =       def test_case01(self):         """ 用例 01 """         print("执行用例01.......") >       assert 0  # 断言失败 E       assert 0  demo1.py:49: AssertionError ====================================================== 1 failed, 1 passed in 0.42s =======================================================
  函数级别的setup_function/teardown_function import pytest  def setup_function():     """ 函数级别的 setup,在该脚本内每个用例函数执行之前触发执行 """     print("函数级别的 setup.....")  def test_case01():     print("执行用例01.......")     assert 0  # 断言失败  def test_case02():     print("执行用例02.......")     assert 1  # 断言成功  def teardown_function():     """ 函数级别的 teardown,在该脚本内每个用例函数执行之后触发执行 """     print("函数级别的 teardown.....")   if __name__ == "__main__":     pytest.main(["-s", "demo1.py"])
  执行结果: M:py_tests>python demo1.py ========================================================== test session starts =========================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests collected 2 items                                                                                                                           demo1.py 函数级别的 setup..... 执行用例01....... F函数级别的 teardown..... 函数级别的 setup..... 执行用例02....... .函数级别的 teardown.....   ================================================================ FAILURES ================================================================ ______________________________________________________________ test_case01 _______________________________________________________________      def test_case01():         print("执行用例01.......") >       assert 0  # 断言失败 E       assert 0  demo1.py:16: AssertionError ====================================================== 1 failed, 1 passed in 0.11s =======================================================
  小结 在类中,不需要 __init__ 方法。测试类的类名必须以 Test 开头。类中的测试方法编写规则跟函数一致。 配置文件#
  该脚本有多种运行方式,如果处于PyCharm环境,可以使用右键或者点击运行按钮运行,也就是在pytest中的主函数中运行: if __name__ == "__main__":     pytest.main(["-s", "demo1.py"])   # 就是调用的 pytest 的 main 函数
  也可以在命令行中运行: M:py_tests>python demo1.py
  这种方式,跟使用Python解释器执行Python脚本没有什么两样。也可以如下面这么执行: M:py_tests>pytest -s demo1.py
  当然,还有一种是使用配置文件运行,来看看怎么用。
  在项目的根目录下,我们可以建立一个 pytest.ini 文件,在这个文件中,我们可以实现相关的配置:[pytest] addopts = -s -v testpaths = ./scripts python_files = test_*.py python_classes = Test* python_functions = test_*
  注意,配置文件中不许有中文
  那这个配置文件中的各项都是什么意思呢?
  首先, pytest.ini 文件必须位于项目的根目录,而且也必须叫做pytest.ini 。
  其他的参数: addopts 可以搭配相关的参数,比如-s 。多个参数以空格分割,其他参数后续用到再说。-s ,在运行测试脚本时,为了调试或打印一些内容,我们会在代码中加一些print内容,但是在运行pytest时,这些内容不会显示出来。如果带上-s,就可以显示了。-v ,使输出结果更加详细。testpaths 配置测试用例的目录,因为我们用例可能分布在不同的目录或文件中,那么这个 scripts 就是我们所有文件或者目录的顶层目录。其内的子文件或者子目录都要以test_ 开头,pytest才能识别到。另外,上面这么写,是从一个总目录下寻找所有的符合条件的文件或者脚本,那么我们想要在这个总目录下执行其中某个具体的脚本文件怎么办? [pytest] testpaths = ./scripts/ python_files = test_case_01.py 这么写就是执行scripts 目录下面的test_case_01.py 这个文件。python_classes 则是说明脚本内的所有用例类名必须是以Test 开头,当然,你也可以自定义为以Test_ 开头,而类中的用例方法则当然是以test_ 开头。python_functions 则是说脚本内的所有用例函数以test_ 开头才能识别。
  OK,来个示例。
  首先,(详细目录参考开头的目录结构)在 scripts/test_case_01.py 中:import pytest  def test_case01():     print("执行用例01.......")     assert 1  # 断言成功  def test_case02():     print("执行用例02.......")     assert 1  # 断言成功  class TestCaseClass(object):      def test_case_03(self):         assert 0  # 断言失败
  在 scripts/test_case_dir1/test_case02.py 中:import pytest  def test_case_04():     assert 1  # 断言成功      def test_case_05():     assert 0  # 断言失败
  那么,在不同的目录或者文件中,共有5个用例将被执行,而结果则是两个失败三个成功。来执行验证一下,因为有了配置文件,我们在终端中(前提是在项目的根目录),直接输入 pytest 即可。M:py_tests>pytest ======================================================= test session starts ======================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests, inifile: pytest.ini, testpaths: ./scripts collected 5 items                                                                                                                     scripts	est_case_01.py 执行用例01....... .执行用例02....... .F scripts	est_case_dir1	est_case_02.py .F  ============================================================= FAILURES ============================================================= ____________________________________________________ TestCaseClass.test_case_03 ____________________________________________________  self =       def test_case_03(self): >       assert 0 E       assert 0  scripts	est_case_01.py:22: AssertionError ___________________________________________________________ test_case_05 ___________________________________________________________      def test_case_05(): >       assert 0 E       assert 0  scripts	est_case_dir1	est_case_02.py:14: AssertionError =================================================== 2 failed, 3 passed in 0.14s ====================================================
  由执行结果可以发现, 2 failed, 3 passed ,跟我们的预期一致。
  后续执行相关配置都来自配置文件,如果更改,会有相应说明,终端都是直接使用 pytest 执行。进阶#跳过用例#
  我们知道在unittest中,跳过用例可以用 skip ,那么这同样是适用于pytest。
  来看怎么使用: import pytest  @pytest.mark.skip(condition="我就是要跳过这个用例啦") def test_case_01():     assert 1  @pytest.mark.skipif(condition=1 < 2, reason="如果条件为true就跳过用例") def test_case_02():     assert 1
  跳过用例,我们使用 @pytest.mark.skipif(condition, reason) :condition表示跳过用例的条件。 reason表示跳过用例的原因。
  然后将它装饰在需要被跳过用例的的函数上面。
  效果如下: M:py_tests>pytest                                                                                                                     scripts/test_allure_case.py::test_case_01 SKIPPED scripts/test_allure_case.py::test_case_02 SKIPPED  =========================================================== 2 skipped in 0.14s ===========================================================
  上例执行结果相对详细,因为我们在配置文件中为 addopts 增加了-v ,之前的示例结果中,没有加!
  另外,此时,在输出的控制台中, 还无法打印出reason 信息,如果需要打印,则可以在配置文件中的addopts 参数的-s 变为-rs :[pytest] addopts = -rs -v testpaths = ./scripts python_files = test_*.py python_classes = Test* python_functions = test_* 标记预期失败#
  如果我们事先知道测试函数会执行失败,但又不想直接跳过,而是希望显示的提示。
  Pytest 使用  pytest.mark.xfail 实现预见错误功能::xfail(condiition, reason, [raises=None, run=True, strict=False])
  需要掌握的必传参数的是: condition,预期失败的条件,当条件为真的时候,预期失败。 reason,失败的原因。
  那么关于预期失败的几种情况需要了解一下: 预期失败,但实际结果却执行成功。 预期失败,实际结果也执行执行失败。
  来看示例: import pytest   class TestCase(object):      @pytest.mark.xfail(1 < 2, reason="预期失败, 执行失败")     def test_case_01(self):         """ 预期失败, 执行也是失败的 """         print("预期失败, 执行失败")         assert 0      @pytest.mark.xfail(1 < 2, reason="预期失败, 执行成功")     def test_case_02(self):         """ 预期失败, 但实际执行结果却成功了 """         print("预期失败, 执行成功")         assert 1
  结果如下: M:py_tests>pytest ========================================================== test session starts =========================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests, inifile: pytest.ini, testpaths: ./scripts/ plugins: allure-pytest-2.8.6, cov-2.8.1, forked-1.1.3, html-2.0.0, metadata-1.8.0, ordering-0.6, rerunfailures-7.0, xdist-1.30.0 collected 2 items                                                                                                                           scriptsdemo1.py xX                                                                                                                 [100%]  ===================================================== 1 xfailed, 1 xpassed in 0.15s =================================================
  pytest 使用  x  表示预见的失败(XFAIL)。
  如果预见的是失败,但实际运行测试却成功通过,pytest 使用  X  进行标记(XPASS)。
  而在预期失败的两种情况中,我们不希望出现预期失败,结果却执行成功了的情况出现,因为跟我们想的不一样嘛,我预期这条用例失败,那这条用例就应该执行失败才对,你虽然执行成功了,但跟我想的不一样,你照样是失败的!
  所以,我们需要将预期失败,结果却执行成功了的用例标记为执行失败,可以在 pytest.ini 文件中,加入:[pytest] xfail_strict=true
  这样就就把上述的情况标记为执行失败了。 参数化#
  pytest身为强大的单元测试框架,那么同样支持DDT数据驱动测试的概念。也就是当对一个测试函数进行测试时,通常会给函数传递多组参数。比如测试账号登陆,我们需要模拟各种千奇百怪的账号密码。
  当然,我们可以把这些参数写在测试函数内部进行遍历。不过虽然参数众多,但仍然是一个测试,当某组参数导致断言失败,测试也就终止了。
  通过异常捕获,我们可以保证程所有参数完整执行,但要分析测试结果就需要做不少额外的工作。
  在 pytest 中,我们有更好的解决方法,就是参数化测试,即每组参数都独立执行一次测试。使用的工具就是  pytest.mark.parametrize(argnames, argvalues) 。argnames表示参数名。 argvalues表示列表形式的参数值。
  使用就是以装饰器的形式使用。
  只有一个参数的测试用例 import pytest  mobile_list = ["10010", "10086"]  @pytest.mark.parametrize("mobile", mobile_list) def test_register(mobile):     """ 通过手机号注册 """     print("注册手机号是: {}".format(mobile))
  来看(重要部分)结果:: M:py_tests>pytest scripts/test_case_01.py::test_register[10010] 注册手机号是: 10010 PASSED scripts/test_case_01.py::test_register[10086] 注册手机号是: 10086 PASSED  ====================================================== 2 passed in 0.11s ======================================================
  可以看到,列表内的每个手机号,都是一条测试用例。
  多个参数的测试用例 import pytest  mobile_list = ["10010", "10086"] code_list = ["x2zx", "we2a"]  @pytest.mark.parametrize("mobile", mobile_list) @pytest.mark.parametrize("code", code_list) def test_register(mobile, code):     """ 通过手机号注册 """     print("注册手机号是: {} 验证码是: {}".format(mobile, code))
  (重要部分)结果: M:py_tests>pytest                              scripts/test_case_01.py::test_register[x2zx-10010] 注册手机号是: 10010 验证码是: x2zx PASSED scripts/test_case_01.py::test_register[x2zx-10086] 注册手机号是: 10086 验证码是: x2zx PASSED scripts/test_case_01.py::test_register[we2a-10010] 注册手机号是: 10010 验证码是: we2a PASSED scripts/test_case_01.py::test_register[we2a-10086] 注册手机号是: 10086 验证码是: we2a PASSED  ====================================================== 4 passed in 0.17s =======================================================
  可以看到,每一个手机号与每一个验证码都组合一起执行了,这样就执行了4次。那么如果有很多个组合的话,用例数将会更多。我们希望手机号与验证码一一对应组合,也就是只执行两次,怎么搞呢? import pytest  mobile_list = ["10010", "10086"] code_list = ["x2zx", "we2a"]  @pytest.mark.parametrize("mobile,code", zip(mobile_list, code_list)) def test_register(mobile, code):     """ 通过手机号注册 """     print("注册手机号是: {} 验证码是: {}".format(mobile, code))
  在多参数情况下,多个参数名是以 , 分割的字符串。参数值是列表嵌套的形式组成的。M:py_tests>pytest                     scripts/test_case_01.py::test_register[10010-x2zx] 注册手机号是: 10010 验证码是: x2zx PASSED scripts/test_case_01.py::test_register[10086-we2a] 注册手机号是: 10086 验证码是: we2a PASSED  ====================================================== 2 passed in 0.44s ====================================================== 固件#什么是固件#
  固件(Fixture)是一些函数,pytest 会在执行测试函数之前(或之后)加载运行它们,也称测试夹具。
  我们可以利用固件做任何事情,其中最常见的可能就是数据库的初始连接和最后关闭操作。
  Pytest 使用  pytest.fixture()  定义固件,下面是最简单的固件,访问主页前必须先登录:import pytest  @pytest.fixture() def login():     print("登录....")  def test_index(login):     print("主页....")
  结果: M:py_tests>pytest                 scripts/test_case_01.py::test_index 登录.... 主页.... PASSED  ====================================================== 1 passed in 0.13s ======================================================= 作用域#
  在之前的示例中,你可能会觉得,这跟之前的setup和teardown的功能也类似呀,但是,fixture相对于setup和teardown来说更灵活。pytest通过 scope 参数来控制固件的使用范围,也就是作用域。
  在定义固件时,通过  scope  参数声明作用域,可选项有:function : 函数级,每个测试函数都会执行一次固件;class : 类级别,每个测试类执行一次,所有方法都可以使用;module : 模块级,每个模块执行一次,模块内函数和方法都可使用;session : 会话级,一次测试只执行一次,所有被找到的函数和方法都可用。
  默认的作用域为  function 。
  比如之前的login固件,可以指定它的作用域: import pytest  @pytest.fixture(scope="function") def login():     print("登录....")  def test_index(login):     print("主页....") 预处理和后处理#
  很多时候需要在测试前进行预处理(如新建数据库连接),并在测试完成进行清理(关闭数据库连接)。
  当有大量重复的这类操作,最佳实践是使用固件来自动化所有预处理和后处理。
  Pytest 使用  yield  关键词将固件分为两部分,yield  之前的代码属于预处理,会在测试前执行;yield  之后的代码属于后处理,将在测试完成后执行。
  以下测试模拟数据库查询,使用固件来模拟数据库的连接关闭: import pytest  @pytest.fixture() def db():     print("Connection successful")      yield      print("Connection closed")  def search_user(user_id):     d = {         "001": "xiaoming",         "002": "xiaohua"     }     return d[user_id]  def test_case_01(db):     assert search_user("001") == "xiaoming"  def test_case_02(db):     assert search_user("002") == "xiaohua"
  结果: M:py_tests>pytest                      scripts/test_case_01.py::test_case_01 Connection successful PASSEDConnection closed  scripts/test_case_01.py::test_case_02 Connection successful PASSEDConnection closed  ====================================================== 2 passed in 0.15s =======================================================
  可以看到在两个测试用例执行前后都有预处理和后处理。 常用插件#
  pytest中还有非常多的插件供我们使用,我们来介绍几个常用的。
  先来看一个重要的,那就是生成测试用例报告。 pytest测试报告插件#
  想要生成测试报告,首先要有下载,才能使用。
  下载 pip install pytest-html
  https://github.com/pytest-dev/pytest-html
  如果下载失败,可以使用PyCharm下载,怎么用PyCharm下载这里无需多言了吧。
  使用
  在配置文件中,添加参数: [pytest] addopts = -s --html=report/report.html
  完事之后,让我们继续终端中使用 pytest 重新跑测试用例,用例结果就不展示了,跟上面的结果一样,我们关注项目目录下的report/report.html 文件,我们用浏览器打开它,你会发现:
  效果很不错吧!
  没完,看我大招   allure#
  Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简洁的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息。
  从开发人员(dev,developer)和质量保证人员(QA,Quality Assurance)的角度来看,Allure报告简化了常见缺陷的统计:失败的测试可以分为bug和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与TMS和BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。
  从管理者的角度来看,Allure提供了一个清晰的"大图",其中包括已覆盖的特性、缺陷聚集的位置、执行时间轴的外观以及许多其他方便的事情。allure的模块化和可扩展性保证了我们总是能够对某些东西进行微调。
  少扯点,来看看怎么使用。
  Python的pytest中allure下载 pip install allure-pytest
  但由于这个 allure-pytest 插件生成的测试报告不是html 类型的,我们还需要使用allure工具再"加工"一下。所以说,我们还需要下载这个allure工具。
  allure工具下载
  在现在allure工具之前,它依赖Java环境,我们还需要先配置Java环境。
  各平台配置Java环境参考:https://www.cnblogs.com/Neeo/articles/11954283.html
  注意,如果你的电脑已经有了Java环境,就无需重新配置了。
  配置完了Java环境,我们再来下载allure工具,我这里直接给出了百度云盘链接,你也可以去其他链接中自行下载: https://github.com/allure-framework/allure2
  优先选择:https://bintray.com/qameta/maven/allure2
  百度云盘链接:https://pan.baidu.com/s/1Xj1A_xsRscOZHskTR4xjAg 提取码:6b33
  下载并解压好了allure工具包之后,还需要将allure包内的 bin 目录添加到系统的环境变量中。
  完事后打开你的终端测试: C:UsersAnthonyDesktop>allure --version 2.10.0
  返回了版本号说明安装成功。
  使用
  一般使用allure要经历几个步骤: 配置 pytest.ini 文件。编写用例并执行。 使用allure工具生成html报告。
  来看配置 pytest.ini :[pytest] addopts =  -v -s --html=report/report.html --alluredir ./report/result testpaths = ./scripts/ python_files = test_allure_case.py python_classes = Test* python_functions = test_* # xfail_strict=true
  就是 --alluredir ./report/result 参数。
  在终端中输入 pytest 正常执行测试用例即可:import pytest  def test_case_01():     assert 1  def test_case_02():     assert 0  def test_case_03():     assert 1
  执行完毕后,在项目的根目下,会自动生成一个 report 目录,这个目录下有:report.html是我们的之前的 pytest-html 插件生成的HTML报告,跟allure无关。result和assets目录是allure插件生成的测试报告文件,但此时该目录内还没有什么HTML报告,只有一些相关数据。
  接下来需要使用allure工具来生成HTML报告。
  此时我们在终端(如果是windows平台,就是cmd),路径是项目的根目录,执行下面的命令。
  PS:我在pycharm中的terminal输入allure提示"allure" 不是内部或外部命令,也不是可运行的程序或批处理文件。但windows的终端没有问题。 M:py_tests>allure generate report/result -o report/allure_html --clean Report successfully generated to reportallure_html
  命令的意思是,根据 reportresult 目录中的数据(这些数据是运行pytest后产生的)。在report 目录下新建一个allure_html 目录,而这个目录内有index.html 才是最终的allure版本的HTML报告;如果你是重复执行的话,使用--clean 清除之前的报告。
  结果很漂亮:
  allure open
  默认的,allure报告需要HTTP服务器来打开,一般我们可以通过pycharm来完成,另外一种情况就是通过allure自带的open命令来完成。
  allure的其他用法
  当然,故事还是没有完!在使用allure生成报告的时候,在编写用例阶段,还可以有一些参数可以使用: title,自定义用例标题,标题默认是用例名。 description,测试用例的详细说明。 feature和story被称为行为驱动标记,因为使用这个两个标记,通过报告可以更加清楚的掌握每个测试用例的功能和每个测试用例的测试场景。或者你可以理解为feature是模块,而story是该模块下的子模块。 allure中对bug的严重(severity)级别也有定义,allure使用 severity 来标识测试用例或者测试类的bug级别,分为blocker,critical,normal,minor,trivial5个级别。一般,bug分为如下几个级别:Blocker级别:中断缺陷(客户端程序无响应,无法执行下一步操作),系统无法执行、崩溃或严重资源不足、应用模块无法启动或异常退出、无法测试、造成系统不稳定。Critical级别:即影响系统功能或操作,主要功能存在严重缺陷,但不会影响到系统稳定性。比如说一个服务直接不可用了,微信不能发消息,支付宝不能付款这种,打开直接报错。Major:即界面、性能缺陷、兼容性。如操作界面错误(包括数据窗口内列名定义、含义是否一致)、长时间操作无进度提示等。Normal级别:普通缺陷(数值计算错误),是指非核心业务流程产生的问题,比如说知乎无法变更头像,昵称等。这个要看自己的定义。Minor/Trivial级别:轻微缺陷(必输项无提示,或者提示不规范),比如各种影响体验,但不影响使用的内容。dynamic,动态设置相关参数。
  allure.title与allure.description import pytest import allure  @allure.title("测试用例标题1") @allure.description("这是测试用例用例1的描述信息") def test_case_01():     assert 1  def test_case_02():     assert 0  def test_case_03():     assert 1
  feature和story import pytest import allure  @allure.feature("登录模块") class TestCaseLogin(object):      @allure.story("登录模块下的子模块: test1")     def test_case_01(self):         assert 1      @allure.story("登录模块下的子模块: test1")     def test_case_02(self):         assert 1      @allure.story("登录模块下的子模块: test2")     def test_case_03(self):         assert 1      @allure.story("登录模块下的子模块: test3")     def test_case_04(self):         assert 1  @allure.feature("注册模块") class TestCaseRegister(object):     @allure.story("注册模块下的子模块: test1")     def test_case_01(self):         assert 1      @allure.story("注册模块下的子模块: test1")     def test_case_02(self):         assert 1      @allure.story("注册模块下的子模块: test1")     def test_case_03(self):         assert 1      @allure.story("注册模块下的子模块: test2")     def test_case_04(self):         assert 1
  由上图可以看到,不同的用例被分为不同的功能中。
  allure.severity
  allure.severity 用来标识测试用例或者测试类的级别,分为blocker,critical,normal,minor,trivial5个级别。import pytest import allure  @allure.feature("登录模块") class TestCaseLogin(object):      @allure.severity(allure.severity_level.BLOCKER)     def test_case_01(self):         assert 1      @allure.severity(allure.severity_level.CRITICAL)     def test_case_02(self):         assert 1      @allure.severity(allure.severity_level.MINOR)     def test_case_03(self):         assert 1      @allure.severity(allure.severity_level.TRIVIAL)     def test_case_04(self):         assert 1      def test_case_05(self):         assert 1
  severity的默认级别是normal,所以上面的用例5可以不添加装饰器了。
  allure.dynamic import pytest import allure  @allure.feature("登录模块") class TestCaseLogin(object):      @allure.severity(allure.severity_level.BLOCKER)     def test_case_01(self):         assert 1      @allure.severity(allure.severity_level.CRITICAL)     def test_case_02(self):         assert 1      @allure.severity(allure.severity_level.MINOR)     def test_case_03(self):         assert 1      @allure.severity(allure.severity_level.TRIVIAL)     def test_case_04(self):         assert 1     @pytest.mark.parametrize("name", ["动态名称1", "动态名称2"])     def test_case_05(self, name):         allure.dynamic.title(name)
  控制用例执行顺序#
  在之前,用例的执行顺序是从上到下依次执行: import pytest  class TestCaseClass(object):     def test_case_03(self):         print("执行用例03.......")         assert 1  def test_case01():     print("执行用例01.......")     assert 1  # 断成功  def test_case02():     print("执行用例02.......")     assert 1  # 断言成功
  正如上例的执行顺序是 3 1 2 。
  现在,来看看我们如何手动控制多个用例的执行顺序,这里也依赖一个插件。
  下载 pip install pytest-ordering
  使用 import pytest  class TestCaseClass(object):     @pytest.mark.run(order=3)     def test_case_03(self):         print("执行用例03.......")         assert 1  @pytest.mark.run(order=2) def test_case01():     print("执行用例01.......")     assert 1  # 断言成功  @pytest.mark.run(order=1) def test_case02():     print("执行用例02.......")     assert 1  # 断言成功
  手动控制用例执行顺序的方法是在给各用例添加一个装饰器: @pytest.mark.run(order=x)   # x 是一个整数
  那么, 现在的执行顺序是 2 1 3 ,按照order指定的排序执行的。
  如果有人较劲传个0或者负数啥的,那么它们的排序关系应该是这样的: 0 > 正数 > 没有参与的用例 > 负数 # 正数和负数就是按照大小关系排列的 失败重试#
  失败重试意思是指定某个用例执行失败可以重新运行。
  下载 pip install pytest-rerunfailures
  使用
  需要在 pytest.ini 文件中, 配置:[pytest] addopts = -s --html=report/report.html --reruns=3 ;addopts = -s --alluredir ./report/result testpaths = ./scripts/ python_files = test_case_01.py python_classes = Test* python_functions = test_*
  给 addopts 字段新增(其他原有保持不变)--reruns=3 字段,这样如果有用例执行失败,则再次执行,尝试3次。
  来看示例: import pytest  def test_case01():     print("执行用例01.......")     assert 1  # 断言成功  def test_case02():     print("执行用例02.......")     assert 0  # 断言失败,需要重新执行  class TestCaseClass(object):      def test_case_03(self):         print("执行用例03.......")         assert 1
  结果: M:py_tests>pytest ======================================================= test session starts ======================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests, inifile: pytest.ini, testpaths: ./scripts/ plugins: allure-pytest-2.8.6, html-2.0.0, metadata-1.8.0, ordering-0.6, rerunfailures-7.0 collected 3 items                                                                                                                     scripts	est_case_01.py 执行用例01....... .执行用例02....... R执行用例02....... R执行用例02....... R执行用例02....... F执行用例03....... .  ============================================================= FAILURES ============================================================= ___________________________________________________________ test_case02 ____________________________________________________________      def test_case02():         print("执行用例02.......") >       assert 0  # 断言失败,需要重新执行 E       assert 0  scripts	est_case_01.py:19: AssertionError ------------------------------------ generated html file: file://M:py_testsreportreport.html ------------------------------------ =============================================== 1 failed, 2 passed, 3 rerun in 0.20s ===============================================
  我们也可以从用例报告中看出重试的结果:
  上面演示了用例失败了,然后重新执行多少次都没有成功,这是一种情况。
  接下来,来看另一种情况,那就是用例执行失败,重新执行次数内通过了,那么剩余的重新执行的次数将不再执行。 import random import pytest  def test_case01():     print("执行用例01.......")     assert 1  # 断言成功  def test_case02():     print("执行用例02.......")     status = random.randint(0, 2)     if status:         assert 1  # 断言成功,无需再重复执行了     else:         assert 0  # 断言失败,需要重新执行 class TestCaseClass(object):      def test_case_03(self):         print("执行用例03.......")         assert 1
  通过 random 模块帮助我们演示出在某次执行中出现失败的情况,而在重新执行的时候,会出现成功的情况,看结果:M:py_tests>pytest ======================================================= test session starts ======================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 rootdir: M:py_tests, inifile: pytest.ini, testpaths: ./scripts/ plugins: allure-pytest-2.8.6, html-2.0.0, metadata-1.8.0, ordering-0.6, rerunfailures-7.0 collected 3 items                                                                                                                     scripts	est_case_01.py 执行用例01....... .执行用例02....... R执行用例02....... .执行用例03....... .  ------------------------------------ generated html file: file://M:py_testsreportreport.html ------------------------------------ ==================================================== 3 passed, 1 rerun in 0.08s ====================================================
  可以看到,用例 02 重新执行了一次就成功了,剩余的两次执行就终止了。并发执行#
  一条一条用例的执行,肯定会很慢,来看如何并发的执行测试用例,当然这需要相应的插件。
  下载 pip install pytest-xdist
  使用
  在配置文件中添加: [pytest] addopts =  -v -s --html=report/report.html -n=auto ;addopts = -s --alluredir ./report/result testpaths = ./scripts/ python_files = test_case_01.py python_classes = Test* python_functions = test_*
  就是这个 -n=auto :-n=auto ,自动侦测系统里的CPU数目。-n=numprocesses ,也就是自己指定运行测试用例的进程数。
  并发的配置可以写在配置文件中,然后其他正常的执行用例脚本即可。另外一种就是在终端中指定,先来看示例: import pytest  def test_case01():     print("执行用例01.......")     assert 1  # 断言成功   @pytest.mark.skipif(condition= 2 > 1, reason="跳过用例") def test_case02():     print("执行用例02.......")     assert 0  # 断言失败  class TestCaseClass(object):      def test_case_03(self):         print("执行用例03.......")         assert 1      def test_case_04(self):         print("执行用例04.......")         assert 1
  结果: M:py_tests>pytest .scripts	est_case_01.py -s -n auto ======================================================= test session starts ======================================================== platform win32 -- Python 3.6.2, pytest-5.2.2, py-1.8.0, pluggy-0.13.0 -- c:python36python.exe cachedir: .pytest_cache metadata: {"Python": "3.6.2", "Platform": "Windows-10-10.0.14393-SP0", "Packages": {"pytest": "5.2.2", "py": "1.8.0", "pluggy": "0.13 .0"}, "Plugins": {"allure-pytest": "2.8.6", "forked": "1.1.3", "html": "2.0.0", "metadata": "1.8.0", "ordering": "0.6", "rerunfailure s": "7.0", "xdist": "1.30.0"}, "JAVA_HOME": "C:Program FilesJavajdk1.8.0_201"} rootdir: M:py_tests, inifile: pytest.ini plugins: allure-pytest-2.8.6, forked-1.1.3, html-2.0.0, metadata-1.8.0, ordering-0.6, rerunfailures-7.0, xdist-1.30.0 [gw0] win32 Python 3.6.2 cwd: M:py_tests [gw1] win32 Python 3.6.2 cwd: M:py_tests [gw2] win32 Python 3.6.2 cwd: M:py_tests [gw3] win32 Python 3.6.2 cwd: M:py_tests [gw0] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] [gw1] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] [gw2] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] [gw3] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] gw0 [4] / gw1 [4] / gw2 [4] / gw3 [4] scheduling tests via LoadScheduling  scripts/test_case_01.py::test_case02 scripts/test_case_01.py::TestCaseClass::test_case_04 scripts/test_case_01.py::TestCaseClass::test_case_03 scripts/test_case_01.py::test_case01 [gw3] PASSED scripts/test_case_01.py::TestCaseClass::test_case_04 [gw0] PASSED scripts/test_case_01.py::test_case01 [gw2] PASSED scripts/test_case_01.py::TestCaseClass::test_case_03 [gw1] SKIPPED scripts/test_case_01.py::test_case02  ------------------------------------ generated html file: file://M:py_testsreportreport.html ------------------------------------ =================================================== 3 passed, 1 skipped in 2.23s =================================================== pytest-sugar#
  pytest-sugar 改变了  pytest  的默认外观,添加了一个进度条,并立即显示失败的测试。它不需要配置,只需 下载插件即可,用 pytest  运行测试,来享受更漂亮、更有用的输出。
  下载 pip install pytest-sugar
  其他照旧执行用例即可。 pytest-cov#
  pytest-cov 在  pytest  中增加了覆盖率支持,来显示哪些代码行已经测试过,哪些还没有。它还将包括项目的测试覆盖率。
  下载 pip install pytest-cov
  使用
  在配置文件中: [pytest] addopts =  -v -s --html=report/report.html -n=auto --cov=./scripts ;addopts = -s --alluredir ./report/result testpaths = ./scripts/ python_files = test_case_01.py python_classes = Test* python_functions = test_*
  也就是配置 --cov=./scripts ,这样,它就会统计所有scripts 目录下所有符合规则的脚本的测试覆盖率。
  执行的话,就照常执行就行。
  结果: M:py_tests>pytest Test session starts (platform: win32, Python 3.6.2, pytest 5.2.2, p ytest-sugar 0.9.2) cachedir: .pytest_cache metadata: {"Python": "3.6.2", "Platform": "Windows-10-10.0.14393-SP 0", "Packages": {"pytest": "5.2.2", "py": "1.8.0", "pluggy": "0.13. 0"}, "Plugins": {"allure-pytest": "2.8.6", "cov": "2.8.1", "forked" : "1.1.3", "html": "2.0.0", "metadata": "1.8.0", "ordering": "0.6",  "rerunfailures": "7.0", "sugar": "0.9.2", "xdist": "1.30.0"}, "JAV A_HOME": "C:Program FilesJavajdk1.8.0_201"} rootdir: M:py_tests, inifile: pytest.ini, testpaths: ./scripts/ plugins: allure-pytest-2.8.6, cov-2.8.1, forked-1.1.3, html-2.0.0, metadata-1.8.0, ordering-0.6, rerunfailures-7.0, sugar-0.9.2, xdist -1.30.0 [gw0] win32 Python 3.6.2 cwd: M:py_tests [gw1] win32 Python 3.6.2 cwd: M:py_tests [gw2] win32 Python 3.6.2 cwd: M:py_tests [gw3] win32 Python 3.6.2 cwd: M:py_tests [gw0] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] [gw1] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] [gw2] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] [gw3] Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] gw0 [4] / gw1 [4] / gw2 [4] / gw3 [4] scheduling tests via LoadScheduling    scripts	est_case_01.py::test_case02 s                                                                                          50%        pts	est_case_01.py::test_case01                                                                                            25%       ] PASSED scripts/test_case_01.py    scripts	est_case_01.py::TestCaseClass.test_case_03                                                                             75%         scripts	est_case_01.py::TestCaseClass.test_case_04                                                                            100%     scripts/test_case_01.py             Coverage.py warning: No data was collected. (no-data-collected)   ----------------------------------------- generated html file: file://M:py_testsreportreport.html -----------------------------------------  ----------- coverage: platform win32, python 3.6.2-final-0 ----------- Name                          Stmts   Miss  Cover ------------------------------------------------- scriptsdemo1.py                  4      4     0% scripts	est_allure_case.py       7      7     0% scripts	est_case_01.py          15      2    87% ------------------------------------------------- TOTAL                            26     13    50%   Results (2.58s):        3 passed        1 skipped
  更多插件参考:https://zhuanlan.zhihu.com/p/50317866 常见问题#
  有的时候,在 pytest.ini 中配置了pytest-html 和allure 插件之后,执行后报错:
  出现了这个报错,检查你配置的解释器中是否存在 pytest-html 和allure-pytest 这两个模块。如果是使用的pycharm ide,那么你除了检查settings中的解释器配置之外,还需要保证运行脚本的编辑器配置是否跟settings中配置一致。

氢取第一金龙汽车集团旗下三家企业喜获省科学技术奖日前,2020年度福建省科学技术奖正式公布,金龙汽车集团旗下三家企业喜获科技进步一等奖一项三等奖两项。金龙汽车集团本次获奖的项目均和新能源密切关联。其中,获得一等奖的,是金旅客车金华人首富赵长鹏是谁?感染了新冠的赵长鹏身穿4年前300美元买的西装,戴苹果的AppleWatch,住2000美元一晚的酒店,他去年9月在迪拜刚买了一套公寓。财富杂志说他的身价740亿美元,他发推特说没3。31比特币持续下行,以太坊回踩试探支撑?比特币矿企Bitfarms发布Q4财报BTC持有总量或已达到4,301枚金色财经消息,比特币矿企Bitfarms发布Q4财报和全年业绩数据,该公司四季度收入达到6,000万美元,较从亏44亿到赚18。5亿,阅文免费后怎么反而赚钱了?去年还因收购新丽巨亏44亿的大阅文,今年就用18。5亿元的净利润为自己正名。连新丽集团也不再拖后腿,一年赚了5。3亿元。看来经过一年的调试,阅文集团真正走过了低谷期。不过这并非意味何晟铭解锁新身份,出任启牛学堂品牌体验官赋能国人成长,知识点量未来。3月30日,尔湾科技品牌升级发布会如期举行,会上,尔湾科技品牌正式升级为量子之歌。量子之歌集团创始人CEO李鹏,量子之歌集团联合创始人白柏,量子之歌集团互联网前浪张朝阳,依然战斗在一线雷达财经出品文张凯旌编深海张朝阳的物理课真上头。最近在社交平台中搜索张朝阳,可以看到类似的评价。雷达财经注意到,这位搜狐CEO自2021年11月就开始在线上直播上物理课,不久前的3为何超市扫码枪不用输密码就能支付?微信和支付宝有漏洞吗?为何超市扫码枪不用输密码就能支付?微信和支付宝有漏洞吗?随着移动互联网的发展,人们的生活方式也发生了很大的改变,今天我们来聊聊付款方式。如今我国已经迎来了移动支付时代,在这方面可以网约车的路网约车的路越走越难,尤其是平台的野蛮生长,司机的野蛮生长,平台和司机的内卷格外严重,司机们心不齐,司机心奇的话所有的问题都可以迎刃而解,司机老是任人宰割,各大平台都在无底线的试探着骁龙888Plus12GB512GB5000mAh,红米的最大竞争者众所周知,现在手机的性价比市场可以说是越来越大,也是越来越受欢迎的。要说性价比市场最具代表性的品牌,应该要非红米莫属了。作为小米的子品牌,红米的手机兼具了比较高的性能与价高的性价比大疆Mavic3s无人机或在研发中强化长焦副摄提升续航表现去年下半年,大疆正式发布了DJIMavic3无人机,其采用43英寸的大底主摄以及加入长焦副摄的配置为消费级无人机市场带来了新的变化,不过最近有外媒透露,DJIMavic3的下一代无iPhone14定价方案曝光14起售599914Pro起售8999按照惯例,苹果将会在今年的秋季发布会上推出iPhone14系列新品,这也是目前果粉最为期待的一款手机,虽然从现在算起来大约还有半年时间,不过按照苹果新品的研发进度来看,目前已经到了
苹果发布Mac系统更新修复睡眠状态下的电池耗尽问题苹果发布了macOS12。2。1更新,修复了搭载Intel芯片的Mac电脑在连接蓝牙外围设备时,其电池电量可能会在睡眠期间耗尽的问题。在这次更新之前,有用户报告称他们的MacBoo朋友圈出现一条线,原来被好友拉黑了!教你低调检查好友状态随着我国网络技术的发展,越来越多的人使用智能手机,而在使用智能手机的过程中,微信是必不可少的社交软件。微信能让我们交到全国各地的好友,而且能通过微信跟他们视频聊天。在使用微信时我们尚为早报亚马逊推出定价状态功能亚马逊推出定价状态功能近日,亚马逊美国站和欧洲站发布公告称,为了增加卖家的产品成为精选商品的机会,亚马逊为卖家推出定价状态功能。据悉,借助新推出的定价状态功能,卖家可以在管理库存页用机器学习算法解决密度泛函问题?若成功,药物发现超导研究有望更上一层楼如果科学家们能够了解电子在分子中的活动,那么他们就能够预测一切事物的行为,包括实验药物与高温超导体。作者吴彤编辑陈彩娴AIX愈发如火如荼。最近,权威学术媒介QuantaMagazi一只耳朵没有听力,另一只耳朵听力也不好,怎么保护好残余听力?您好,一只耳朵没有听力,另一只耳朵听力也不好,怎么保护好残余听力?建议您先到医院或者听力中心全面详细的检查听力,如果能够通过治疗改善的话先治疗,如果不能通过治疗提高听力,建议您选配阿里女员工案,涉事男领导不构成犯罪说明了什么?很高兴一起来探讨阿里女员工案,涉事男领带不构成犯罪说明了什么这个问题,我的答案是,男领导的猥亵只是违法但没够成犯罪,下面我来说说我的观点这个事件已经几度上了热搜,现在两男的处理结果你失意时给闺密发了好几条微信,也没回复,第二天看到了她发的朋友圈,还能继续交往吗?这种我也遇到过吧我们三个有一个聊天的群,平时会聊聊天扯扯淡什么(都未婚)后来一段时间我发现只要我不说话她们俩可以很久不说话,我觉得大家都有各自的生活和工作不能时时刻刻聊天也没有多想桌面图片看腻了?换成自己喜欢的图片吧(出教程)现在手机内存越做越大,我们手机里的应用也越来越多,然而,我们每天经常使用的应用的图标可能从上市到现在都没有换过,有些图标经典倒还好,但是偶尔的新鲜也是必要的。那我们就拿王者荣耀这款各位大神,怎么样才能变得和马云一样有钱?有两个途径,一是去奋斗,二是多睡觉,梦里梦。把马云打倒了,把他的钱拿来给你用,那你就是马云了!而是比马云有钱,马云就回到旧社会!这样比较快赶上马云,打倒一个赶上一个!所以你就成马云高通公司孟樸以5G赋能千行百业助推数字经济高质量发展来源人民网153个国家和地区1万余家企业200余场论坛会议9月2日,以数字开启未来,服务促进发展为主题的2021年中国国际服务贸易交易会(以下简称服贸会)在北京举办。作为全球服务贸中国的工程师红利中国企业真正具备比较优势的地方其实是在研发成本上。国外一位工程师的月薪相当于中国一个工厂几百名工人工资的总和,而中国一位工程师的月薪才相当于几位工人工资的总和,国外与国内工程师正常