测试入门

未匹配的标注

Masonite 测试非常简单。 你可以很轻松地测试很复杂的代码,只需要通过 Masonite 的测试类来扩展你的类。

虽然 Masonite 使用 pytest 来运行测试用例, 但是 Masonite 的测试套件是基于 unittest 的。 所以你将使用 unittest 语法,但是通过 pytest 运行测试用例。 因此,所有语法将采用驼峰大小写,而不是PEP 8 的 小写加下划线用例。只是需要知道所有测试用例断言都是驼峰形式,以符合单元测试标准。

测试环境

当进行测试时,Masonite 会自动设置环境 environment 来测试( testing)。需要的时候,你可以自定义其他测试环境配置信息。

你可以创建一个 .env.testing 文件,在其中可以随意加载任何测试环境变量,默认情况下,他们是不会被提交的。 当 pytest 运行时, 这个文件会被额外加载并重写所有额外的环境变量。

创建测试

你可以简单地创建一个以 test_ 开头的文件,然后创建一个测试类继承自 masonite 的 TestCase 类。

你也可以直接使用命令

$ python craft test SomeFeatureTest

来创建 tests/unit/test_some_feature.py:

from masonite.tests import TestCase

class SomeFeatureTest(TestCase):
    def setUp(self):
        super().setUp()

    def test_something(self):
        self.assertTrue(True)

就是这样了! 你已经准备开始测试了。 请继续阅读以学习如何构建并运行你的测试用例。

运行测试

你可以运行测试用例,通过执行:

$ python -m pytest

这将自动发现(搜索)你的测试用例, 依据 pytest 的搜索规则: automatic tests discovery.
你也可以运行指定的测试类:

$ python -m pytest tests/unit/test_my_feature.py

或者指定一个测试方法:

$ python -m pytest tests/unit/test_my_feature.py::MyFeatureTest::test_feature_is_working

最后,你还可以自动重跑上次失败的用例:

$ python -m pytest --last-failed

构建测试

测试的生命周期

当你运行一个测试类时, 测试类中的每个方法将会依据一个特定的生命周期来运行。

class TestFeatures(TestCase):

    @classmethod
    def setUpClass(cls):
        """在所有测试执行前运行一次"""
        print("Setting up test class")

    @classmethod
    def tearDownClass(cls):
        """在所有测试结束后运行一次"""
        print("Cleaning up test class")

    def setUp(self):
        """在每个测试执行前均运行一次"""
        super().setUp()
        print("Setting up individual unit test")

    def tearDown(self):
        """在每个测试执行后均运行一次"""
        super().tearDown()
        print("Cleaning up individual unit test")

    def test_1(self):
        print("Running test 1")

    def test_2(self):
        print("Running test 2")

运行以上的测试类将会得到这样的输出:

Setting up test class
Setting up individual unit test
Running test 2
Cleaning up individual unit test
Setting up individual unit test
Running test 1
Cleaning up individual unit test
Cleaning up test class

注意:测试方法并不总是根据类中指定的顺序运行的。你应该试着让你的测试独立,而不要假定测试会根据给定的顺序运行。

链接断言

所有以 assert 开始的方法会通过许多断言被链接到一起来运行。所有其他方法会返回某种布尔值或 你可以用来自行断言的值。

断言异常

有时候你需要断言某个给定的代码片断会抛出异。 为此你可以使用标准的 assertRaises() 上下文管理器:

with self.assertRaises(ValidationError) as e:
    # 这里写一些代码
    raise ValidationError("An error occured !")

self.assertEqual(str(e.exception), "An error occured !")

捕获输出

有时候你需要测试某个函数打印到控制台的输出。 为此你可以在测试中使用 captureOutput() 上下文管理器:

with self.captureOutput() as output:
    # 这里写一些代码
    print("Hello World !")

self.assertEqual(output.getvalue().strip(), "Hello World !")

重写调试模式

有时候你需要在测试期间修改调试模式的值。 为此你可使用 debugMode() 上下文管理器:

# 开启调试模式运行代码内容
with self.debugMode() as output:
    self.get("/").assertError()

# 关闭调试模式运行代码内容
with self.debugMode(False) as output:
    self.get("/").assertError()

转储数据

在测试执行期间, print() 语句将不可用。 你可以使用 dump() 测试辅助器在测试时将数据转储到控制台:

def test_can_create_user(self):
    user = User.find(1)
    self.get("/register").assertRedirect()
    self.dump("Hello")
    self.dump(user, "User with ID 1")

注意你可以传入第二个参数来命名转储控制台。

停止测试

如果你想在测试期间停止测试,你可以使用 stop() 辅助器。你甚至可以提供下原因。

def test_can_create_user(self):
    user = User.find(1)
    self.get("/register").assertRedirect()
    self.stop("for debugging")  #== 测试将会在此处停止。

    self.post("/login", {"email": user.email, "password": "secret"})

测试是通过返回 pytest 2 的停止代码(用户中断)来停止的。

测试辅助

Masonite 有不同的辅助器可以轻松地编写代码。 其中一些已经在上面的章节中进行了解释。

使用异常处理器

测试期间会进行异常处理。

self.withExceptionsHandling()

不使用异常处理器

测试期间不会进行异常处理。

self.withoutExceptionsHandling()

注意:测试期间是默认禁用异常处理。

使用Csrf

测试期间会采用 CSRF 保护机制。

self.withCsrf()

不使用Csrf

测试期间不会采用 CSRF 保护机制。

self.withoutCsrf()

注意:测试期间是默认禁用 CSRF 保护机制。

使用Cookies

添加的 Cookies 将会在下一次请求时使用。 这个方法接收键值对形式的字典。 Cookies 字典在每个用例间都会重置。

self.withCookies(data)

使用Headers

添加的 Headers 将会在下一次请求时使用。这个方法接收键值对形式的字典。 Headers 字典在每个用例间都会重置。

self.withHeaders(data)

假定时间

now (或 todaytomorrowyesterday) 实例被创建后,设置要返回的给定时钟实例。对于要在测试期间检查时间戳逻辑,它真的很有用。

这允许控制返回的日期时间来让用例始终是符合预期行为。

given_date = pendulum.datetime(2021, 2, 5)
self.fakeTime(given_date)
self.assertEqual(pendulum.now(), given_date)

注意:当使用这些辅助器时,别忘了使用 restoreTime() 辅助器来重置默认的 pendulum 行为 ,以避免破坏了其他用例。 它可以直接在这个测试中完成或者在 tearDown() 方法中完成。

假定明天的时间

将模拟时间设置为明天。(这是一条捷径,避免使用 self.fakeTime(pendulum.tomorrow()))。

tomorrow = pendulum.tomorrow()
self.fakeTimeTomorrow()
self.assertEqual(pendulum.now(), tomorrow)

假定昨天的时间

将模拟时间设置为昨天。

假定未来的时间

将模拟时间设置为将来给定时间单位的偏移量。 可以在时钟单位中指定单位: secondsminuteshoursday (默认), weeksmonthsyears

self.fakeTimeInFuture(offset, unit="days")
real_now = pendulum.now()
self.fakeTimeInFuture(1, "months")
self.assertEqual(pendulum.now().diff(real_now).in_months(), 1)

假定过去的时间

将模拟时间设置为过去给定时间单位的偏移量。 可以在时钟单位中指定单位: secondsminuteshoursdays (默认),weeksmonthsyears

self.fakeTimeInPast(offset, unit="days")

恢复时间

恢复模拟时间成默认的 pendulum 时间。 当使用 fake 时间辅助器时, 别忘了在最后执行这个。

它可以直接在这个测试中完成或者在 tearDown() 方法中完成。

def tearDown(self):
    super().tearDown()
    self.restoreTime()

def test_creation_date(self):
    self.fakeTimeYesterday()
    # 从现在直到这个单元测试完成, 时间将会模拟成昨天的时间。

当你运行测试类时, 这个测试类中的每个测试方法将会在指定生命期间运行。

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/masonite/4.0/te...

译文地址:https://learnku.com/docs/masonite/4.0/te...

上一篇 下一篇
贡献者:2
讨论数量: 0
发起讨论 只看当前版本


暂无话题~