在测试中使用url_for

Kev*_*erg 4 python flask

我正在为Flask应用程序编写一些测试,并且遇到了一个问题,我的test_client响应中的URL与通过在测试用例中调用url_for产生的URL不匹配.例如,我的模板中有以下内容:

<li><a href="#" onClick="requestReport('{{ url_for('report') }}', '{{ session['email'] }}');">Report</a></li>
Run Code Online (Sandbox Code Playgroud)

test_client的响应将其呈现为:

<li><a href="#" onClick="requestReport('/api/report', 'user@domain.com');">Report</a></li>
Run Code Online (Sandbox Code Playgroud)

我有一个测试用例,用于检查以确保在某些条件下此网址显示在页面上:

self.client = self.app.test_client(use_cookies=True)
with self.app.app_context():
    page = self.client.get(url_for("index"), follow_redirects=True).data.decode()
    assert url_for("report") in page
Run Code Online (Sandbox Code Playgroud)

问题是,即使URL出现在页面上,此测试也会失败,因为模板中的url_for调用产生的输出与我的测试用例中的url_for调用不同.如果我从测试用例代码中打印url_for("report"),我得到:

http://localhost:5000/api/report
Run Code Online (Sandbox Code Playgroud)

我将app.config中的SERVER_NAME键设置为"localhost:5000",因为如果我没有设置SERVER_NAME,则测试用例代码将抛出此错误:

RuntimeError: Application was not able to create a URL adapter for request independent URL generation. You might be able to fix this by setting the SERVER_NAME config variable.
Run Code Online (Sandbox Code Playgroud)

显然,我可以通过在我的测试用例代码中对URL进行硬编码来解决这个问题,但我更倾向于使用URL_for,以便将来对我的URL的更改不会破坏我的测试代码.

我尝试了几个不同的字符串作为SERVER_NAME,包括"",它只生成一个格式错误的URL,但仍然与响应中生成的URL不匹配.

除了硬编码URL之外,还有其他方法可以解决这个问题吗?

小智 8

对于API测试,您可以使用 test_request_context

class TestFlaskApi(unittest.TestCase):                                          
    def setUp(self):                                                            
        self.app = create_app()                                                 
        self.app_context = self.app.test_request_context()                      
        self.app_context.push()                                                 
        self.client = self.app.test_client() 

    def test_hello(self):                                                       
        response =  self.client.get(url_for('api.hello'),                       
                                    content_type='text')                        

        self.assertEqual(response.get_data(as_text=True), 'hello') 
Run Code Online (Sandbox Code Playgroud)


MrL*_*eeh 5

如果您url_for像在测试代码中一样在应用程序上下文中使用,Flask 会自动假设您想要创建一个包含完整主机名(在配置SERVER_NAME变量中设置)的外部链接。而url_for您的模板中的 将会创建一个不带主机名的内部链接。所以他们不会匹配。要检查相等性,您需要将该_external属性显式设置为False

self.client = self.app.test_client(use_cookies=True)
with self.app.app_context():
    page = self.client.get(url_for("index"), follow_redirects=True).data.decode()
    assert url_for("report", _external=False) in page
Run Code Online (Sandbox Code Playgroud)