From a8621bbc2929b904dfe14985dd1f94aeedc86648 Mon Sep 17 00:00:00 2001 From: tpeng Date: Thu, 26 Jun 2014 11:28:03 +0200 Subject: [PATCH 1/3] show all the missing field when scrapes contract fails --- scrapy/contracts/default.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scrapy/contracts/default.py b/scrapy/contracts/default.py index 20582503d..0f6bdbad2 100644 --- a/scrapy/contracts/default.py +++ b/scrapy/contracts/default.py @@ -84,6 +84,6 @@ class ScrapesContract(Contract): def post_process(self, output): for x in output: if isinstance(x, (BaseItem, dict)): - for arg in self.args: - if not arg in x: - raise ContractFail("'%s' field is missing" % arg) + missing = [arg for arg in self.args if arg not in x] + if missing: + raise ContractFail("'%s' field is missing" % " ".join(missing)) From bff335cf7f90a0dc3aeafc199aaa81697d5f122b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Chaves?= Date: Mon, 5 Aug 2019 15:47:58 +0200 Subject: [PATCH 2/3] Improve the error message in contract failures due to multiple missing fields --- scrapy/contracts/default.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scrapy/contracts/default.py b/scrapy/contracts/default.py index 0f6bdbad2..7745959a7 100644 --- a/scrapy/contracts/default.py +++ b/scrapy/contracts/default.py @@ -86,4 +86,5 @@ class ScrapesContract(Contract): if isinstance(x, (BaseItem, dict)): missing = [arg for arg in self.args if arg not in x] if missing: - raise ContractFail("'%s' field is missing" % " ".join(missing)) + raise ContractFail( + "Missing fields: %s" % ", ".join(missing)) From 9119798a5ce10aaf015d1af647c5b85e312d2386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Chaves?= Date: Mon, 5 Aug 2019 15:49:07 +0200 Subject: [PATCH 3/3] Add test coverage for contract failures involving multiple missing fields --- tests/test_contracts.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/test_contracts.py b/tests/test_contracts.py index a06bb2cc3..a728099c0 100644 --- a/tests/test_contracts.py +++ b/tests/test_contracts.py @@ -123,6 +123,14 @@ class TestSpider(Spider): """ return {'url': response.url} + def scrapes_multiple_missing_fields(self, response): + """ returns item with no name + @url http://scrapy.org + @returns items 1 1 + @scrapes name url + """ + return {} + def parse_no_url(self, response): """ method with no url @returns items 1 1 @@ -256,6 +264,13 @@ class ContractsManagerTest(unittest.TestCase): request.callback(response) self.should_fail() + # scrapes_multiple_missing_fields + request = self.conman.from_method(spider.scrapes_multiple_missing_fields, self.results) + request.callback(response) + self.should_fail() + message = 'ContractFail: Missing fields: name, url' + assert message in self.results.failures[-1][-1] + def test_custom_contracts(self): self.conman.from_spider(CustomContractSuccessSpider(), self.results) self.should_succeed()