Das anfängliche Problem
Ich bin ein CrawlSpider Klasse zu schreiben (die scrapy
Bibliothek) und stützen sich auf eine Menge von scrapy
asynchronen Magie, damit es funktioniert. Hier ist sie, abgespeckte:erstellen Unit-Test für die Methode von scrapy CrawlSpider
class MySpider(CrawlSpider):
rules = [Rule(LinkExtractor(allow='myregex'), callback='parse_page')]
# some other class attributes
def __init__(self, *args, **kwargs):
super(MySpider, self).__init__(*args, **kwargs)
self.response = None
self.loader = None
def parse_page_section(self):
soup = BeautifulSoup(self.response.body, 'lxml')
# Complicated scraping logic using BeautifulSoup
self.loader.add_value(mykey, myvalue)
# more methods parsing other sections of the page
# also using self.response and self.loader
def parse_page(self, response):
self.response = response
self.loader = ItemLoader(item=Item(), response=response)
self.parse_page_section()
# call other methods to collect more stuff
self.loader.load_item()
Die Klasse Attribut rule
meine Spinne erzählt bestimmte Links zu folgen und springen Sie zu einer Callback-Funktion sobald die Web-Seiten heruntergeladen werden. Mein Ziel ist es, die Parsing-Methode namens parse_page_section
zu testen, ohne den Crawler auszuführen oder sogar echte HTTP-Anfragen zu stellen.
Was habe ich versucht,
Instinktiv Ich wandte mich an die mock
Bibliothek. Ich verstehe, wie Sie eine Funktion verspotten, um zu testen, ob sie aufgerufen wurde (mit welchen Argumenten und ob es irgendwelche Nebenwirkungen gab ...), aber das ist nicht das, was ich will. Ich möchte ein gefälschtes Objekt MySpider
instanziieren und gerade genug Attribute zuweisen, um parse_page_section
Methode darauf aufrufen zu können.
Im obigen Beispiel, ich brauche ein response
Objekt mein ItemLoader
und speziell ein self.response.body
Attribut zu instanziiert meine BeautifulSoup
instanziiert. Im Prinzip könnte ich gefälschte Objekte wie diese machen:
from argparse import Namespace
my_spider = MySpider(CrawlSpider)
my_spider.response = NameSpace(body='<html>...</html>')
, die gut auf die BeautifulSoup
Klasse funktioniert, aber ich müsste mehr Attribute hinzufügen, um ein ItemLoader
-Objekt zu erstellen. Für komplexere Situationen würde es hässlich und unüberschaubar werden.
Meine Frage
Ist dies der ganz richtige Ansatz? Ich kann keine ähnlichen Beispiele im Internet finden, daher denke ich, dass mein Ansatz auf einer grundlegenderen Ebene falsch ist. Jede Einsicht würde sehr geschätzt werden.
@ChrisP danke für Ihre Bearbeitung. Ich habe das "scrapy" -Label nicht an erster Stelle platziert, weil ich dachte, dass die Frage im Allgemeinen mit Unit-Testing zu tun hat. – cyberbikepunk
Es ist definitiv Unit-Tests im Allgemeinen, aber Leute, die viel Scraping machen, können einige einzigartige Einsichten für Unit-Test-Scraper haben. – ChrisP
In diesem speziellen 'CrawlSpider'-Fall konnte ich mit dem Vortäuschen eines Antwortobjekts davonkommen. Es ist schwierig, es von Hand zu tun, aber könnte das helfen? http://requests-mock.readthedocs.io/en/latest/overview.html. Wäre das ein guter Ansatz? – cyberbikepunk