Python 在测试中使用url_

Python 在测试中使用url_,python,flask,Python,Flask,我正在为一个Flask应用程序编写一些测试,并且遇到了一个问题,即我的测试客户端响应中的url与从测试用例中调用url所生成的url不匹配。例如,我的模板中包含以下内容: <li><a href="#" onClick="requestReport('{{ url_for('report') }}', '{{ session['email'] }}');">Report</a></li> 问题是,即使URL出现在页面上,该测试也会失败,因为模板中

我正在为一个Flask应用程序编写一些测试,并且遇到了一个问题,即我的测试客户端响应中的url与从测试用例中调用url所生成的url不匹配。例如,我的模板中包含以下内容:

<li><a href="#" onClick="requestReport('{{ url_for('report') }}', '{{ session['email'] }}');">Report</a></li>
问题是,即使URL出现在页面上,该测试也会失败,因为模板中用于调用的URL\u产生的输出与我的测试用例中用于调用的URL\u不同。如果我从测试用例代码中打印(“报告”)的url_,我会得到:

http://localhost:5000/api/report
我将app.config中的SERVER\u NAME键设置为“localhost:5000”,因为如果我没有设置SERVER\u 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.
显然,我可以通过在测试用例代码中硬编码URL来解决这个问题,但我更愿意使用URL_,以便将来对URL的更改不会破坏我的测试代码

我尝试了几个不同的字符串作为服务器名称,包括“”它只生成了一个格式错误的URL,但仍然与响应中生成的URL不匹配


除了对URL进行硬编码之外,还有其他方法可以解决此问题吗?

如果在应用程序上下文中使用
URL\u for
,就像在测试代码中一样,Flask会自动假定您想要创建一个包含完整主机名的外部链接(在
服务器名
配置变量中设置)。而模板中的
url\u将创建一个没有主机名的内部链接。所以他们不会匹配。要检查是否相等,需要将
\u 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

对于API测试,您可以使用
test\u request\u 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') 

最上面的答案推送了测试请求上下文,但没有在
tearDown
方法中弹出它。正确的设置和拆卸应如下所示:

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

    def tearDown(self):
        self.context.pop()  # pop it

    def test_hello(self):
        response =  self.client.get(url_for('api.hello'), content_type='text')
        self.assertEqual(response.get_data(as_text=True), 'hello')
如果您使用的是pytest,请签出

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') 
class TestFlaskApi(unittest.TestCase):
    def setUp(self):
        self.app = create_app()
        self.context = self.app.test_request_context()
        self.context.push()  # push it
        self.client = self.app.test_client()

    def tearDown(self):
        self.context.pop()  # pop it

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