← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/hasquerycount-details into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/hasquerycount-details into lp:launchpad.

Commit message:
Introduce HasQueryCount.byEquality, which provides details of both sides of a query count mismatch.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/hasquerycount-details/+merge/274289

Introduce HasQueryCount.byEquality, which provides details of both sides of a query count mismatch, and use it everywhere we were previously using something like HasQueryCount(Equals(recorder.count)).  This means that next time we see a buildbot failure in lp.soyuz.browser.tests.test_archive_webservice.TestArchiveWebservice.test_getAllPermissions_constant_query_count we stand some chance of debugging it rather than just having to hit retry.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/hasquerycount-details into lp:launchpad.
=== modified file 'lib/lp/answers/tests/test_question_webservice.py'
--- lib/lp/answers/tests/test_question_webservice.py	2015-03-17 15:34:05 +0000
+++ lib/lp/answers/tests/test_question_webservice.py	2015-10-13 17:01:34 +0000
@@ -294,4 +294,4 @@
         search_questions()
         recorder1, recorder2 = record_two_runs(
             search_questions, create_question, 2)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))

=== modified file 'lib/lp/app/tests/test_security.py'
--- lib/lp/app/tests/test_security.py	2015-07-08 16:05:11 +0000
+++ lib/lp/app/tests/test_security.py	2015-10-13 17:01:34 +0000
@@ -283,4 +283,4 @@
 
         recorder1, recorder2 = record_two_runs(
             check_team_limited_view, create_subscribed_archive, 5)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))

=== modified file 'lib/lp/bugs/browser/tests/test_bugtask.py'
--- lib/lp/bugs/browser/tests/test_bugtask.py	2015-09-28 12:18:09 +0000
+++ lib/lp/bugs/browser/tests/test_bugtask.py	2015-10-13 17:01:34 +0000
@@ -126,7 +126,7 @@
         # This may seem large: it is; there is easily another 25% fat in
         # there.
         self.assertThat(recorder1, HasQueryCount(LessThan(83)))
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_rendered_query_counts_constant_with_attachments(self):
         task = self.factory.makeBugTask()
@@ -137,7 +137,7 @@
             lambda: self.factory.makeBugAttachment(bug=task.bug),
             1, 9, login_method=lambda: login(ADMIN_EMAIL))
         self.assertThat(recorder1, HasQueryCount(LessThan(84)))
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def makeLinkedBranchMergeProposal(self, sourcepackage, bug, owner):
         with person_logged_in(owner):
@@ -218,7 +218,7 @@
             lambda: add_activity("description", self.factory.makePerson()),
             1, 20, login_method=lambda: login(ADMIN_EMAIL))
         self.assertThat(recorder1, HasQueryCount(LessThan(84)))
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_rendered_query_counts_constant_with_milestones(self):
         # More queries are not used for extra milestones.
@@ -2007,7 +2007,7 @@
             lambda: self.factory.makeBug(target=product),
             1, 10, login_method=lambda: login(ANONYMOUS))
         self.assertThat(recorder1, HasQueryCount(LessThan(46)))
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_mustache_model_in_json(self):
         """The IJSONRequestCache should contain mustache_model.

=== modified file 'lib/lp/bugs/model/tests/test_bug.py'
--- lib/lp/bugs/model/tests/test_bug.py	2014-04-29 00:44:32 +0000
+++ lib/lp/bugs/model/tests/test_bug.py	2015-10-13 17:01:34 +0000
@@ -538,8 +538,7 @@
 
         recorder1, recorder2 = record_two_runs(
             get_subscribers, create_subscriber, 3)
-        self.assertThat(
-            recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_getSubscribersFromDuplicates_with_recipients_query_count(self):
         # getSubscribersFromDuplicates() uses a constant number of queries
@@ -562,8 +561,7 @@
 
         recorder1, recorder2 = record_two_runs(
             get_subscribers, create_subscriber, 3)
-        self.assertThat(
-            recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_getAlsoNotifiedSubscribers_with_recipients_query_count(self):
         # getAlsoNotifiedSubscribers() uses a constant number of queries when
@@ -590,8 +588,7 @@
 
         recorder1, recorder2 = record_two_runs(
             get_subscribers, create_stuff, 3)
-        self.assertThat(
-            recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_newMessage_default(self):
         # Adding a bug message notifies that is was created.

=== modified file 'lib/lp/buildmaster/browser/tests/test_builder.py'
--- lib/lp/buildmaster/browser/tests/test_builder.py	2015-09-11 13:56:38 +0000
+++ lib/lp/buildmaster/browser/tests/test_builder.py	2015-10-13 17:01:34 +0000
@@ -52,7 +52,7 @@
         nb_objects = 2
         recorder1, recorder2 = record_two_runs(
             builders_homepage_render, create_build, nb_objects)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_builders_recipe_build_query_count(self):
         def create_build():
@@ -65,7 +65,7 @@
         nb_objects = 2
         recorder1, recorder2 = record_two_runs(
             builders_homepage_render, create_build, nb_objects)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_builders_translation_template_build_query_count(self):
         def create_build():
@@ -75,7 +75,7 @@
         nb_objects = 2
         recorder1, recorder2 = record_two_runs(
             builders_homepage_render, create_build, nb_objects)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_builders_variety_query_count(self):
         def create_builds():
@@ -90,4 +90,4 @@
         nb_objects = 2
         recorder1, recorder2 = record_two_runs(
             builders_homepage_render, create_builds, nb_objects)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))

=== modified file 'lib/lp/buildmaster/browser/tests/test_builder_views.py'
--- lib/lp/buildmaster/browser/tests/test_builder_views.py	2015-09-11 13:56:38 +0000
+++ lib/lp/buildmaster/browser/tests/test_builder_views.py	2015-10-13 17:01:34 +0000
@@ -102,7 +102,7 @@
         flush_database_updates()
         with StormStatementRecorder() as recorder2:
             getSpecificJobs(build_farm_jobs)
-        self.assertThat(recorder, HasQueryCount(Equals(recorder2.count)))
+        self.assertThat(recorder, HasQueryCount.byEquality(recorder2))
 
     def test_getSpecificJobs_no_specific_job(self):
         build_farm_job_source = getUtility(IBuildFarmJobSource)
@@ -180,7 +180,7 @@
             partial(self.createRecipeBuildWithBuilder, builder=self.builder),
             self.nb_objects)
 
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_build_history_queries_count_binary_package_builds(self):
         # Rendering to builder's history issues a constant number of queries
@@ -192,7 +192,7 @@
             partial(self.createBinaryPackageBuild, builder=self.builder),
             self.nb_objects)
 
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_build_history_queries_count_binary_package_builds_in_ppa(self):
         # Rendering to builder's history issues a constant number of queries
@@ -205,7 +205,7 @@
             builder_history_render, createBinaryPackageBuildInPPA,
             self.nb_objects)
 
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_build_history_queries_count_translation_template_builds(self):
         # Rendering to builder's history issues a constant number of queries
@@ -219,7 +219,7 @@
                 builder=self.builder),
             self.nb_objects)
 
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_build_history_private_build_view(self):
         self.createRecipeBuildWithBuilder(builder=self.builder)

=== modified file 'lib/lp/code/browser/tests/test_branchmergeproposallisting.py'
--- lib/lp/code/browser/tests/test_branchmergeproposallisting.py	2015-09-30 10:25:58 +0000
+++ lib/lp/code/browser/tests/test_branchmergeproposallisting.py	2015-10-13 17:01:34 +0000
@@ -859,7 +859,7 @@
         recorder2, view2 = self.createUserBMPsAndRecordQueries(
             base_bmps + added_bmps)
         self.assertEqual(base_bmps + added_bmps, view2.proposal_count)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def createProductBMP(self, product):
         merge_target = self._makeStackedOnBranchChain(target=product)
@@ -895,7 +895,7 @@
         recorder2, view2 = self.createProductBMPsAndRecordQueries(
             base_bmps + added_bmps)
         self.assertEqual(base_bmps + added_bmps, view2.proposal_count)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
 
 class ActiveReviewsPerformanceBzr(

=== modified file 'lib/lp/code/browser/tests/test_gitrepository.py'
--- lib/lp/code/browser/tests/test_gitrepository.py	2015-10-07 16:06:35 +0000
+++ lib/lp/code/browser/tests/test_gitrepository.py	2015-10-13 17:01:34 +0000
@@ -287,7 +287,7 @@
 
         recorder1, recorder2 = record_two_runs(
             lambda: self.getMainText(repository, "+index"), create_ref, 10)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
 
 class TestGitRepositoryEditReviewerView(TestCaseWithFactory):

=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipelisting.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipelisting.py	2015-10-05 13:36:06 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipelisting.py	2015-10-13 17:01:34 +0000
@@ -53,7 +53,7 @@
 
         recorder1, recorder2 = record_two_runs(
             lambda: self.getMainText(branch, "+recipes"), create_recipe, 5)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_project_query_count(self):
         # The number of queries required to render the list of all recipes
@@ -69,7 +69,7 @@
 
         recorder1, recorder2 = record_two_runs(
             lambda: self.getMainText(project, "+recipes"), create_recipe, 5)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_person_query_count(self):
         # The number of queries required to render the list of all recipes
@@ -85,4 +85,4 @@
 
         recorder1, recorder2 = record_two_runs(
             lambda: self.getMainText(person, "+recipes"), create_recipe, 5)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))

=== modified file 'lib/lp/registry/browser/tests/test_distribution_views.py'
--- lib/lp/registry/browser/tests/test_distribution_views.py	2015-09-25 13:54:46 +0000
+++ lib/lp/registry/browser/tests/test_distribution_views.py	2015-10-13 17:01:34 +0000
@@ -365,7 +365,7 @@
 
         recorder1, recorder2 = record_two_runs(
             render_mirrors, create_mirror, 10)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
 
 class TestDistributionArchiveMirrorsView(

=== modified file 'lib/lp/registry/browser/tests/test_distroseries.py'
--- lib/lp/registry/browser/tests/test_distroseries.py	2015-10-01 10:25:19 +0000
+++ lib/lp/registry/browser/tests/test_distroseries.py	2015-10-13 17:01:34 +0000
@@ -1006,8 +1006,7 @@
             text_content(u"%.2f" % statement_count_per_row))
         # Query count is ~O(1) (i.e. not dependent of the number of
         # differences displayed).
-        self.assertThat(
-            recorder3, HasQueryCount(Equals(recorder2.count)))
+        self.assertThat(recorder3, HasQueryCount.byEquality(recorder2))
 
     def test_queries_single_parent(self):
         dsp = self.factory.makeDistroSeriesParent()
@@ -1516,9 +1515,7 @@
         flush_database_caches()
         with StormStatementRecorder() as recorder2:
             self.makeView(derived_series).requestUpgrades()
-        self.assertThat(
-            recorder2,
-            HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def makeDSDJob(self, dsd):
         """Create a `DistroSeriesDifferenceJob` to update `dsd`."""

=== modified file 'lib/lp/registry/browser/tests/test_person.py'
--- lib/lp/registry/browser/tests/test_person.py	2015-08-06 16:48:48 +0000
+++ lib/lp/registry/browser/tests/test_person.py	2015-10-13 17:01:34 +0000
@@ -932,7 +932,7 @@
 
         recorder1, recorder2 = record_two_runs(
             get_participations, create_subscriptions, 5)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
 
 class TestPersonRelatedPackagesView(TestCaseWithFactory):

=== modified file 'lib/lp/registry/browser/tests/test_person_webservice.py'
--- lib/lp/registry/browser/tests/test_person_webservice.py	2015-05-11 13:17:41 +0000
+++ lib/lp/registry/browser/tests/test_person_webservice.py	2015-10-13 17:01:34 +0000
@@ -179,7 +179,7 @@
         get_members()
         recorder1, recorder2 = record_two_runs(
             get_members, create_member, 2)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_many_ppas(self):
         # POSTing to a person with many PPAs doesn't OOPS.
@@ -258,7 +258,7 @@
         find_teams()
         recorder1, recorder2 = record_two_runs(
             find_teams, create_match, 2)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_findPerson(self):
         # The search can be restricted to people.

=== modified file 'lib/lp/registry/tests/test_distroseries.py'
--- lib/lp/registry/tests/test_distroseries.py	2015-03-06 13:19:06 +0000
+++ lib/lp/registry/tests/test_distroseries.py	2015-10-13 17:01:34 +0000
@@ -528,7 +528,7 @@
                 status=PackagePublishingStatus.PUBLISHED),
             5, 5)
         self.assertThat(recorder1, HasQueryCount(Equals(11)))
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_getBinaryPackagePublishing_query_count(self):
         # Check that the number of queries required to publish binary
@@ -550,7 +550,7 @@
                 status=PackagePublishingStatus.PUBLISHED),
             5, 5)
         self.assertThat(recorder1, HasQueryCount(Equals(15)))
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
 
 class TestDistroSeriesWebservice(TestCaseWithFactory):

=== modified file 'lib/lp/services/webhooks/tests/test_browser.py'
--- lib/lp/services/webhooks/tests/test_browser.py	2015-10-01 12:24:36 +0000
+++ lib/lp/services/webhooks/tests/test_browser.py	2015-10-13 17:01:34 +0000
@@ -142,7 +142,7 @@
         self.makeView("+webhooks")()
         recorder1, recorder2 = record_two_runs(
             lambda: self.makeView("+webhooks")(), create_webhook, 10)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
 
 class TestWebhooksViewGitRepository(

=== modified file 'lib/lp/services/webhooks/tests/test_webservice.py'
--- lib/lp/services/webhooks/tests/test_webservice.py	2015-09-24 13:44:02 +0000
+++ lib/lp/services/webhooks/tests/test_webservice.py	2015-10-13 17:01:34 +0000
@@ -154,7 +154,7 @@
         get_deliveries()
         recorder1, recorder2 = record_two_runs(
             get_deliveries, create_delivery, 2)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_delete(self):
         with person_logged_in(self.owner):
@@ -302,7 +302,7 @@
         get_webhooks()
         recorder1, recorder2 = record_two_runs(
             get_webhooks, create_webhook, 2)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_newWebhook(self):
         self.useFixture(FeatureFixture({'webhooks.new.enabled': 'true'}))

=== modified file 'lib/lp/snappy/browser/tests/test_snaplisting.py'
--- lib/lp/snappy/browser/tests/test_snaplisting.py	2015-10-05 13:36:06 +0000
+++ lib/lp/snappy/browser/tests/test_snaplisting.py	2015-10-13 17:01:34 +0000
@@ -148,7 +148,7 @@
     def assertSnapsQueryCount(self, context, item_creator):
         recorder1, recorder2 = record_two_runs(
             lambda: self.getMainText(context, "+snaps"), item_creator, 5)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_branch_query_count(self):
         # The number of queries required to render the list of all snap

=== modified file 'lib/lp/soyuz/browser/tests/test_archive.py'
--- lib/lp/soyuz/browser/tests/test_archive.py	2015-09-30 23:31:45 +0000
+++ lib/lp/soyuz/browser/tests/test_archive.py	2015-10-13 17:01:34 +0000
@@ -174,4 +174,4 @@
             lambda: create_initialized_view(
                 source, '+copy-packages', user=person),
             create_targets, nb_objects)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))

=== modified file 'lib/lp/soyuz/browser/tests/test_archive_packages.py'
--- lib/lp/soyuz/browser/tests/test_archive_packages.py	2015-09-29 01:38:34 +0000
+++ lib/lp/soyuz/browser/tests/test_archive_packages.py	2015-10-13 17:01:34 +0000
@@ -447,4 +447,4 @@
                 view.render()
         recorder1, recorder2 = record_two_runs(
             ppa_index_render, self.createPackage, 2, 3)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))

=== modified file 'lib/lp/soyuz/browser/tests/test_archive_webservice.py'
--- lib/lp/soyuz/browser/tests/test_archive_webservice.py	2015-09-23 11:52:26 +0000
+++ lib/lp/soyuz/browser/tests/test_archive_webservice.py	2015-10-13 17:01:34 +0000
@@ -108,7 +108,7 @@
 
         recorder1, recorder2 = record_two_runs(
             get_permissions, create_permission, 1)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
     def test_delete(self):
         with admin_logged_in():

=== modified file 'lib/lp/testing/matchers.py'
--- lib/lp/testing/matchers.py	2015-09-29 01:38:34 +0000
+++ lib/lp/testing/matchers.py	2015-10-13 17:01:34 +0000
@@ -173,9 +173,14 @@
     as a test attachment.
     """
 
-    def __init__(self, count_matcher):
+    def __init__(self, count_matcher, other_query_collector=None):
         """Create a HasQueryCount that will match using count_matcher."""
         self.count_matcher = count_matcher
+        self.other_query_collector = other_query_collector
+
+    @classmethod
+    def byEquality(cls, other_query_collector):
+        return cls(Equals(other_query_collector.count), other_query_collector)
 
     def __str__(self):
         return "HasQueryCount(%s)" % self.count_matcher
@@ -184,24 +189,34 @@
         mismatch = self.count_matcher.match(something.count)
         if mismatch is None:
             return None
-        return _MismatchedQueryCount(mismatch, something)
+        return _MismatchedQueryCount(
+            mismatch, something,
+            other_query_collector=self.other_query_collector)
 
 
 class _MismatchedQueryCount(Mismatch):
     """The Mismatch for a HasQueryCount matcher."""
 
-    def __init__(self, mismatch, query_collector):
+    def __init__(self, mismatch, query_collector, other_query_collector=None):
         self.count_mismatch = mismatch
         self.query_collector = query_collector
+        self.other_query_collector = other_query_collector
 
     def describe(self):
         return "queries do not match: %s" % (self.count_mismatch.describe(),)
 
+    @staticmethod
+    def _getQueryDetails(collector):
+        result = [unicode(query).encode('utf8') for query in collector.queries]
+        return Content(UTF8_TEXT, lambda: ['\n'.join(result)])
+
     def get_details(self):
-        result = []
-        for query in self.query_collector.queries:
-            result.append(unicode(query).encode('utf8'))
-        return {'queries': Content(UTF8_TEXT, lambda: ['\n'.join(result)])}
+        details = {}
+        details['queries'] = self._getQueryDetails(self.query_collector)
+        if self.other_query_collector is not None:
+            details['other_queries'] = self._getQueryDetails(
+                self.other_query_collector)
+        return details
 
 
 class IsNotProxied(Mismatch):

=== modified file 'lib/lp/testing/tests/test_matchers.py'
--- lib/lp/testing/tests/test_matchers.py	2015-09-29 01:38:34 +0000
+++ lib/lp/testing/tests/test_matchers.py	2015-10-13 17:01:34 +0000
@@ -4,7 +4,9 @@
 __metaclass__ = type
 
 from testtools.matchers import (
+    Equals,
     Is,
+    KeysEqual,
     LessThan,
     Not,
     )
@@ -231,6 +233,30 @@
             "queries do not match: %s" % (LessThan(2).match(2).describe(),),
             mismatch.describe())
 
+    def test_byEquality(self):
+        old_collector = RequestTimelineCollector()
+        old_collector.count = 2
+        old_collector.queries = [("a", "1"), ("b", "2")]
+        new_collector = RequestTimelineCollector()
+        new_collector.count = 3
+        new_collector.queries = [("a", "1"), ("b", "2"), ("c", "3")]
+        matcher = HasQueryCount.byEquality(old_collector)
+        mismatch = matcher.match(new_collector)
+        self.assertThat(mismatch, Not(Is(None)))
+        details = mismatch.get_details()
+        old_lines = []
+        new_lines = []
+        self.assertThat(details, KeysEqual("queries", "other_queries"))
+        self.assertEqual("text", details["other_queries"].content_type.type)
+        old_lines.append("".join(details["other_queries"].iter_text()))
+        self.assertEqual("text", details["queries"].content_type.type)
+        new_lines.append("".join(details["queries"].iter_text()))
+        self.assertEqual(["('a', '1')\n('b', '2')"], old_lines)
+        self.assertEqual(["('a', '1')\n('b', '2')\n('c', '3')"], new_lines)
+        self.assertEqual(
+            "queries do not match: %s" % (Equals(2).match(3).describe(),),
+            mismatch.describe())
+
 
 class TestBrowserQueryMatching(TestCaseWithFactory):
 

=== modified file 'lib/lp/translations/browser/tests/test_pofile_view.py'
--- lib/lp/translations/browser/tests/test_pofile_view.py	2015-10-01 10:25:19 +0000
+++ lib/lp/translations/browser/tests/test_pofile_view.py	2015-10-13 17:01:34 +0000
@@ -80,7 +80,7 @@
             lambda: create_initialized_view(
                 pofile, '+translate', principal=person)(),
             create_suggestions, nb_objects)
-        self.assertThat(recorder2, HasQueryCount(Equals(recorder1.count)))
+        self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
 
 
 class TestPOFileTranslateViewInvalidFiltering(TestCaseWithFactory):


Follow ups