百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

软件测试 | pytest测试框架(pytest框架设计)

haoteby 2025-05-09 18:44 12 浏览

简介

pytest 是一个全功能的 Python 测试工具,可以帮助您编写更好的程序。它与 Python 自带的 unittest 测 试框架类似,但 pytest 使用起来更简洁和高效,并且兼容 unittest 框架。pytest 支持简单的单元测试和 复杂的功能测试,可以结合 requests 实现接口测试,结合 selenium、appium 实现自动化功能测试,使 用 pytest 结合 Allure2 集成到 Jenkins 中可以实现持续集成。pytest 支持三百多种插件(可以访问网 址:
http://plugincompat.herokuapp.com/ 查看插件),可以访问网址:https://docs.pytest.org/ 查看帮助文 档。

安装

pip install -U pytest

查看版本

pytest --version

用例的识别与运行

用例编写规范

  • 测试文件以 test_开头或以 _test 结尾
  • 测试类以 Test 开头,并且不能带有 __init__ 方法
  • 测试函数以 test_开头
  • 断言使用基本的 assert 即可

创建一个 python 文件,命名以 test_ 开头(或者以 _test 结尾),创建测试方法以 test_ 开 头,测试类需要以 Test 开头。

创建文件名为 test_add.py 文件,代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
def add(x, y):
 return x + y
def test_add():
 assert add(1, 10) == 11
 assert add(1, 1) == 2
 assert add(1, 99) == 100
class TestClass:
 def test_one(self):
 x = "this"
assert "h" in x
 def test_two(self):
 x = "hello"
 assert hasattr(x, "check")

命令行进入到这个文件所在的路径,运行 test_add.py 文件。

可以直接使用 pytest 命令运行,pytest 会找当前目录以及递归查找子目录下所有的 test_*.py 或 *_test.py 的文件,把其当作测试文件。在这些文件里,pytest 会收集符合编写规范的函数、类以及 方法,当作测试用例并且执行。

执行如下:

 $ pytest
....
test_add.py ..F [100%]
....
self = <test_cases.test_add.TestClass object at 0x1091810d0>
 def test_two(self):
 x = "hello"
> assert hasattr(x, "check")
E AssertionError: assert False
E + where False = hasattr('hello', 'check')
test_add.py:18: AssertionError
===================================================== 1 failed, 2 passed in 0.05s
...

结果分析:

执行结果中, F 代表用例未通过(断言错误), . 代表用例通过。如果报错会有详细的错误信息。 pytest 也支持运行 unittest 模式的用例。

运行参数

pytest 提供了很多参数,可以使用 pytest --help 来查看帮助文档,下面介绍几种常用的参数:

  • -v 参数

打印详细运行日志信息,一般在调试的时候加上这个参数,终端会打印出每条用例的详细日志信息,方 便定位问题。使用方法如下:

pytest -v
  • -s 参数

控制台输出结果,当你的代码里面有 print 输出语句,如果想在运行结果中打印 print 输出的代码 (默认控制台是不输出打印结果的),在运行的时候可以添加 -s 参数,一般在调试的时候使用,使 用方法如下:

pytest -s
  • -k 参数

只执行含有某个关键字的测试用例。

控制台输出结果,当你的代码里面有 print 输出语句,如果想在运行结果中打印 print 输出的代码 (默认控制台是不输出打印结果的),在运行的时候可以添加 -s 参数,一般在调试的时候使用,使 用方法如下:

pytest -k "类名"
pytest -k "方法名"
pytest -k "类名 and not 方法名" #运行类里所有的方法,不包含某个方法

注意:如果是 windows 系统, -k 后面的字符串参数必须用双引号。

  • -x 参数

遇到用例失败立即停止运行。

应用场景:

在回归测试过程中,假如一共有 10 条基础用例,当开发人员打完包提交测试的时候,需要先运行这 10 条基础用例,全部通过才能提交给测试人员正式测试。如果有一条用例失败,就将这个版本打回给 开发人员。这时就可以添加 -x 参数,一旦发现有失败的用例即中止运行。

使用方法如下:

pytest -x
  • --maxfail 参数

用例失败个数达到阈值停止运行。 应用场景: 在回归测试过程中,假如一共有 10 条基础用例,当开发人员打完包提交测试的时候,需要先运行这 10 条基础用例,全部通过才能提交给测试人员正式测试。如果运行过程中有 [num] 条用例失败,即 中止运行,后面测试用例都放弃执行,直接退出。这时可以使用 --maxfail 参数。

具体用法:

pytest --maxfail=[num]
  • -m参数

将运行有 @pytest.mark.[标记名] 这个标记的测试用例。

应用场景:

在自动化测试过程中可以将测试用例添加标签进行分类,比如登录功能、搜索功能、购物车功能、订单 结算功能等,在运行的时候可以只运行某个功能的所有的测试用例,比如这个版本只想验证登录功能, 那就在所有登录功能的测试用例方法上面加上装饰符 @pytest.mark.login ,运行的时候使用命令添 加一个 -m 参数,例如执行 pytest -m login 命令就可以只执行登录功能这部分的测试用例。

使用方法如下:

pytest -m[标记名]

运行模式

pytest 提供了多种运行模式,让开发和调试更得心应手。指定某个模块,执行单独一个 pytest 模块。

应用场景:

在编写测试用例的时候,经常会单独调试某个类,或者某个方法,这时可以使用 Pycharm 里面自带的调 试方式,点击用例方法名前面的绿色按钮,也可以使用命令行的方式单独运行某个用例。

pytest 中可以使用 pytest 文件名.py 单独执行某个 python 文件,也可以使用 pytest 文件名.py:: 类名 单独执行某个文件中的类,使用 pytest 文件名.py::类名::方法名 单独执行类中的某个方法。 使用方法如下:

pytest 文件名.py
pytest 文件名.py::类名
pytest 文件名.py::类名::方法名

在Pycharm中运行pytest用例

打开 Pycharm -> 设置 - Tools -> Python Integrated Tools -> Testing: pytest

首先设置成 pytest ,需要安装 pytest,可以直接按照这个页面的提示点击 fix ,也可以在 Project interpreter 里面添加 pytest 安装包。安装完 pytest 之后,符合规则的测试用例都能被识别出来并且会显 示出一个三角形的执行按钮,点击这个按钮也能执行某个方法或者某个类。例如:

pytest 框架结构

执行用例前后会执行 setup,teardown 来完成用例的前置和后置条件。pytest 框架中使用 setup, teardown 更灵活,按照用例运行级别可以分为以下几类:

模块级(
setup_module/teardown_module)在模块始末调用

函数级(
setup_function/teardown_function)在函数始末调用(在类外部)

类级(
setup_class/teardown_class)在类始末调用(在类中)

方法级(
setup_method/teardown_methond)在方法始末调用(在类中)

方法级(setup/teardown)在方法始末调用(在类中)

调用顺序

setup_module > setup_class >setup_method > setup > teardown > teardown_method > teardown_class > teardown_module

画图说明

验证上面的执行顺序,看下面的案例。

创建文件名为 test_module.py ,代码如下:

# 模块级别
def setup_module():
 print("setup module")
def teardown_module():
 print("teardown module")
class TestDemo:
 # 执行类 前后分别执行setup_class teardown_class
 def setup_class(self):
 print("TestDemo setup_class")
 def teardown_class(self):
 print("TestDemo teardown_class")
 # 每个类里面的方法前后分别执行 setup, teardown
 def setup(self):
 print("TestDemo setup")
 def teardown(self):
 print("TestDemo teardown")
 def test_demo1(self):
 print("test demo1")
 def test_demo2(self):
 print("test demo2")
class TestDemo1:
 def test_demo3(self):
 print("test demo3")

运行结果:

setup module
TestDemo setup_class
TestDemo setup
test demo1
TestDemo teardown
TestDemo setup
test demo2
TestDemo teardown
TestDemo teardown_class
test demo3
teardown module

setup_module 和 teardown_module 在整个模块只执行一次,setup_class 和 teardown_class 在类里面只 执行一次,setup_method/setup 和 teardown_method/teardown 在每个方法前后都会调用。一般用的最多 的是方法级别(setup/teardown)和类级别(
setup_class/teardown_class)。

pytest fixtures

pytest 中可以使用 @pytest.fixture 装饰器来装饰一个方法,被装饰的方法名可以作为一个参数传入 到测试方法中。可以使用这种方式来完成测试之前的初始化,也可以返回数据给测试函数。

将 FIXTURE 作为函数参数

通常使用 setup 和 teardown 来进行资源的初始化。如果有这样一个场景,测试用例 1 和 测试用例 3 需要依赖登录功能,测试用例 2 不需要依赖登录功能。这种场景 setup,teardown 无法实现,可以使用 pytest fixture 功能,在方法前面加个 @pytest.fixture 装饰器,加了这个装饰器的方法可以以参数的 形式传入到方法里面执行。例如在登录的方法,加上 @pytest.fixture 这个装饰器后,将这个用例 方法名以参数的形式传到方法里,这个方法就会先执行这个登录方法,再去执行自身的用例步骤,如果 没有传入这个登录方法,就不执行登录操作,直接执行已有的步骤。

创建一个文件名为 “test_fixture.py”,代码如下;

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pytest
@pytest.fixture()
def login():
 print("这是个登录方法")
 return ('tom','123')
@pytest.fixture()
def operate():
 print("登录后的操作")
def test_case1(login,operate):
 print(login)
 print("test_case1,需要登录")
def test_case2():
 print("test_case2,不需要登录 ")
def test_case3(login):
 print(login)
 print("test_case3,需要登录")

在上面的代码中,测试用例 test_case1 和 test_case3 分别增加了 login 方法名作为参数,pytest 会发现 并调用 @pytest.fixture 标记的 login 功能,运行测试结果如下:

test_fixture.py::test_case1 这是个登录方法
登录后的操作
PASSED [ 33%]('tom', '123')
test_case1,需要登录
test_fixture.py::test_case2 PASSED \
[ 66%]test_case2,不需要登录
test_fixture.py::test_case3 这是个登录方法
PASSED [100%]('tom', '123')
test_case3,需要登录
============================== 3 passed in 0.02s ===============================
Process finished with exit code 0

从上面的结果可以看出,test_case1 和 test_case3 运行之前执行了 login 方法,test_case2 没有执行这个 方法。

指定范围内共享

fixture 里面有一个参数 scope,通过 scope 可以控制 fixture 的作用范围,根据作用范围大小划分: session> module> class> function,具体作用范围如下:

 - function 函数或者方法级别都会被调用
 - class 类级别调用一次
 - module 模块级别调用一次
 - session 多个文件/包调用一次(可以跨.py文件调用,每个.py文件就是module)

例如整个模块有很多条测试用例,需要在全部用例执行之前打开浏览器,全部执行完之后去关闭浏览 器,打开和关闭操作只执行一次,如果每次都重新执行打开操作,会非常占用系统资源。这种场景除了
setup_module/teardown_module 可以实现,还可以通过设置模块级别的 fixture 装饰器 (@pytest.fixture(scope="module"))来实现。

scope='module'

fixture 参数 scope='module' ,module 作用是整个模块都会生效。

创建文件名为 test_fixture_scope.py ,代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pytest
# 作用域:module是在模块之前执行, 模块之后执行
@pytest.fixture(scope="module")
def open():
 print("打开浏览器")
 yield
 print("执行teardown !")
 print("最后关闭浏览器")
@pytest.mark.usefixtures("open")
def test_search1():
 print("test_search1")
 raise NameError
 pass
def test_search2(open):
 print("test_search2")
 pass
def test_search3(open):
 print("test_search3")
 pass

代码解析:

@pytest.fixture() 如果不写参数,参数默认 scope='function' 。当 scope='module' 时,在当前 .py 脚本里面所有的用例开始前只执行一次。scope 巧妙与 yield 关键字结合使用,相当于 setup 和 teardown 方法。还可以使用 @pytest.mark.usefixtures 装饰器,传入前置函数名作为参数。

运行结果如下:

test_fixture_yield.py::test_search1 打开浏览器
FAILED [ 33%]test_search1
test_fixture_yield.py:13 (test_search1)
open = None
 def test_search1(open):
 print("test_search1")
> raise NameError
E NameError
test_fixture_yield.py:16: NameError
test_fixture_yield.py::test_search2 PASSED \
[ 66%]test_search2
test_fixture_yield.py::test_search3 PASSED \
[100%]test_search3
执行teardown !
最后关闭浏览器
...
open = None
 def test_search1(open):
 print("test_search1")
> raise NameError
E NameError
test_fixture_yield.py:16: NameError
...

从上面运行结果可以看出, scope="module" 与 yield 结合,相当于 setup_module 和 teardown_module 方法。整个模块运行之前调用了 open() 方法中 yield 前面的打印输出“打开浏览 器”,整个运行之后调用了 yield 后面的打印语句“执行 teardown !”与“关闭浏览器”。

通过 yield 来唤醒 teardown 的执行,如果用例出现异常,不影响 yield 后面的 teardown 执行。

CONFTEST.PY 文件

fixture scope 为 session 级别是可以跨 .py 模块调用的,也就是当我们有多个 .py 文件的用例时, 如果多个用例只需调用一次 fixture,可以将 scope='session' ,并且写到 conftest.py 文件里。 写到 conftest.py 文件可以全局调用这里面的方法。使用的时候不需要导入 conftest.py 这个文 件。使用 conftest.py 的规则:

1. conftest.py 这个文件名是固定的,不可以更改。

2. conftest.py 与运行用例在同一个包下,并且该包中有 __init__.py 文件

3.使用的时候不需要导入 conftest.py ,pytest 会自动识别到这个文件

4.放到项目的根目录下可以全局调用,放到某个 package 下,就在这个 package 内有效。

案例

运行整个项目下的所有的用例,只执行一次打开浏览器。执行完所有的用例之后再执行关闭浏览器,可 以在这个项目下创建一个 conftest.py 文件,将打开浏览器操作的方法放在这个文件下,并添加一个 装饰器 @pytest.fixture(scope="session") ,就能够实现整个项目所有测试用例的浏览器复用,案 例目录结构如下:

创建目录 test_scope,并在目录下创建三个文件 conftest.py , test_scope1.py 和 test_scope2.py 。 conftest.py 文件定义了公共方法,pytest 会自动读取 conftest.py 定义的方法,代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pytest
@pytest.fixture(scope="session")
def open():
 print("打开浏览器")
 yield
 print("执行teardown !")
 print("最后关闭浏览器")

创建“test_scopel.py”文件,代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pytest
def test_search1(open):
 print("test_search1")
 pass
def test_search2(open):
 print("test_search2")
 pass
def test_search3(open):
 print("test_search3")
 pass
if __name__ == '__main__':
 pytest.main()

创建文件“test_scope2.py”,代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
class TestFunc():
 def test_case1(self):
 print("test_case1,需要登录")
def test_case2(self):
 print("test_case2,不需要登录 ")
 def test_case3(self):
 print("test_case3,需要登录")

打开 cmd,进入目录 test_scope/,执行如下命令:

pytest -v -s

或者

pytest -v -s test_scope1.py test_scope2.py

执行结果如下:

省略...
collected 6 items
test_scope1.py::test_search1 打开浏览器
test_search1
PASSED
test_scope1.py::test_search2 test_search2
PASSED
test_scope1.py::test_search3 test_search3
PASSED
test_scope2.py::TestFunc::test_case1 test_case1,需要登录
PASSED
test_scope2.py::TestFunc::test_case2 test_case2,不需要登录
PASSED
test_scope2.py::TestFunc::test_case3 test_case3,需要登录
PASSED执行teardown !
最后关闭浏览器
省略后面打印结果...

自动执行FIXTURE

如果每条测试用例都需要添加 fixture 功能,则需要在每一条要用例方法里面传入这个 fixture 的名字, 这里就可以在装饰器里面添加一个参数 autouse='true' ,它会自动应用到所有的测试方法中,只是这 里没有返回值。 使用方法,在方法前面加上装饰器,如下:

@pytest.fixture(autouse="true")
def myfixture():
 print("this is my fixture")

@pytest.fixture 里设置 autouse 参数值为 true(默认 false),每个测试函数都会自动调用这个前置 函数。 创建文件名为“test_autouse.py”,代码如下:

# coding=utf-8
import pytest
@pytest.fixture(autouse="true")
def myfixture():
 print("this is my fixture")
class TestAutoUse:
 def test_one(self):
 print("执行test_one")
 assert 1 + 2 == 3
 def test_two(self):
 print("执行test_two")
 assert 1 == 1
 def test_three(self):
 print("执行test_three")
 assert 1 + 1 == 2

执行上面这个测试文件,结果如下:

...
test_a.py::TestAutoUse::test_one this is my fixture
执行test_one
PASSED
test_a.py::TestAutoUse::test_two this is my fixture
执行test_two
PASSED
test_a.py::TestAutoUse::test_three this is my fixture
执行test_three
PASSED
...

从上面的运行结果可以看出,在方法 myfixture() 上面添加了装饰器 @pytest.fixture(autouse="true") ,测试用例无须传入这个 fixture 的名字,它会自动在每条用例 前执行这个 fixture。

FIXTURE 传递参数

测试过程中需要大量的测试数据,如果每条测试数据都编写一条测试用例,用例数量将是非常庞大的。 一般我们在测试过程中会将测试用到的数据以参数的形式传入到测试用例中,并为每条测试数据生成一 个测试结果。这时候可以使用 fixture 的参数化功能,在 fixture 方法加上装饰器 @pytest.fixture(params=[1,2,3]) ,就会传入三个数据 1、2、3,分别将这三个数据传入到用例当 中。这里传入的数据类型是个列表。传入的数据需要使用一个固定的参数名 request 来接收。

创建文件名为“test_params.py”,代码如下:

import pytest
@pytest.fixture(params=[1, 2, 3])
def data(request):
 return request.param
def test_not_2(data):
 print(f"测试数据:{data}")
 assert data < 5

运行结果如下:

...
test_params.py::test_not_2[1]PASSED [ 33%]测试数据:1
test_params.py::test_not_2[2] PASSED [ 66%]测试数据:2
test_params.py::test_not_2[3] PASSED [100%]测试数据:3
...

从运行结果可以看出,对于 params 里面的每个值,fixture 都会去调用执行一次,使用 request.param 来 接受参数化的数据,并且为每一个测试数据生成一个测试结果。在测试工作中使用这种参数化的方式, 代码量会大大的减少,并且便于阅读与维护。

第三方插件介绍

控制用例的执行顺序

当一个目录下有很多模块,甚至有很多子目录。每个目录下也有大量的测试用例。pytest 加载所有的测 试用例的顺序是按照 pytest 的自定义的规则(不同的模块间是按照模块名字的 ASCII 码顺序排列,同 一模块间是按照定义的前后顺序加载的)。如果想指定用例的顺序,可以使用 pytest-ordering 插件,指 定用例的执行顺序只需要在测试用例的方法前面加上装饰器 @pytest.mark.run(order=[num]) 设置 order 的对应的 num 值,它就可以按照 num 的大小顺序来执行(由小到大的顺序执行,负数反之)。

应用场景:

有时运行测试用例需要指定它的顺序,比如有些场景需要先要登录,才能执行后续的流程(比如购物流 程,下单流程),这时就需要指定测试用例的顺序。通过 pytest-ordering 这个插件可以完成用例 顺序的指定。

安装

pip install pytest-ordering

案例

创建一个测试文件“test_order.py”,代码如下

import pytest
class TestPytest(object):
 @pytest.mark.run(order=-1)
 def test_two(self):
 print("test_two,测试用例")
 @pytest.mark.run(order=3)
 def test_one(self):
 print("test_one,测试用例")
 @pytest.mark.run(order=1)
 def test_three(self):
 print("\ntest_three,测试用例")

执行结果,如下查看执行顺序:

省略...
test_order.py::TestPytest::test_three
test_order.py::TestPytest::test_one
test_order.py::TestPytest::test_two
省略...

从上面的执行结果可以看出,执行时以 order 的顺序执行:order=1,order=3,order=-1。(1 最先执 行,-1 代表倒数第一个执行)

多线程并行与分布式执行

应用场景:

假如项目中有测试用例 1000 条,一条测试用例需要执行 1 分钟,一个测试人员需要 1000 分钟才能 完成一轮回归测试。通常我们会用人力成本换取时间成本,加几个人一起执行,时间就会缩短。如果 10 人一起执行只需要 100 分钟,这就是一种并行测试,分布式的场景。

pytest-xdist 是 pytest 分布式执行插件,这款插件允许用户将测试并发执行(进程级并发),使用 这款插件执行用例是随机的,为了保证各个测试用例能在各自独立进程里正确的执行,应该保证测试用 例的独立性(这也符合测试用例设计的最佳实践)。

安装

pip install pytest-xdist

多个 CPU 并行执行用例,需要在 pytest 后面添加 -n 参数,如果参数为 auto,会自动检测系统的 CPU 数目。如果参数为数字,则指定运行测试的处理器进程数。

pytest -n auto
pytest -n [num]

案例

某个项目有 200 条测试用例,每条测试用例之间没有关联关系,互不影响。这 200 条测试用例需要在 1 小时之内测试完成,可以加个 -n 参数,使用多 CPU 并行测试。

运行方法

pytest -n 4

进入到项目目录下,执行 pytest 可以将项目目录下所有测试用例识别出来并且运行,加上 -n 参数,可 以指定 4 个 CPU 并发执行。如果设置的 CPU 数大于系统 CPU 个数,则会按照当前 CPU 的实际个数 执行.

结合 PYTEST-HTML 生成测试报告

测试报告通常在项目中尤为重要,报告可以体现测试人员的工作量,开发人员可以从测试报告中了解缺 陷的情况,因此测试报告在测试过程中的地位至关重要,测试报告为纠正软件存在的质量问题提供依 据,为软件验收和交付打下基础。

测试报告根据内容的侧重点,可以分为 “版本测试报告” 和 “总结测试报告”。执行完 pytest 测试 用例,可以使用 pytest-html 插件生成 HTML 格式的测试报告。

安装

pip install pytest-html

执行方法

pytest --html=path/to/html/report.html

结合pytest-xdist使用

pytest -v -s -n 3 --html=report.html --self-contained-html

生成测试报告

如下图:

生成的测试报告最终是 HTML 格式,报告内容包括标题、运行时间、环境、汇总结果以及用例的通过 个数、跳过个数、失败个数、错误个数,重新运行个数、以及错误的详细展示信息。 报告会生成在运行脚本的同一路径下,需要指定路径添加 --html=path/to/html/report.html 这个 参数配置报告的路径。如果不添加 --self-contained-html 这个参数,生成报告的 CSS 文件是独立 的,分享的时候容易数据丢失。

assert 断言使用

编写代码时,我们经常会做出一些假设,断言就是用于在代码中验证这些假设。断言表示为一些布尔表 达式,测试人员通常会加一些断言来判断中间过程的正确性。

断言支持最常见的表达式,包括调用,属性,比较以及二元和一元运算符。 Python 使用 assert(断 言)用于判断一个表达式的正确与否,在表达式条件为 False 的时候触发异常。

使用方法

assert True #断言为真
assert not True #断言不为真

案例如下:

assert "h" in "hello" #判断 h 在 hello 中
assert 5>6 #判断 5>6 为真
assert not True #判断不为真
assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'} #判断两个集合相等

如果没有断言,没有办法判定用例中每一个测试步骤结果的正确性。在项目中适当的使用断言对代码的 结构、属性、功能、安全性等场景检查与验证。

搜索微信公众号:TestingStudio霍格沃兹的干货都很硬核

相关推荐

网站seo该怎么优化

一、网站定位在建设一个网站之前,我们首先要做的就是一个网站清晰的定位,会带来转化率相对较高的客户群体,我们建站的目的就是为了营销,只有集中来做某一件事,才会更好的展现我们的网站。在做SEO优化的同时...

3个小技巧教你如何做好SEO优化

  想半路出家做SEO?可是,怎么才做的好呢?关于SEO专业技术弄懂搜索引擎原理,咱们做搜索引擎排名的首先就是要了解搜索引擎的工作原理,对SEO优化有更深入了解之后再来做SEO,你就能从搜索引擎的视点...

SEO指令分享:filetype指令

filetype用于搜索特定的文件格式。百度和谷歌都支持filetype指令。比如搜索filetype:pdf今日头条返回的就是包含今日头条这个关键词的所有pdf文件,如下图:百度只支持:pdf...

网站seo优化技巧大全

SEO在搜索引擎中对检索结果进行排序,看谁最初是在用户的第一眼中看到的。实际上,这些排名都是通过引擎的内部算法来实现的。例如,百度算法很有名。那么,对百度SEO的优化有哪些小技巧?下面小编就会说下针对...

小技巧#10 某些高级的搜索技巧

由于某些原因,我的实验场所仅限百度。1.关键词+空格严格说来这个不能算高级,但关键词之间打空格的办法确实好用。我习惯用右手大拇指外侧敲击空格键,这个习惯在打英文报告时尤其频繁。2.site:(请不要忽...

MYSQL数据库权限与安全

权限与安全数据库的权限和数据库的安全是息息相关的,不当的权限设置可能会导致各种各样的安全隐患,操作系统的某些设置也会对MySQL的安全造成影响。1、权限系统的工作原理...

WPF样式

UniformGrid容器<UniformGridColumns="3"Rows="3"><Button/>...

mysql自动备份,并zabbix检测备份文件是否正常,备份文件大小

推荐...

MySQL学到什么程度?才有可以在简历上写精通

前言如今互联网行业用的最多就是MySQL,然而对于高级Web面试者,尤其对于寻找30k下工作的求职者,很多MySQL相关知识点基本都会涉及,如果面试中,你的相关知识答的模糊和不切要点,基...

jquery的事件名称和命名空间的方法

我们先看一些代码:当然,我们也可以用bind进行事件绑定。我们看到上面的代码,我们可以在事件后面,以点号,加我们的名字,就是事件命名空间。所谓事件命名空间,就是事件类型后面以点语法附加一个别名,以便引...

c#,委托与事件,发布订阅模型,观察者模式

什么是事件?事件(Event)基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。通过委托使用事件事件在类中声明且生成,且通过...

前端分享-原生Popover已经支持

传统网页弹窗开发需要自己处理z-index层级冲突、编写点击外部关闭的逻辑、管理多个弹窗的堆叠顺序。核心优势对比:...

Axure 8.0 综合帖——新增细节内容

一、钢笔工具与PS或者AI中的钢笔工具一样的用法。同样有手柄和锚点,如果终点和起点没有接合在一起,只要双击鼠标左键即可完成绘画。画出来的是矢量图,可以理解为新的元件。不建议通过这个工具来画ICON图等...

PostgreSQL技术内幕28:触发器实现原理

0.简介在PostgreSQL(简称PG)数据库中,触发器(Trigger)能够在特定的数据库数据变化事件(如插入、更新、删除等)或数据库事件(DDL)发生时自动执行预定义的操作。触发器的实现原理涉及...

UWP开发入门(十七)--判断设备类型及响应VirtualKey

蜀黍我做的工作跟IM软件有关,UWP同时会跑在电脑和手机上。电脑和手机的使用习惯不尽一致,通常我倾向于根据窗口尺寸来进行布局的变化,但是特定的操作习惯是依赖于设备类型,而不是屏幕尺寸的,比如聊天窗口的...