对于pytest十五:pytest-html生成html报告感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解pytest--html,并且为您提供关于$pytest和$python-mpyt
对于pytest十五:pytest-html 生成 html 报告感兴趣的读者,本文将提供您所需要的所有信息,我们将详细讲解pytest --html,并且为您提供关于$ pytest 和 $ python -m pytest 测试的区别、@pytest.mark标记 @pytest.fixture()、ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction、asp.net – Html.Partial vs Html.RenderPartial&Html.Action vs Html.RenderAction.任何人都可以描述不同之处的宝贵知识。
本文目录一览:- pytest十五:pytest-html 生成 html 报告(pytest --html)
- $ pytest 和 $ python -m pytest 测试的区别
- @pytest.mark标记 @pytest.fixture()
- ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction
- asp.net – Html.Partial vs Html.RenderPartial&Html.Action vs Html.RenderAction.任何人都可以描述不同之处
pytest十五:pytest-html 生成 html 报告(pytest --html)
pytest-HTML 是一个插件,pytest 用于生成测试结果的 HTML 报告。兼容 Python 2.7,3.6
pytest-html
1.github 上源码地址
【https://github.com/pytest-dev/pytest-html】
2.pip 安装
> pip install pytest-html
3.执行方法
> pytest --html=report.html
html 报告
1.打开 cmd,cd 到需要执行 pytest 用例的目录,执行指令:pytest —html=report.html
2.执行完之后,在当前目录会生成一个 report.html 的报告文件
指定报告路径
1.直接执行”pytest —html=report.html”生成的报告会在当前脚本的同一路径,如果想指定报告的存放位置,放到当前脚本的同一目录下的 report 文件夹里
2.如果想指定执行某个.py 文件用例戒者某个文件夹里面的所有用例,需加个参数。
报告独立显示
上面方法生成的报告,css 是独立的,分享报告的时候样式会丢失,为了更好的分享发邮件展示报告,可以把 css 样式合并到 html 里
> pytest --html=report.html --self-contained-html
显示选项
默认情况下,“ 结果”表中的所有行都将被展开,但具测试通过的行除外 Passed。
可以使用查询参数自定义此行为:?collapsed=Passed,XFailed,Skipped。
更多功能
更多功能查看官方文档【https://github.com/pytest-dev/pytest-html】
-html 报告报错截图+失败重跑
前言
做 web 自动化的小伙伴应该都希望在 html 报告中展示失败后的截图,提升报告的档次,pytest-html 也可以生成带截图的报告。
conftest.py
1.失败截图可以写到 conftest.py 文件里,这样用例运行时,只要检测到用例实例,就调用截图的方法,并且把截图存到 html 报告上
2.用例部分如下:
报告展示
cmd 打开,cd 到用例的目录,执行指令
> pytest --html=report.html --self-contained-html
失败重试
失败重跑需要依赖 pytest-rerunfailures 插件,使用 pip 安装就行
> pip install pytest-rerunfailures
用例失败再重跑 1 次,命令行加个参数--reruns 就行了
> py.test --reruns 1 --html=report.html --self-contained-html
关于 reruns 参数的 2 个用法
--reruns=RERUNS RERUNS 参数是失败重跑的次数,默认为 0
--reruns-delay=RERUNS_DELAY RERUNS_DELAY 是失败后间隔多少 s 重新执行,时间单位是 s
$ pytest 和 $ python -m pytest 测试的区别
如何解决$ pytest 和 $ python -m pytest 测试的区别
我想了解跑步有什么区别:
$ pytest
和
$ python -m pytest tests
我在 Mac 上的虚拟环境中工作。 第一个解决方案给了我一个错误:
ModuleNotFoundError: No module named ''app''
第二种解决方案工作正常。
为什么第二个解决方案有效而第一个无效?
如何仅使用 $ pytest
使其工作?
我的文件夹结构:
├── app.py
├── requirements.txt
├── templates
├── tests
│ ├── conftest.py
│ ├── functional
│ │ ├── __init__.py
│ │ └── test_s.py
│ └── unit
│ ├── __init__.py
│ └── test_app.py
└── venv
在 test_app.py 中,此行失败:
from app import app
解决方法
不同之处在于搜索模块的 Python 算法,以及 Pytest 发现测试的方式。
1. Python 模块搜索
根据Python实现如下:
- 在内置模块中搜索
- 在 sys.path 列表中搜索:
- 第一个“当前目录”被添加到 sys.path
- 第二个 PYTHONPATH 内容被添加到 sys.path
- 然后最后将所有 Python 安装目录添加到 sys.path
这可能非常复杂。我在这里看到“在扩展模式下”很好地解释了这一点: Where is Python''s sys.path initialized from?
2. Pytest 发现机制
所以
from app import app
当您像上面一样导入“应用程序”时,在这两种情况下都会以不同的方式进行搜索。换句话说,对于这两种情况,sys.path 中的“当前目录”设置不同。您可以通过打印 sys.path 列表来检查这一点。
这不是问题,而是 python/pytest 的工作方式。
3.解决方法示例
你可以通过例如下面的方法解决这个问题(我把它放在单独的 pathmagic.py 文件中,然后在 test_xyz 中导入 pathmagic )
import pathmagic # noqa Pep8 uncheck
pathmagic.py
,
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path.append(os.path.dirname((os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
python -m pytest
将当前目录添加到 sys.path,即允许您从那里导入模块。
他暗示有些东西 - 让我们称之为 - 不是您的目录结构的最佳选择。
为什么这可能不是一件好事,您可以阅读这篇精彩的博文
https://blog.ganssle.io/articles/2019/08/test-as-installed.html
我还写了一篇关于这个主题的简短博文:
https://github.com/jugmac00/til/blob/master/python/difference-between-pytest-and-python-m-pytest.md
@pytest.mark标记 @pytest.fixture()
一、标记跳过
1.1、无条件跳过skip
使用方法:通过 @pytest.mark.skip(reason=跳过原因) 装饰器标记要跳过的测试用例
- 参数reason:跳过的原因,非必填
import pytest
@pytest.mark.skip
def test_001():
raise Exception(''该功能尚未开发完成'')
@pytest.mark.skip(reason=''该功能尚未开发完成'')
def test_002():
raise Exception(''该功能尚未开发完成'')
def test_003():
assert True
执行结果
collecting ... collected 3 items
skip_mark.py::test_001 SKIPPED (unconditional skip) [ 33%]
Skipped: unconditional skip
skip_mark.py::test_002 SKIPPED (该功能尚未开发完成) [ 66%]
Skipped: 该功能尚未开发完成
skip_mark.py::test_003 PASSED [100%]
======================== 1 passed, 2 skipped in 0.01s =========================
1.2、有条件跳过skipif
使用方法:通过@pytest.mark.skipif(condition=跳过条件,reason=跳过原因)标记要跳过的测试用例。
- 参数condition:跳过的条件,值为True则跳过,值为False则继续执行,默认值为True
- 参数reason:必填,跳过的原因
import pytest
@pytest.mark.skipif(condition=True, reason="有条件的跳过")
def test_001():
assert ''h'' in ''hello''
def test_002():
assert 1 == 1
执行结果:
collecting ... collected 2 items
skipif_mark.py::test_001 SKIPPED (有条件的跳过) [ 50%]
Skipped: 有条件的跳过
skipif_mark.py::test_002 PASSED [100%]
======================== 1 passed, 1 skipped in 0.01s =========================
二、标记实现参数化
使用说明:@pytest.mark.parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)装饰器来实现参数化
- argnames:参数名,使用逗号分隔的列表,或元祖,或字符串,表示一个或多个参数名,【常用】
- argvalues:参数值,可以是列表、元祖、字典列表、字典元祖,【常用】
indirect:中文翻译为中间人,为True时可以对argvalues的参数值进行处理,默认False,【不常用】
- indirect=True: 且argnames的值为fixture函数名,此时argnames的值变为可执行函数,会将argvalues的参数值当做参数传递给fixture函数进行处理,fixture函数返回处理结果给argnames
- indirect=False: argnames仅为参数名
- ids:给用例起别名,字符串列表或数字列表,不设置会自动从测试数据中提取
scope:fixture函数的作用域;可选值:function(默认)、class、module、session
- function:作用于每个方法或函数,每个方法或函数都运行一次
- 作用于整个class类,每个class中的所有test只运行一次
- 作用于整个模块,每个module中的所有test只运行一次
- 作用于整个session,整个session只运行一次(慎用)
2.1、单个参数
import pytest
phone_list = [
"13881118888",
"13012034288",
"13234324188",
"13231423288"
]
@pytest.mark.parametrize(argnames="phone_num", argvalues=phone_list)
def test_phone_number(phone_num): # 注意,这里的参数要和argnames参数名一致
print(f"\n正在测试手机号{phone_num}")
执行结果:
collecting ... collected 4 items
sing_parme.py::test_phone_number[13881118888] PASSED [ 25%]
正在测试手机号13881118888
sing_parme.py::test_phone_number[13012034288] PASSED [ 50%]
正在测试手机号13012034288
sing_parme.py::test_phone_number[13234324188] PASSED [ 75%]
正在测试手机号13234324188
sing_parme.py::test_phone_number[13231423288] PASSED [100%]
正在测试手机号13231423288
============================== 4 passed in 0.01s ==============================
2.2、多个参数
import pytest
user_info = [
("张三", "18011111111"),
("李四", "18022222222"),
("王五", "18033333333")
]
@pytest.mark.parametrize(argnames="name,phonenum", argvalues=user_info)
def test_read_info(name, phonenum):
print(f"\n正在读取用户{name},手机号{phonenum}")
执行结果:
collecting ... collected 3 items
more_data.py::test_read_info[\u5f20\u4e09-18011111111] PASSED [ 33%]
正在读取用户张三,手机号18011111111
more_data.py::test_read_info[\u674e\u56db-18022222222] PASSED [ 66%]
正在读取用户李四,手机号18022222222
more_data.py::test_read_info[\u738b\u4e94-18033333333] PASSED [100%]
正在读取用户王五,手机号18033333333
============================== 3 passed in 0.01s ==============================
注意:由上面例子执行结果中可以看到中文参数值乱码了,解决办法如下
方法1. 在pytest.ini中加入disable_test_id_escaping_and_forfeit_all_rights_to_community_support=True
2.3、多个参数化
import pytest
data1 = [''a'', ''b'']
data2 = [1, 2]
@pytest.mark.parametrize(''test1'', data1)
@pytest.mark.parametrize(''test2'', data2)
def test_param(test1, test2):
print(f''\n测试数据:{test1}-{test2}'')
执行结果:
collecting ... collected 4 items
more_parames.py::test_param[1-a]
测试数据:a-1
PASSED
more_parames.py::test_param[1-b]
测试数据:b-1
PASSED
more_parames.py::test_param[2-a]
测试数据:a-2
PASSED
more_parames.py::test_param[2-b]
测试数据:b-2
PASSED
============================== 4 passed in 0.02s ==============================
2.4、ids参数给用例起别名
import pytest
user_info = [
("张三", "18011111111"),
("李四", "18022222222"),
("王五", "18033333333")
]
@pytest.mark.parametrize(argnames="name,phonenum", argvalues=user_info, ids=["用户1", "用户2", "用户3"])
def test_read_info(name, phonenum):
print(f"正在读取用户{name},手机号{phonenum}")
2.5、indirect处理参数值
import pytest
@pytest.fixture()
def fixture_and_parametrize(request): # request是关键字不能改变,用来接收参数
print(f''邮箱账号为:{request.param}'')
return request.param + "@qq.com"
@pytest.mark.parametrize(''fixture_and_parametrize'', [''100203'', ''466238894'', ''23942423''],
indirect=True)
def test_fixture_and_parametrize_2(fixture_and_parametrize):
print(f''拼接后邮箱为:{fixture_and_parametrize}'')
collecting ... collected 3 items
flag.py::test_fixture_and_parametrize_2[100203] 邮箱账号为:100203
拼接后邮箱为:100203@qq.com
PASSED
flag.py::test_fixture_and_parametrize_2[466238894] 邮箱账号为:466238894
拼接后邮箱为:466238894@qq.com
PASSED
flag.py::test_fixture_and_parametrize_2[23942423] 邮箱账号为:23942423
拼接后邮箱为:23942423@qq.com
PASSED
============================== 3 passed in 0.00s ==============================
三、自定义标记
pytest支持通过pytest.ini文件注册自定义的标记。以满足执行用例时,通过标记对用例进行筛选
语法:
[pytest]
markers =
标记1
标记2
...
pytest.ini
[pytest]
markers =
demo
smoke
import pytest
@pytest.mark.smoke
def test_001():
print(''001'')
@pytest.mark.smoke
def test_002():
print(''002'')
@pytest.mark.demo
def test_003():
print(''003'')
@pytest.mark.demo
def test_004():
print(''004'')
执行命令:pytest -m "smoke" demo.py
三、@pytest.fixture()详细使用
3.1、fixture简介
- 有独立的命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活;
- 按模块化的方式实现,每个fixture都可以互相调用
- fixture的范围从简单的单元测试到复杂的功能测试,可以对fixture配置参数,或者跨函数function,类class,模块module或整个测试session范围
3.2、用途
- 做测试前后的初始化设置,如测试数据准备,连接数据库,打开浏览器等这些操作都可以使用fixture来实现
- 测试用例的前置条件可以使用fixture实现
- 支持经典的xunit fixture ,像unittest使用的setup和teardown
- 可以实现unittest不能实现的功能,比如unittest中的测试用例和测试用例之间是无法传递参数和数据的,但是fixture却可以解决这个问题
3.3、fixture可以当做参数传入
- 定义fixture跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture命名不要用test_开头,跟用例区分开。用例才是test_开头的命名
- fixture是可以有返回值的,如果没return默认返回None。用例调用fixture的返回值,直接就是把fixture的函数名称当成变量传入
- fixture装饰器里的scope有四个级别的参数。function(不写默认这个)、class、module、session
- 除scope之外。还有params、autouse、ids、name等
- fixture可以返回一个元组、列表或字典
- test_用例可传单个、多个fixture参数
- fixture与fixture间可相互调用
3.4、fixture源码详解
fixture(scope=''function'',params=None,autouse=False,ids=None,name=None):
scope:参数可以控制fixture的作用范围,scope:function(不写默认这个)、class、module、session
params:一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它
autouse:如果True,则为所有测试激活fixture func可以看到它。如果为False则显示需要参考来激活fixture
ids:每个字符串id的列表,每个字符串对应于params这样他们就是测试ID的一部分。如果没有提供ID它们将从params自动生成
name:fixture的名称。这默认为装饰函数的名称。如果fixture在定义它的统一模块中使用,夹具的功能名称将被请求夹具的功能arg遮蔽,解决这个问题的一种方法时将装饰函数命令"fixture_<fixturename>"然后使用"@pytest.fixtur(name=''<fixturename>'')"。
fixture里面有个scope参数可以控制fixture的作用范围:session>module>class>function
function:每一个函数或方法都会调用
class:每一个类调用一次,一个类中可以有多个方法
module:每一个.py文件调用一次,该文件内又有多个function和class
session:是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module
import pytest
@pytest.fixture()
def city():
a = ''北京''
return a
@pytest.fixture(scope=''function'', params=None, autouse=False, ids=None, name=None)
def skill():
b = ''测试''
return b
@pytest.fixture()
def job(skill): # fixture之间可以相互调用
c = ''api''
return skill, c
def test_demo001(city, skill): # 可以传多个,单个fixture参数
assert city == ''北京''
assert skill == ''测试''
def test_demo002(job):
assert job[0] == ''测试'' # fixture 可以返回一个元组,列表或字典
assert job[1] == ''api''
四、fixture的使用
4.1、fixture函数
fixture(scope="function", params=None, autouse=False, ids=None, name=None)
参数说明
scope:fixture函数的作用域;可选值:function(默认)、class、module、session
- function:作用于每个方法或函数,每个方法或函数都运行一次
- class:作用于整个class类,每个class中的所有test只运行一次
- module:作用于整个模块,每个module中的所有test只运行一次
- session:作用于整个session,整个session只运行一次(慎用)
params:列表类型;
一个可选的参数列表;它将会多次调用被fixture标记的方法和 所有用到这个fixture的test测试用例;默认为None;当前调用参数 可以用 request.param 来获取
autouse
如果为True,则为所有测试用例激活fixture,运行测试用例的时候会自动运行被fixture标记的方法; 如果为False,则需要显示指定来激活fixture,不会自动运行
ids
id字符串列表,与params相对应,因此它们也是测试的一部分。 如果没有提供ids,那么将会从params来自动生成
name
fixture的名称。默认为被fixture装饰器标记的函数名
4.2、通过参数引用fixture函数
import pytest
@pytest.fixture()
def before():
print(''\n----------before fixture has run----------'')
class TestA:
def test_a(self, before): # before为被fixture标记的函数,默认为fixture标记的函数名
print(''\n----test_a has run------'')
assert 1
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
4.3、通过使用name参数来引用fixture函数
import pytest
@pytest.fixture(name=''before_fixture_name'')
def before():
print(''\n----------before fixture has run----------'')
class TestA:
def test_a(self, before_fixture_name): # before为被fixture标记的函数,fixture的名称为:before_fixture_name
print(''\n----test_a has run------'')
assert 1
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
4.4、使用@pytest.mark.usefixtures(''fixture函数名'')
import pytest
@pytest.fixture()
def before():
print(''\n----------before fixture has run----------'')
@pytest.mark.usefixtures(''before'')
class TestA:
def test_a(self):
print(''\n----test_a has run------'')
assert 1
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
注意:被fixture标记的函数before会优先于测试用例test_a运行
4.5、通过autouse=True设置默认执行fixture函数
①fixture函数的autouse参数默认等于False;
②fixture函数的autouse参数若为True,刚每个测试函数都会自动调用该fixture函数,而且无需传入fixture函数名
import pytest
@pytest.fixture(autouse=True)
def before():
print(''\n----------before fixture has run----------'')
class TestA:
def test_a(self):
print(''\n----test_a has run------'')
assert 1
def test_b(self):
print(''\n----test_b has run------'')
assert 2
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
4.6、fixture作用域设置成function
import pytest
@pytest.fixture(scope=''function'', autouse=True)
def before():
print(''\n----------before fixture has run----------'')
class TestA:
def test_a(self):
print(''\n----test_a has run------'')
assert 1
def test_b(self):
print(''\n----test_b has run------'')
assert 2
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
4.7、fixture作用域设置成class
import pytest
@pytest.fixture(scope=''class'', autouse=True)
def before():
print(''\n----------before fixture has run----------'')
class TestA:
def test_a(self):
print(''\n----test_a has run------'')
assert 1
def test_b(self):
print(''\n----test_b has run------'')
assert 2
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
4.8、fixture的返回值使用
import pytest
@pytest.fixture()
def before():
print(''\n----------before fixture has run----------'')
return 2
class TestA:
def test_a(self, before):
print(''\n----test_a has run------'')
assert 1 == before # 拿返回值做断言
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
fixture的返回值为2,在测试用例中拿到返回值做断言,断言失败
4.9、fixture的params参数使用
①params形参是fixture函数的可选形参列表,支持列表传入;
②不传此参数时默认为None;
③每个param的值fixture函数都会去调用执行一次,类似for循环。
④可与参数ids一起使用,作为每个参数的标识,类似于用例参数化时的ids作用
import pytest
@pytest.fixture(params=[1, 2, 3])
def before(request):
print(''\n----------before fixture has run----------'')
return request.param
class TestA:
def test_a(self, before):
print(f''\n----test_a has run{before}------'')
assert 1 == before # 拿返回值做断言
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
4.10、fixture的params参数于ids参数结合使用
①fixture函数未配置ids参数之前:用例执行后的标识为传入的params参数
②fixture函数配置ids参数之后:用例执行后的标识为传入的ids参数。并与params参数一一对应
4.11、fixture函数的相互调用(fixture函数与fixture函数之间的依赖关系)
import pytest
@pytest.fixture()
def account():
a = ''account''
print(''\n第一层fixture'')
return a
@pytest.fixture()
def login(account):
print(''第二层fixture'')
class TestLogin:
def test_1(self, login):
print(f''\n直接使用第二层fixture,返回值为{login}'')
def test_2(self, account):
print(f''\n只调用account fixture, 返回值为{account}'')
if __name__ == ''__main__'':
pytest.main([''-s'', ''test_fixture.py''])
注意:如果一个fixture函数依赖另外一个fixture函数,此时不能使@pytest.mark.usefixtures() 调用被依赖的fixture函数,这种调用方式不会生效。而是需要用函数传递的方式才能生效
import pytest
@pytest.fixture()
def login_weibo():
print("==============登陆微博===============")
@pytest.fixture()
# @pytest.mark.usefixtures("login_weibo") #这种方式不会生效
def get_weibo_data(login_weibo): # 这种方式才会生效
"""fixture函数依赖,需要用传递函数的方式"""
print("=============获取微博数据==============")
@pytest.mark.demo
class TestMyCode:
@pytest.mark.usefixtures("get_weibo_data")
def test_fixture_005(self):
"""fixture函数在测试脚本文件中"""
assert 1 == 1
注意:
- 即使fixture函数之间支持相互调用,但普通函数直接使用fixture是不支持的,一定是在测试函数内调用才会逐级调用生效
- 有多层fixture函数调用时,最先执行的是最后一层fixture函数,而不是先执行传入测试函数的fixture函数
- 上层fixture函数的值不会自动return,这里就类似函数相互调用一样的逻辑。【函数调用值需要赋值给一个变量并使用】
ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction
1.Action、RenderAction加载办法的视图,履行Controller → Model → View的次序,然后把产生的页面带回到本来的View中再回传。而Partial、RenderPartial直接加载视图文件内容
2.Html.Partial可以直接供给用户控件名作为参数,而Html.Action须要有对应的Action,在Action内部返回PartailResult(即retun PartialView())。
3.对于简单的没有任何逻辑的用户控件,推荐应用Html.Partial;对于须要设置一些Model的用户控件,推荐应用Html.Action。当然,有Model数据也是可以应用Html.Partial办法的,可以看办法的重载。
4.Html.Partial与Html.Action有啥区别呢?区别就是,Html.Partial只有一个视图,而Html.Action除了视图,还真的有个Action跟它对应,所以,Html.Action功能比Html.Partial要强。
如何调用这个Html.Partial
//1、以视图名使用当前文件夹下的视图(如果没有找到,则搜索 Shared 文件夹)
@Html.Partial(
"_test"
)
//加载对应文件 /Views/Product/_test.cshtml
//2、依据应用根路径定位视图// 以 "/" 或 "~/" 开头的路径代表应用根路径
@Html.Partial(
"~/Views/Product/_test.cshtml"
)
@Html.Partial(
"/Views/Product/_test2.cshtml"
)
//3、加载其他目录的 视图文件
//注意:需要复制views中的web.config 到template目录,否则会提示 "/template/A.cshtml”处的视图必须派生自 WebViewPage 或 WebViewPage<TModel>"
@Html.Partial(
"/template/A.cshtml"
)
asp.net – Html.Partial vs Html.RenderPartial&Html.Action vs Html.RenderAction.任何人都可以描述不同之处
Html.Partial and Html.RenderPartial Html.Action and Html.RenderAction
解决方法
Html.Partial使用已创建的模型(或者可以在没有模型的情况下调用)来渲染指定的视图.
何时使用一个而不是另一个?如果您已有模型并且只想拥有可重复使用的视图,请选择Html.Partial.如果你看到某个部分值得拥有自己的模型和动作,那么使用Html.Action可能是有意义的.
这个问题在this article中有更详细的讨论,你在上面看到的基本上是它的摘录.
今天的关于pytest十五:pytest-html 生成 html 报告和pytest --html的分享已经结束,谢谢您的关注,如果想了解更多关于$ pytest 和 $ python -m pytest 测试的区别、@pytest.mark标记 @pytest.fixture()、ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction、asp.net – Html.Partial vs Html.RenderPartial&Html.Action vs Html.RenderAction.任何人都可以描述不同之处的相关知识,请在本站进行查询。
本文标签: