如何对执行get请求的测试类进行单元化

时间:2017-10-17 00:58:20

标签: python unit-testing testing web-scraping

说我想从特定网站上抓取“长篇”帖子。为了做到这一点,我创建了以下类:

import requests

class PostScraper:

    THRESHOLD = 100

    def __init__(self, thread_id):
        self.url = 'foo.bar/thread-%s?pg=last' % thread_id

    def get_long_posts(self):
        page = requests.get(self.url)
        soup = BeautifulSoup(page.content, 'html.parser')
        posts = soup.find_all('div', 'post-text')
        return [post if len(post.text) > THRESHOLD for post in posts]

我想为此编写一个单元测试,但我不确定如何正确地进行它...我想像这样的伪Python:

def test_getting_long_posts():
    scraper = PostScraper(None) # <- Not sure what to pass in. Advice?
    stub = {'text': '<html></html>', 'status': '200'}
    bind(url=scraper.url, response=stub)
    posts = scraper.get_long_posts()
    assert.equals(len(posts), 0)

我对单元测试有些新意,特别是在Python中。这种方法是否有意义?我应该如何 这个?

1 个答案:

答案 0 :(得分:0)

最好以这样的方式编写课程,即获取网址文本内容的过程与扫描合适帖子的文本的过程是分开的。

通过这种方式,您可以使用已知数量的合适帖子创建自己的手工制作的html文本,并测试您的函数是否找到了正确的数字。

这是实现分离的一种方式:

class PostScraper(object):

    THRESHOLD = 100

    def __init__(self, thread_id):
        self.url = 'foo.bar/thread-%s?pg=last' % thread_id
        self.content = None

    def fetch_page(self):
        self.content = requests.get(self.url).content

    def get_long_posts(self):
        soup = BeautifulSoup(self.content, 'html.parser')
        posts = soup.find_all('div', 'post-text')
        return [post if len(post.text) > THRESHOLD for post in posts]

在测试代码时,您根本不会调用fetch_page(),而是可以直接将self.content指定为您创建的虚假页面内容。