В bookspider.py у меня есть:
from typing import Iterable
import scrapy
from scrapy.http import Request
class BookSpider(scrapy.Spider):
name = None
def start_requests(self) -> Iterable[Request]:
yield scrapy.Request("https://books.toscrape.com/")
def parse(self, response):
books = response.css("article.product_pod")
for book in books:
yield {
"name": self.name,
"title": book.css("h3 a::text").get().strip(),
}
В test_bookspider.py у меня есть:
import json
import os
from pytest_twisted import inlineCallbacks
from scrapy.crawler import CrawlerRunner
from twisted.internet import defer
from bookspider import BookSpider
@inlineCallbacks
def test_bookspider():
runner = CrawlerRunner(
settings = {
"REQUEST_FINGERPRINTER_IMPLEMENTATION": "2.7",
"FEEDS": {"books.json": {"format": "json"}},
"TWISTED_REACTOR": "twisted.internet.asyncioreactor.AsyncioSelectorReactor",
# "TWISTED_REACTOR": "twisted.internet.selectreactor.SelectReactor",
}
)
yield runner.crawl(BookSpider, name = "books")
with open("books.json", "r") as f:
books = json.load(f)
assert len(books) >= 1
assert books[0]["name"] == "books"
assert books[0]["title"] == "A Light in the ..."
os.remove("books.json")
defer.returnValue(None)
Если "TWISTED_REACTOR": "twisted.internet.asyncioreactor.AsyncioSelectorReactor" раскомментировать, я получаю следующую ошибку:
Exception: The installed reactor (twisted.internet.selectreactor.SelectReactor) does not match the requested one (twisted.internet.asyncioreactor.AsyncioSelectorReactor)
С "TWISTED_REACTOR": "twisted.internet.selectreactor.SelectReactor" без комментариев мой тест пройден.
Может ли кто-нибудь объяснить это поведение и, в более широком смысле, как тестировать CrawlerRunner или CrawlerProcess с помощью pytest?






Если вы используете pytest-twisted, вам нужно указать ему установить соответствующий реактор, передав --reactor=asyncio в команду pytest, иначе он установит реактор по умолчанию. См. https://github.com/pytest-dev/pytest-twisted#using-the-plugin
как протестировать CrawlerRunner или CrawlerProcess с помощью pytest?
Вам не следует использовать CrawlerProcess в таких вещах, как тесты pytest, потому что он запустит и остановит реактор за вас. Если вам действительно нужно их протестировать, вам следует написать тесты, которые используют один процесс для каждого вызова CrawlerProcess.