Flask 单元测试并且不理解我对“TypeError:需要一个类似字节的对象,而不是‘str’”的修复

Joh*_*ann 5 python tdd unit-testing flask

我目前正在构建一个小型 Web 应用程序来提高我的技能,作为其中的一部分,我正在尝试全面采用最佳实践、测试、CI、架构良好、干净的代码,所有这些。在过去的几个会议中,我一直在努力测试我的根路由,而不是通过路由函数返回一个字符串,我正在渲染一个模板,我已经让它工作了,但我没有理解它为什么起作用,这让我很困扰。

主要是使用 b,在我的断言字符串之前,我认为这与我渲染的不是字符串,而是 html 表示的事实有关,类似于 return 和 print 之间的区别,但我是朦胧,很感激有人来教我。

我要问的行是 test_homepage_response 函数的第 4 行。以及它是如何运作的。特别是关于我收到的这个错误:

返回的错误:

ERROR: test_home_welcome_return (tests.home_page_tests.HomePageTestClass)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/xibalba/code/reel/tests/home_page_tests.py", line 31, in test_home_welcome_return
    self.assertIn(u"Welcome to Reel!", response.data)
  File "/usr/local/lib/python3.6/unittest/case.py", line 1077, in assertIn
    if member not in container:
TypeError: a bytes-like object is required, not 'str'
Run Code Online (Sandbox Code Playgroud)

我对回家路线的测试:


# Test Suite
import unittest
from reel import app
from reel.views import home_welcome


class HomePageTesttClass(unittest.TestCase):

    @classmethod
    def setupClass(cls):
        pass

    @classmethod
    def tearDownClass(cls):
        pass

    def setUp(self):
        self.app = app.test_client()
        self.app.testing = True

    def test_homepage_response(self):
        result = self.app.get('/')
        self.assertEqual(result.status_code, 200)
        self.assertIn(b"Welcome to Reel!", result.data)

    def tearDown(self):
        pass

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

我的意见文件:


from reel import app
from flask import render_template


@app.route('/')
def home_welcome():
    return render_template("homepage.html")

@app.route('/signup')
def signup_welcome():
    return 'Welcome to the signup page!'

@app.route('/login')
def login_welcome():
    return 'Welcome to the login page!'

@app.route('/become_a_guide')
def guide_welcome():
    return 'Welcome to the guide page!'

@app.route('/help')
def help_welcome():
    return 'Welcome to the help page!'
Run Code Online (Sandbox Code Playgroud)

我使用的一些资源来解决这个问题,这使我转向使用 b:

https://github.com/mjhea0/flaskr-tdd#first-test

字符串文字前面的“b”字符有什么作用?

感谢这是一个很长的问题,我试图提供尽可能多的背景信息,因为老实说我对这个问题感到很愚蠢,但我不想在不知道为什么我使用的解决方案有效的情况下继续。

一如既往地谢谢你。

idj*_*jaw 5

非常简单的答案是, string 属于str type,而string前面的 "b"现在将使它成为一个bytes对象,属于type bytes。因此,期望它们实际上应该彼此相等,因为不同类型的比较将预期失败。

此外,您正在使用的断言assertIn是使用in关键字进行测试。为了正确测试in,您需要在这种情况下将字节与字节进行比较。

观察这个简单的例子,它带你复制你正在经历的事情:

>>> s = "this is a string"
>>> t = "this is another string"
>>> type(s) == type(t)
True
>>> sb = b"this is a string"
>>> type(sb) == type(s)
False
>>> s in sb
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: a bytes-like object is required, not 'str'
Run Code Online (Sandbox Code Playgroud)

所以,正如你所看到的,“b”实际上在这里起到了一个功能性的作用,它为你提供了一种不同类型的“对象”。

可能解码为一个字符串:

>>> res = sb.decode()
>>> type(res)
<class 'str'>
Run Code Online (Sandbox Code Playgroud)

建议明确您的解码,但是:

>>> res = sb.decode('utf-8')
>>> type(res)
<class 'str'>
Run Code Online (Sandbox Code Playgroud)

最后,这里是关于一个优秀的更详细的解释遏制与测试bytes。希望这可以帮助。