GVKun编程网logo

pytest十五:pytest-html 生成 html 报告(pytest --html)

4

对于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十五: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 测试的区别

我想了解跑步有什么区别:

  1. $ pytest

  1. $ python -m pytest tests

我在 Mac 上的虚拟环境中工作。 第一个解决方案给了我一个错误:

  1. ModuleNotFoundError: No module named ''app''

第二种解决方案工作正常。

为什么第二个解决方案有效而第一个无效? 如何仅使用 $ pytest 使其工作?

我的文件夹结构:

  1. ├── app.py
  2. ├── requirements.txt
  3. ├── templates
  4. ├── tests
  5. ├── conftest.py
  6. ├── functional
  7. ├── __init__.py
  8. └── test_s.py
  9. └── unit
  10. ├── __init__.py
  11. └── test_app.py
  12. └── venv

在 test_app.py 中,此行失败:

  1. from app import app

解决方法

不同之处在于搜索模块的 Python 算法,以及 Pytest 发现测试的方式。

1. Python 模块搜索

根据Python实现如下:

  1. 在内置模块中搜索
  2. 在 sys.path 列表中搜索:
    • 第一个“当前目录”被添加到 sys.path
    • 第二个 PYTHONPATH 内容被添加到 sys.path
    • 然后最后将所有 Python 安装目录添加到 sys.path

这可能非常复杂。我在这里看到“在扩展模式下”很好地解释了这一点: Where is Python''s sys.path initialized from?

2. Pytest 发现机制

所以

  1. from app import app

当您像上面一样导入“应用程序”时,在这两种情况下都会以不同的方式进行搜索。换句话说,对于这两种情况,sys.path 中的“当前目录”设置不同。您可以通过打印 sys.path 列表来检查这一点。

这不是问题,而是 python/pytest 的工作方式。

3.解决方法示例

你可以通过例如下面的方法解决这个问题(我把它放在单独的 pathmagic.py 文件中,然后在 test_xyz 中导入 pathmagic )

  1. import pathmagic # noqa Pep8 uncheck

pathmagic.py

  1. import sys
  2. import os
  3. sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
  4. 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()

@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}")

image.png

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

image.png

三、@pytest.fixture()详细使用

3.1、fixture简介

  • 有独立的命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活;
  • 按模块化的方式实现,每个fixture都可以互相调用
  • fixture的范围从简单的单元测试到复杂的功能测试,可以对fixture配置参数,或者跨函数function,类class,模块module或整个测试session范围

3.2、用途

  1. 做测试前后的初始化设置,如测试数据准备,连接数据库,打开浏览器等这些操作都可以使用fixture来实现
  2. 测试用例的前置条件可以使用fixture实现
  3. 支持经典的xunit fixture ,像unittest使用的setup和teardown
  4. 可以实现unittest不能实现的功能,比如unittest中的测试用例和测试用例之间是无法传递参数和数据的,但是fixture却可以解决这个问题

3.3、fixture可以当做参数传入

  1. 定义fixture跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture命名不要用test_开头,跟用例区分开。用例才是test_开头的命名
  2. fixture是可以有返回值的,如果没return默认返回None。用例调用fixture的返回值,直接就是把fixture的函数名称当成变量传入
  3. fixture装饰器里的scope有四个级别的参数。function(不写默认这个)、class、module、session
  4. 除scope之外。还有params、autouse、ids、name等
  5. fixture可以返回一个元组、列表或字典
  6. test_用例可传单个、多个fixture参数
  7. 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)

参数说明

  1. scope:fixture函数的作用域;可选值:function(默认)、class、module、session

    • function:作用于每个方法或函数,每个方法或函数都运行一次
    • class:作用于整个class类,每个class中的所有test只运行一次
    • module:作用于整个模块,每个module中的所有test只运行一次
    • session:作用于整个session,整个session只运行一次(慎用)
  2. params:列表类型;

     一个可选的参数列表;它将会多次调用被fixture标记的方法和
     所有用到这个fixture的test测试用例;默认为None;当前调用参数
     可以用 request.param 来获取
    
  3. autouse

     如果为True,则为所有测试用例激活fixture,运行测试用例的时候会自动运行被fixture标记的方法;
     如果为False,则需要显示指定来激活fixture,不会自动运行
    
  4. ids

     id字符串列表,与params相对应,因此它们也是测试的一部分。
     如果没有提供ids,那么将会从params来自动生成
  5. 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''])

image.png

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''])

image.png

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参数
image.png

②fixture函数配置ids参数之后:用例执行后的标识为传入的ids参数。并与params参数一一对应

image.png

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''])

image.png

注意:如果一个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

image.png

注意:

  1. 即使fixture函数之间支持相互调用,但普通函数直接使用fixture是不支持的,一定是在测试函数内调用才会逐级调用生效
  2. 有多层fixture函数调用时,最先执行的是最后一层fixture函数,而不是先执行传入测试函数的fixture函数
  3. 上层fixture函数的值不会自动return,这里就类似函数相互调用一样的逻辑。【函数调用值需要赋值给一个变量并使用】

ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction

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.任何人都可以描述不同之处

asp.net – Html.Partial vs Html.RenderPartial&Html.Action vs Html.RenderAction.任何人都可以描述不同之处

在ASP.NET MVC中,有什么区别:

Html.Partial and Html.RenderPartial
Html.Action and Html.RenderAction

解决方法

Html.Action调用控制器的动作,这意味着它实例化控制器实体,调用动作方法,构建模型并返回视图结果.

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.任何人都可以描述不同之处的相关知识,请在本站进行查询。

本文标签: