Bug 1518152 - Create a TelemetryTestUtils.jsm and start using it in browser/modules/test. r=Dexter
authorMark Banner <standard8@mozilla.com>
Wed, 09 Jan 2019 09:08:42 +0000
changeset 510119 5f5e0f6f9b55d05e0186a647c8f7e2bbe9df25e3
parent 510118 045c6ce06b3d2251809d6b51dc780ba7d7d9e156
child 510120 17b9f7326ef3a3176837edaa5b722fbf76a28336
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersDexter
bugs1518152
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1518152 - Create a TelemetryTestUtils.jsm and start using it in browser/modules/test. r=Dexter Differential Revision: https://phabricator.services.mozilla.com/D15839
browser/modules/test/browser/browser_UsageTelemetry.js
browser/modules/test/browser/browser_UsageTelemetry_content.js
browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js
browser/modules/test/browser/browser_UsageTelemetry_content_aboutRestartRequired.js
browser/modules/test/browser/browser_UsageTelemetry_domains.js
browser/modules/test/browser/browser_UsageTelemetry_private_and_restore.js
browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
browser/modules/test/browser/head.js
toolkit/components/telemetry/tests/moz.build
toolkit/components/telemetry/tests/utils/TelemetryTestUtils.jsm
--- a/browser/modules/test/browser/browser_UsageTelemetry.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry.js
@@ -15,33 +15,34 @@ ChromeUtils.defineModuleGetter(this, "MI
 
 // Reset internal URI counter in case URIs were opened by other tests.
 Services.obs.notifyObservers(null, TELEMETRY_SUBSESSION_TOPIC);
 
 /**
  * Get a snapshot of the scalars and check them against the provided values.
  */
 let checkScalars = (countsObject) => {
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
 
   // Check the expected values. Scalars that are never set must not be reported.
-  checkScalar(scalars, MAX_CONCURRENT_TABS, countsObject.maxTabs,
-              "The maximum tab count must match the expected value.");
-  checkScalar(scalars, TAB_EVENT_COUNT, countsObject.tabOpenCount,
-              "The number of open tab event count must match the expected value.");
-  checkScalar(scalars, MAX_CONCURRENT_WINDOWS, countsObject.maxWindows,
-              "The maximum window count must match the expected value.");
-  checkScalar(scalars, WINDOW_OPEN_COUNT, countsObject.windowsOpenCount,
-              "The number of window open event count must match the expected value.");
-  checkScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs,
-              "The total URI count must match the expected value.");
-  checkScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount,
-              "The unique domains count must match the expected value.");
-  checkScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs,
-              "The unfiltered URI count must match the expected value.");
+  TelemetryTestUtils.assertScalar(scalars, MAX_CONCURRENT_TABS, countsObject.maxTabs,
+    "The maximum tab count must match the expected value.");
+  TelemetryTestUtils.assertScalar(scalars, TAB_EVENT_COUNT, countsObject.tabOpenCount,
+    "The number of open tab event count must match the expected value.");
+  TelemetryTestUtils.assertScalar(scalars, MAX_CONCURRENT_WINDOWS, countsObject.maxWindows,
+    "The maximum window count must match the expected value.");
+  TelemetryTestUtils.assertScalar(scalars, WINDOW_OPEN_COUNT, countsObject.windowsOpenCount,
+    "The number of window open event count must match the expected value.");
+  TelemetryTestUtils.assertScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs,
+    "The total URI count must match the expected value.");
+  TelemetryTestUtils.assertScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount,
+    "The unique domains count must match the expected value.");
+  TelemetryTestUtils.assertScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs,
+    "The unfiltered URI count must match the expected value.");
 };
 
 add_task(async function test_tabsAndWindows() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
 
   let openedTabs = [];
   let expectedTabOpenCount = 0;
@@ -136,17 +137,17 @@ add_task(async function test_subsessionS
 });
 
 function checkTabCountHistogram(result, expected, message) {
   Assert.deepEqual(result.values, expected, message);
 }
 
 add_task(async function test_tabsHistogram() {
   let openedTabs = [];
-  let tabCountHist = getAndClearHistogram("TAB_COUNT");
+  let tabCountHist = TelemetryTestUtils.getAndClearHistogram("TAB_COUNT");
 
   checkTabCountHistogram(tabCountHist.snapshot(), {}, "TAB_COUNT telemetry - initial tab counts");
 
   // Add a new tab and check that the count is right.
   BrowserUsageTelemetry._lastRecordTabCount = 0;
   openedTabs.push(await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank"));
   checkTabCountHistogram(tabCountHist.snapshot(), {1: 0, 2: 1, 3: 0}, "TAB_COUNT telemetry - opening tabs");
 
--- a/browser/modules/test/browser/browser_UsageTelemetry_content.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_content.js
@@ -44,17 +44,17 @@ add_task(async function setup() {
     Services.telemetry.canRecordExtended = oldCanRecord;
   });
 });
 
 add_task(async function test_context_menu() {
   // Let's reset the Telemetry data.
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   // Open a new tab with a page containing some text.
   let tab =
     await BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/plain;charset=utf8,test%20search");
 
   info("Select all the text in the page.");
   await ContentTask.spawn(tab.linkedBrowser, "", async function() {
     return new Promise(resolve => {
@@ -70,59 +70,65 @@ add_task(async function test_context_men
                                            gBrowser.selectedBrowser);
   await popupPromise;
 
   info("Click on search.");
   let searchItem = contextMenu.getElementsByAttribute("id", "context-searchselect")[0];
   searchItem.click();
 
   info("Validate the search metrics.");
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_CONTEXT_MENU, "search", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_CONTEXT_MENU, "search", 1);
   Assert.equal(Object.keys(scalars[SCALAR_CONTEXT_MENU]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch.contextmenu", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.contextmenu", 1);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "contextmenu", null, {engine: "other-MozSearch"}]]);
+  TelemetryTestUtils.assertEvents(events, [
+    ["navigation", "search", "contextmenu", null, {engine: "other-MozSearch"}],
+  ]);
 
   contextMenu.hidePopup();
   BrowserTestUtils.removeTab(gBrowser.selectedTab);
   BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function test_about_newtab() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:newtab", false);
   await ContentTask.spawn(tab.linkedBrowser, null, async function() {
     await ContentTaskUtils.waitForCondition(() => !content.document.hidden);
   });
 
   info("Trigger a simple serch, just text + enter.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await typeInSearchField(tab.linkedBrowser, "test query", "newtab-search-text");
   await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, tab.linkedBrowser);
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_ABOUT_NEWTAB, "search_enter", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_ABOUT_NEWTAB, "search_enter", 1);
   Assert.equal(Object.keys(scalars[SCALAR_ABOUT_NEWTAB]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch.newtab", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.newtab", 1);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "about_newtab", "enter", {engine: "other-MozSearch"}]]);
+  TelemetryTestUtils.assertEvents(events, [
+    ["navigation", "search", "about_newtab", "enter", {engine: "other-MozSearch"}],
+  ]);
 
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_content_aboutHome.js
@@ -44,17 +44,17 @@ add_task(async function setup() {
     Services.telemetry.canRecordExtended = oldCanRecord;
   });
 });
 
 add_task(async function test_abouthome_activitystream_simpleQuery() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
 
   info("Load about:home.");
   BrowserTestUtils.loadURI(tab.linkedBrowser, "about:home");
   await BrowserTestUtils.browserStopped(tab.linkedBrowser, "about:home");
 
   info("Wait for ContentSearchUI search provider to initialize.");
@@ -64,23 +64,26 @@ add_task(async function test_abouthome_a
 
   info("Trigger a simple search, just test + enter.");
   let p = BrowserTestUtils.browserStopped(tab.linkedBrowser, "http://example.com/?q=test+query");
   await typeInSearchField(tab.linkedBrowser, "test query", "newtab-search-text");
   await BrowserTestUtils.synthesizeKey("VK_RETURN", {}, tab.linkedBrowser);
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_ABOUT_HOME, "search_enter", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_ABOUT_HOME, "search_enter", 1);
   Assert.equal(Object.keys(scalars[SCALAR_ABOUT_HOME]).length, 1,
     "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch.abouthome", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.abouthome", 1);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "about_home", "enter", {engine: "other-MozSearch"}]]);
+  TelemetryTestUtils.assertEvents(events, [
+    ["navigation", "search", "about_home", "enter", {engine: "other-MozSearch"}],
+  ]);
 
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/modules/test/browser/browser_UsageTelemetry_content_aboutRestartRequired.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_content_aboutRestartRequired.js
@@ -6,25 +6,25 @@ add_task(async function test_aboutRestar
   let CrashHandlers = {};
   ChromeUtils.import("resource:///modules/ContentCrashHandlers.jsm",
                      CrashHandlers);
 
   // Let's reset the counts.
   Services.telemetry.clearScalars();
 
   let scalars =
-    getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT);
+    TelemetryTestUtils.getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT);
 
   // Check preconditions
   is(scalars[SCALAR_BUILDID_MISMATCH], undefined,
      "Build ID mismatch count should be undefined");
 
   // Simulate buildID mismatch
   CrashHandlers.TabCrashHandler._crashedTabCount = 1;
   CrashHandlers.TabCrashHandler.sendToRestartRequiredPage(
     gBrowser.selectedTab.linkedBrowser);
 
   scalars =
-    getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT);
+    TelemetryTestUtils.getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTOUT);
 
   is(scalars[SCALAR_BUILDID_MISMATCH], 1,
      "Build ID mismatch count should be 1.");
 });
--- a/browser/modules/test/browser/browser_UsageTelemetry_domains.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_domains.js
@@ -44,23 +44,24 @@ function browserLocationChanged(browser)
 }
 
 add_task(async function test_URIAndDomainCounts() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
 
   let checkCounts = (countsObject) => {
     // Get a snapshot of the scalars and then clear them.
-    const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
-    checkScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs,
-                "The URI scalar must contain the expected value.");
-    checkScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount,
-                "The unique domains scalar must contain the expected value.");
-    checkScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs,
-                "The unfiltered URI scalar must contain the expected value.");
+    const scalars = TelemetryTestUtils.getParentProcessScalars(
+      Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
+    TelemetryTestUtils.assertScalar(scalars, TOTAL_URI_COUNT, countsObject.totalURIs,
+      "The URI scalar must contain the expected value.");
+    TelemetryTestUtils.assertScalar(scalars, UNIQUE_DOMAINS_COUNT, countsObject.domainCount,
+      "The unique domains scalar must contain the expected value.");
+    TelemetryTestUtils.assertScalar(scalars, UNFILTERED_URI_COUNT, countsObject.totalUnfilteredURIs,
+      "The unfiltered URI scalar must contain the expected value.");
   };
 
   // Check that about:blank doesn't get counted in the URI total.
   let firstTab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
   checkCounts({totalURIs: 0, domainCount: 0, totalUnfilteredURIs: 0});
 
   // Open a different page and check the counts.
   await BrowserTestUtils.loadURI(firstTab.linkedBrowser, "http://example.com/");
--- a/browser/modules/test/browser/browser_UsageTelemetry_private_and_restore.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_private_and_restore.js
@@ -25,17 +25,18 @@ add_task(async function test_privateMode
   Services.telemetry.clearScalars();
 
   // Open a private window and load a website in it.
   let privateWin = await BrowserTestUtils.openNewBrowserWindow({private: true});
   await BrowserTestUtils.loadURI(privateWin.gBrowser.selectedBrowser, "http://example.com/");
   await BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser);
 
   // Check that tab and window count is recorded.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
 
   ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs in private mode.");
   ok(!(UNFILTERED_URI_COUNT in scalars), "We should not track URIs in private mode.");
   ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains in private mode.");
   is(scalars[TAB_EVENT_COUNT], 1, "The number of open tab event count must match the expected value.");
   is(scalars[MAX_CONCURRENT_TABS], 2, "The maximum tab count must match the expected value.");
   is(scalars[WINDOW_OPEN_COUNT], 1, "The number of window open event count must match the expected value.");
   is(scalars[MAX_CONCURRENT_WINDOWS], 2, "The maximum window count must match the expected value.");
@@ -74,17 +75,18 @@ add_task(async function test_sessionRest
 
   // Load the custom state and wait for SSTabRestored, as we want to make sure
   // that the URI counting code was hit.
   let tabRestored = BrowserTestUtils.waitForEvent(gBrowser.tabContainer, "SSTabRestored");
   SessionStore.setBrowserState(JSON.stringify(state));
   await tabRestored;
 
   // Check that the URI is not recorded.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN);
 
   ok(!(TOTAL_URI_COUNT in scalars), "We should not track URIs from restored sessions.");
   ok(!(UNFILTERED_URI_COUNT in scalars), "We should not track URIs from restored sessions.");
   ok(!(UNIQUE_DOMAINS_COUNT in scalars), "We should not track unique domains from restored sessions.");
 
   // Restore the original session and cleanup.
   let sessionRestored = promiseBrowserStateRestored();
   SessionStore.setBrowserState(JSON.stringify(state));
--- a/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
@@ -92,100 +92,111 @@ add_task(async function setup() {
     Services.telemetry.setEventRecordingEnabled("navigation", false);
   });
 });
 
 add_task(async function test_plainQuery() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
-  let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let resultMethodHist =
+    TelemetryTestUtils.getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
+  let search_hist =
+    TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Simulate entering a simple search.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInSearchbar("simple query");
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_enter", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_enter", 1);
   Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch.searchbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.searchbar", 1);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "searchbar", "enter", {engine: "other-MozSearch"}]]);
+  TelemetryTestUtils.assertEvents(events, [
+    ["navigation", "search", "searchbar", "enter", {engine: "other-MozSearch"}],
+  ]);
 
   // Check the histograms as well.
   let resultMethods = resultMethodHist.snapshot();
   checkHistogramResults(resultMethods,
     URLBAR_SELECTED_RESULT_METHODS.enter,
     "FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   BrowserTestUtils.removeTab(tab);
 });
 
 // Performs a search using the first result, a one-off button, and the Return
 // (Enter) key.
 add_task(async function test_oneOff_enter() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
-  let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let resultMethodHist =
+    TelemetryTestUtils.getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
+  let search_hist =
+    TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Perform a one-off search using the first engine.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInSearchbar("query");
 
   info("Pressing Alt+Down to highlight the first one off engine.");
   EventUtils.synthesizeKey("KEY_ArrowDown", {altKey: true});
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_oneoff", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_oneoff", 1);
   Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch2.searchbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch2.searchbar", 1);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "searchbar", "oneoff", {engine: "other-MozSearch2"}]]);
+  TelemetryTestUtils.assertEvents(events, [
+    ["navigation", "search", "searchbar", "oneoff", {engine: "other-MozSearch2"}],
+  ]);
 
   // Check the histograms as well.
   let resultMethods = resultMethodHist.snapshot();
   checkHistogramResults(resultMethods,
     URLBAR_SELECTED_RESULT_METHODS.enter,
     "FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   BrowserTestUtils.removeTab(tab);
 });
 
 // Performs a search using the second result, a one-off button, and the Return
 // (Enter) key.  This only tests the FX_SEARCHBAR_SELECTED_RESULT_METHOD
 // histogram since test_oneOff_enter covers everything else.
 add_task(async function test_oneOff_enterSelection() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist =
+    TelemetryTestUtils.getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   // Create an engine to generate search suggestions and add it as default
   // for this test.
   const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
   let suggestionEngine = await new Promise((resolve, reject) => {
     Services.search.addEngine(url, "", false, {
       onSuccess(engine) { resolve(engine); },
       onError() { reject(); },
@@ -218,17 +229,18 @@ add_task(async function test_oneOff_ente
 });
 
 // Performs a search using a click on a one-off button.  This only tests the
 // FX_SEARCHBAR_SELECTED_RESULT_METHOD histogram since test_oneOff_enter covers
 // everything else.
 add_task(async function test_oneOff_click() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist =
+    TelemetryTestUtils.getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Type a query.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInSearchbar("query");
   info("Click the first one-off button.");
   BrowserSearch.searchBar.textbox.popup.oneOffButtons.getSelectableButtons(false)[0].click();
@@ -242,18 +254,20 @@ add_task(async function test_oneOff_clic
   BrowserTestUtils.removeTab(tab);
 });
 
 // Clicks the first suggestion offered by the test search engine.
 add_task(async function test_suggestion_click() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
-  let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let resultMethodHist =
+    TelemetryTestUtils.getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
+  let search_hist =
+    TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   // Create an engine to generate search suggestions and add it as default
   // for this test.
   const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
   let suggestionEngine = await new Promise((resolve, reject) => {
     Services.search.addEngine(url, "", false, {
       onSuccess(engine) { resolve(engine); },
       onError() { reject(); },
@@ -268,29 +282,32 @@ add_task(async function test_suggestion_
   info("Perform a one-off search using the first engine.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInSearchbar("query");
   info("Clicking the searchbar suggestion.");
   clickSearchbarSuggestion("queryfoo");
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_suggestion", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(
+    Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_SEARCHBAR, "search_suggestion", 1);
   Assert.equal(Object.keys(scalars[SCALAR_SEARCHBAR]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
   let searchEngineId = "other-" + suggestionEngine.name;
-  checkKeyedHistogram(search_hist, searchEngineId + ".searchbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, searchEngineId + ".searchbar", 1);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "searchbar", "suggestion", {engine: searchEngineId}]]);
+  TelemetryTestUtils.assertEvents(events, [
+    ["navigation", "search", "searchbar", "suggestion", {engine: searchEngineId}],
+  ]);
 
   // Check the histograms as well.
   let resultMethods = resultMethodHist.snapshot();
   checkHistogramResults(resultMethods,
     URLBAR_SELECTED_RESULT_METHODS.click,
     "FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   Services.search.defaultEngine = previousEngine;
@@ -300,17 +317,18 @@ add_task(async function test_suggestion_
 
 // Selects and presses the Return (Enter) key on the first suggestion offered by
 // the test search engine.  This only tests the
 // FX_SEARCHBAR_SELECTED_RESULT_METHOD histogram since test_suggestion_click
 // covers everything else.
 add_task(async function test_suggestion_enterSelection() {
   // Let's reset the counts.
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist =
+    TelemetryTestUtils.getAndClearHistogram("FX_SEARCHBAR_SELECTED_RESULT_METHOD");
 
   // Create an engine to generate search suggestions and add it as default
   // for this test.
   const url = getRootDirectory(gTestPath) + "usageTelemetrySearchSuggestions.xml";
   let suggestionEngine = await new Promise((resolve, reject) => {
     Services.search.addEngine(url, "", false, {
       onSuccess(engine) { resolve(engine); },
       onError() { reject(); },
--- a/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_urlbar.js
@@ -12,28 +12,16 @@ ChromeUtils.defineModuleGetter(this, "UR
                                "resource:///modules/BrowserUsageTelemetry.jsm");
 
 ChromeUtils.defineModuleGetter(this, "URLBAR_SELECTED_RESULT_METHODS",
                                "resource:///modules/BrowserUsageTelemetry.jsm");
 
 ChromeUtils.defineModuleGetter(this, "SearchTelemetry",
                               "resource:///modules/SearchTelemetry.jsm");
 
-function checkHistogramResults(resultIndexes, expected, histogram) {
-  for (let [i, val] of Object.entries(resultIndexes.values)) {
-    if (i == expected) {
-      Assert.equal(val, 1,
-        `expected counts should match for ${histogram} index ${i}`);
-    } else {
-      Assert.equal(!!val, false,
-        `unexpected counts should be zero for ${histogram} index ${i}`);
-    }
-  }
-}
-
 let searchInAwesomebar = async function(inputText, win = window) {
   await new Promise(r => waitForFocus(r, win));
   // Write the search query in the urlbar.
   win.gURLBar.focus();
   win.gURLBar.value = inputText;
 
   // This is not strictly necessary, but some things, like clearing oneoff
   // buttons status, depend on actual input events that the user would normally
@@ -154,530 +142,490 @@ add_task(async function setup() {
     Services.telemetry.setEventRecordingEnabled("navigation", false);
   });
 });
 
 add_task(async function test_simpleQuery() {
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
 
-  let resultIndexHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
-  let resultTypeHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
-  let resultIndexByTypeHist = getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let resultIndexHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
+  let resultTypeHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
+  let resultIndexByTypeHist = TelemetryTestUtils.getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Simulate entering a simple search.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInAwesomebar("simple query");
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_URLBAR, "search_enter", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_URLBAR, "search_enter", 1);
   Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
-  checkKeyedHistogram(search_hist, "other-MozSearch.alias", undefined);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", undefined);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "urlbar", "enter", {engine: "other-MozSearch"}]]);
+  TelemetryTestUtils.assertEvents(events, [["navigation", "search", "urlbar", "enter", {engine: "other-MozSearch"}]]);
 
   // Check the histograms as well.
-  let resultIndexes = resultIndexHist.snapshot();
-  checkHistogramResults(resultIndexes, 0, "FX_URLBAR_SELECTED_RESULT_INDEX");
+  TelemetryTestUtils.assertHistogram(resultIndexHist, 0, 1);
 
-  let resultTypes = resultTypeHist.snapshot();
-  checkHistogramResults(resultTypes,
-    URLBAR_SELECTED_RESULT_TYPES.searchengine,
-    "FX_URLBAR_SELECTED_RESULT_TYPE");
+  TelemetryTestUtils.assertHistogram(resultTypeHist,
+    URLBAR_SELECTED_RESULT_TYPES.searchengine, 1);
 
-  let resultIndexByType = resultIndexByTypeHist.snapshot().searchengine;
-  checkHistogramResults(resultIndexByType,
-    0,
-    "FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+  TelemetryTestUtils.assertKeyedHistogramValue(resultIndexByTypeHist,
+    "searchengine", 0, 1);
 
-  let resultMethods = resultMethodHist.snapshot();
-  checkHistogramResults(resultMethods,
-    URLBAR_SELECTED_RESULT_METHODS.enter,
-    "FX_URLBAR_SELECTED_RESULT_METHOD");
+  TelemetryTestUtils.assertHistogram(resultMethodHist,
+    URLBAR_SELECTED_RESULT_METHODS.enter, 1);
 
   BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function test_searchAlias() {
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
 
-  let resultIndexHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
-  let resultTypeHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
-  let resultIndexByTypeHist = getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let resultIndexHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
+  let resultTypeHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
+  let resultIndexByTypeHist = TelemetryTestUtils.getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Search using a search alias.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInAwesomebar("mozalias query");
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_URLBAR, "search_alias", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_URLBAR, "search_alias", 1);
   Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
-  checkKeyedHistogram(search_hist, "other-MozSearch.alias", undefined);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", undefined);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "urlbar", "alias", {engine: "other-MozSearch"}]]);
+  TelemetryTestUtils.assertEvents(events, [["navigation", "search", "urlbar", "alias", {engine: "other-MozSearch"}]]);
 
   // Check the histograms as well.
-  let resultIndexes = resultIndexHist.snapshot();
-  checkHistogramResults(resultIndexes, 0, "FX_URLBAR_SELECTED_RESULT_INDEX");
+  TelemetryTestUtils.assertHistogram(resultIndexHist, 0, 1);
 
-  let resultTypes = resultTypeHist.snapshot();
-  checkHistogramResults(resultTypes,
-    URLBAR_SELECTED_RESULT_TYPES.searchengine,
-    "FX_URLBAR_SELECTED_RESULT_TYPE");
+  TelemetryTestUtils.assertHistogram(resultTypeHist,
+    URLBAR_SELECTED_RESULT_TYPES.searchengine, 1);
 
-  let resultIndexByType = resultIndexByTypeHist.snapshot().searchengine;
-  checkHistogramResults(resultIndexByType,
-    0,
-    "FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+  TelemetryTestUtils.assertKeyedHistogramValue(resultIndexByTypeHist,
+    "searchengine", 0, 1);
 
-  let resultMethods = resultMethodHist.snapshot();
-  checkHistogramResults(resultMethods,
-    URLBAR_SELECTED_RESULT_METHODS.enter,
-    "FX_URLBAR_SELECTED_RESULT_METHOD");
+  TelemetryTestUtils.assertHistogram(resultMethodHist,
+    URLBAR_SELECTED_RESULT_METHODS.enter, 1);
 
   BrowserTestUtils.removeTab(tab);
 });
 
 add_task(async function test_internalSearchAlias() {
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Search using an internal search alias.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInAwesomebar("@mozaliasfoo query");
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
-  checkKeyedHistogram(search_hist, "other-MozSearch.alias", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", 1);
 
   info("Search using the other internal search alias.");
   p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInAwesomebar("@mozaliasbar query");
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 2);
-  checkKeyedHistogram(search_hist, "other-MozSearch.alias", 2);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 2);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", 2);
 
   BrowserTestUtils.removeTab(tab);
 });
 
 // Performs a search using the first result, a one-off button, and the Return
 // (Enter) key.
 add_task(async function test_oneOff_enter() {
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
 
-  let resultIndexHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
-  let resultTypeHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
-  let resultIndexByTypeHist = getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let resultIndexHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
+  let resultTypeHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
+  let resultIndexByTypeHist = TelemetryTestUtils.getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Perform a one-off search using the first engine.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInAwesomebar("query");
 
   info("Pressing Alt+Down to take us to the first one-off engine.");
   EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true });
   EventUtils.synthesizeKey("KEY_Enter");
   await p;
 
   // Check if the scalars contain the expected values.
-  const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-  checkKeyedScalar(scalars, SCALAR_URLBAR, "search_oneoff", 1);
+  const scalars = TelemetryTestUtils.getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+  TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_URLBAR, "search_oneoff", 1);
   Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
                "This search must only increment one entry in the scalar.");
 
   // Make sure SEARCH_COUNTS contains identical values.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
-  checkKeyedHistogram(search_hist, "other-MozSearch.alias", undefined);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.alias", undefined);
 
   // Also check events.
   let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
   events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-  checkEvents(events, [["navigation", "search", "urlbar", "oneoff", {engine: "other-MozSearch"}]]);
+  TelemetryTestUtils.assertEvents(events, [["navigation", "search", "urlbar", "oneoff", {engine: "other-MozSearch"}]]);
 
   // Check the histograms as well.
-  let resultIndexes = resultIndexHist.snapshot();
-  checkHistogramResults(resultIndexes, 0, "FX_URLBAR_SELECTED_RESULT_INDEX");
+  TelemetryTestUtils.assertHistogram(resultIndexHist, 0, 1);
 
-  let resultTypes = resultTypeHist.snapshot();
-  checkHistogramResults(resultTypes,
-    URLBAR_SELECTED_RESULT_TYPES.searchengine,
-    "FX_URLBAR_SELECTED_RESULT_TYPE");
+  TelemetryTestUtils.assertHistogram(resultTypeHist,
+    URLBAR_SELECTED_RESULT_TYPES.searchengine, 1);
 
-  let resultIndexByType = resultIndexByTypeHist.snapshot().searchengine;
-  checkHistogramResults(resultIndexByType,
-    0,
-    "FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+  TelemetryTestUtils.assertKeyedHistogramValue(resultIndexByTypeHist,
+    "searchengine", 0, 1);
 
-  let resultMethods = resultMethodHist.snapshot();
-  checkHistogramResults(resultMethods,
-    URLBAR_SELECTED_RESULT_METHODS.enter,
-    "FX_URLBAR_SELECTED_RESULT_METHOD");
+  TelemetryTestUtils.assertHistogram(resultMethodHist,
+    URLBAR_SELECTED_RESULT_METHODS.enter, 1);
 
   BrowserTestUtils.removeTab(tab);
 });
 
 // Performs a search using the second result, a one-off button, and the Return
 // (Enter) key.  This only tests the FX_URLBAR_SELECTED_RESULT_METHOD histogram
 // since test_oneOff_enter covers everything else.
 add_task(async function test_oneOff_enterSelection() {
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
 
   await withNewSearchEngine(async function() {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
     info("Type a query. Suggestions should be generated by the test engine.");
     let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
     await searchInAwesomebar("query");
 
     info("Select the second result, press Alt+Down to take us to the first one-off engine.");
     EventUtils.synthesizeKey("KEY_ArrowDown");
     EventUtils.synthesizeKey("KEY_ArrowDown", {altKey: true});
     EventUtils.synthesizeKey("KEY_Enter");
     await p;
 
-    let resultMethods = resultMethodHist.snapshot();
-    checkHistogramResults(resultMethods,
-      URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection,
-      "FX_URLBAR_SELECTED_RESULT_METHOD");
+    TelemetryTestUtils.assertHistogram(resultMethodHist,
+      URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection, 1);
 
     BrowserTestUtils.removeTab(tab);
   });
 });
 
 // Performs a search using a click on a one-off button.  This only tests the
 // FX_URLBAR_SELECTED_RESULT_METHOD histogram since test_oneOff_enter covers
 // everything else.
 add_task(async function test_oneOff_click() {
   Services.telemetry.clearScalars();
 
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
 
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
   info("Type a query.");
   let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
   await searchInAwesomebar("query");
   info("Click the first one-off button.");
   gURLBar.popup.oneOffSearchButtons.getSelectableButtons(false)[0].click();
   await p;
 
-  let resultMethods = resultMethodHist.snapshot();
-  checkHistogramResults(resultMethods,
-    URLBAR_SELECTED_RESULT_METHODS.click,
-    "FX_URLBAR_SELECTED_RESULT_METHOD");
+  TelemetryTestUtils.assertHistogram(resultMethodHist,
+    URLBAR_SELECTED_RESULT_METHODS.click, 1);
 
   BrowserTestUtils.removeTab(tab);
 });
 
 // Clicks the first suggestion offered by the test search engine.
 add_task(async function test_suggestion_click() {
   Services.telemetry.clearScalars();
   Services.telemetry.clearEvents();
 
-  let resultIndexHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
-  let resultTypeHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
-  let resultIndexByTypeHist = getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let resultIndexHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_INDEX");
+  let resultTypeHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_TYPE");
+  let resultIndexByTypeHist = TelemetryTestUtils.getAndClearKeyedHistogram("FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   await withNewSearchEngine(async function(engine) {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
     info("Type a query. Suggestions should be generated by the test engine.");
     let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
     await searchInAwesomebar("query");
     info("Clicking the urlbar suggestion.");
     await clickURLBarSuggestion("queryfoo");
     await p;
 
     // Check if the scalars contain the expected values.
-    const scalars = getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
-    checkKeyedScalar(scalars, SCALAR_URLBAR, "search_suggestion", 1);
+    const scalars = TelemetryTestUtils.getParentProcessScalars(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true, false);
+    TelemetryTestUtils.assertKeyedScalar(scalars, SCALAR_URLBAR, "search_suggestion", 1);
     Assert.equal(Object.keys(scalars[SCALAR_URLBAR]).length, 1,
                 "This search must only increment one entry in the scalar.");
 
     // Make sure SEARCH_COUNTS contains identical values.
     let searchEngineId = "other-" + engine.name;
-    checkKeyedHistogram(search_hist, searchEngineId + ".urlbar", 1);
+    TelemetryTestUtils.assertKeyedHistogramSum(search_hist, searchEngineId + ".urlbar", 1);
 
     // Also check events.
     let events = Services.telemetry.snapshotEvents(Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, false);
     events = (events.parent || []).filter(e => e[1] == "navigation" && e[2] == "search");
-    checkEvents(events, [["navigation", "search", "urlbar", "suggestion", {engine: searchEngineId}]]);
+    TelemetryTestUtils.assertEvents(events, [["navigation", "search", "urlbar", "suggestion", {engine: searchEngineId}]]);
 
     // Check the histograms as well.
-    let resultIndexes = resultIndexHist.snapshot();
-    checkHistogramResults(resultIndexes, 3, "FX_URLBAR_SELECTED_RESULT_INDEX");
+    TelemetryTestUtils.assertHistogram(resultIndexHist, 3, 1);
 
-    let resultTypes = resultTypeHist.snapshot();
-    checkHistogramResults(resultTypes,
-      URLBAR_SELECTED_RESULT_TYPES.searchsuggestion,
-      "FX_URLBAR_SELECTED_RESULT_TYPE");
+    TelemetryTestUtils.assertHistogram(resultTypeHist,
+      URLBAR_SELECTED_RESULT_TYPES.searchsuggestion, 1);
 
-    let resultIndexByType = resultIndexByTypeHist.snapshot().searchsuggestion;
-    checkHistogramResults(resultIndexByType,
-      3,
-      "FX_URLBAR_SELECTED_RESULT_INDEX_BY_TYPE");
+    TelemetryTestUtils.assertKeyedHistogramValue(resultIndexByTypeHist,
+      "searchsuggestion", 3, 1);
 
-    let resultMethods = resultMethodHist.snapshot();
-    checkHistogramResults(resultMethods,
-      URLBAR_SELECTED_RESULT_METHODS.click,
-      "FX_URLBAR_SELECTED_RESULT_METHOD");
+    TelemetryTestUtils.assertHistogram(resultMethodHist,
+      URLBAR_SELECTED_RESULT_METHODS.click, 1);
 
     BrowserTestUtils.removeTab(tab);
   });
 });
 
 // Selects and presses the Return (Enter) key on the first suggestion offered by
 // the test search engine.  This only tests the FX_URLBAR_SELECTED_RESULT_METHOD
 // histogram since test_suggestion_click covers everything else.
 add_task(async function test_suggestion_arrowEnterSelection() {
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
 
   await withNewSearchEngine(async function() {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
     info("Type a query. Suggestions should be generated by the test engine.");
     let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
     await searchInAwesomebar("query");
     info("Select the second result and press Return.");
     EventUtils.synthesizeKey("KEY_ArrowDown");
     EventUtils.synthesizeKey("KEY_Enter");
     await p;
 
-    let resultMethods = resultMethodHist.snapshot();
-    checkHistogramResults(resultMethods,
-      URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection,
-      "FX_URLBAR_SELECTED_RESULT_METHOD");
+    TelemetryTestUtils.assertHistogram(resultMethodHist,
+      URLBAR_SELECTED_RESULT_METHODS.arrowEnterSelection, 1);
 
     BrowserTestUtils.removeTab(tab);
   });
 });
 
 // Selects through tab and presses the Return (Enter) key on the first
 // suggestion offered by the test search engine.
 add_task(async function test_suggestion_tabEnterSelection() {
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
 
   await withNewSearchEngine(async function() {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
     info("Type a query. Suggestions should be generated by the test engine.");
     let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
     await searchInAwesomebar("query");
     info("Select the second result and press Return.");
     EventUtils.synthesizeKey("KEY_Tab");
     EventUtils.synthesizeKey("KEY_Enter");
     await p;
 
-    let resultMethods = resultMethodHist.snapshot();
-    checkHistogramResults(resultMethods,
-      URLBAR_SELECTED_RESULT_METHODS.tabEnterSelection,
-      "FX_URLBAR_SELECTED_RESULT_METHOD");
+    TelemetryTestUtils.assertHistogram(resultMethodHist,
+      URLBAR_SELECTED_RESULT_METHODS.tabEnterSelection, 1);
 
     BrowserTestUtils.removeTab(tab);
   });
 });
 
 // Selects through code and presses the Return (Enter) key on the first
 // suggestion offered by the test search engine.
 add_task(async function test_suggestion_enterSelection() {
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
 
   await withNewSearchEngine(async function() {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
     info("Type a query. Suggestions should be generated by the test engine.");
     let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
     await searchInAwesomebar("query");
     info("Select the second result and press Return.");
     gURLBar.popup.selectedIndex = 1;
     EventUtils.synthesizeKey("KEY_Enter");
     await p;
 
-    let resultMethods = resultMethodHist.snapshot();
-    checkHistogramResults(resultMethods,
-      URLBAR_SELECTED_RESULT_METHODS.enterSelection,
-      "FX_URLBAR_SELECTED_RESULT_METHOD");
+    TelemetryTestUtils.assertHistogram(resultMethodHist,
+      URLBAR_SELECTED_RESULT_METHODS.enterSelection, 1);
 
     BrowserTestUtils.removeTab(tab);
   });
 });
 
 // Selects through mouse right button and press the Return (Enter) key.
 add_task(async function test_suggestion_rightclick() {
   Services.telemetry.clearScalars();
-  let resultMethodHist = getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
+  let resultMethodHist = TelemetryTestUtils.getAndClearHistogram("FX_URLBAR_SELECTED_RESULT_METHOD");
 
   await withNewSearchEngine(async function() {
     let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank");
 
     info("Type a query. Suggestions should be generated by the test engine.");
     let p = BrowserTestUtils.browserLoaded(tab.linkedBrowser);
     await searchInAwesomebar("query");
     info("Right click the the second result and then press Return.");
     await clickURLBarSuggestion("queryfoo", 2);
     EventUtils.synthesizeKey("KEY_Enter");
     await p;
 
-    let resultMethods = resultMethodHist.snapshot();
-    checkHistogramResults(resultMethods,
-      URLBAR_SELECTED_RESULT_METHODS.rightClickEnter,
-      "FX_URLBAR_SELECTED_RESULT_METHOD");
+    TelemetryTestUtils.assertHistogram(resultMethodHist,
+      URLBAR_SELECTED_RESULT_METHODS.rightClickEnter, 1);
 
     BrowserTestUtils.removeTab(tab);
   });
 });
 
 add_task(async function test_privateWindow() {
   // Mock the search telemetry search provider info so that its
   // recordSearchURLTelemetry() function adds the in-content SEARCH_COUNTS
   // telemetry for our test engine.
   SearchTelemetry.overrideSearchTelemetryForTests({
     "example": {
       "regexp": "^http://example\\.com/",
       "queryParam": "q",
     },
   });
 
-  let search_hist = getAndClearKeyedHistogram("SEARCH_COUNTS");
+  let search_hist = TelemetryTestUtils.getAndClearKeyedHistogram("SEARCH_COUNTS");
 
   // First, do a bunch of searches in a private window.
   let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
 
   info("Search in a private window and the pref does not exist");
   let p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 1);
 
   info("Search again in a private window after setting the pref to true");
   Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", true);
   p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("another query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should *not* be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 1);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 1);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 1);
 
   info("Search again in a private window after setting the pref to false");
   Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", false);
   p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("another query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 2);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 2);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 2);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 2);
 
   info("Search again in a private window after clearing the pref");
   Services.prefs.clearUserPref("browser.engagement.search_counts.pbm");
   p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("another query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 3);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 3);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 3);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 3);
 
   await BrowserTestUtils.closeWindow(win);
 
   // Now, do a bunch of searches in a non-private window.  Telemetry should
   // always be recorded regardless of the pref's value.
   win = await BrowserTestUtils.openNewBrowserWindow();
 
   info("Search in a non-private window and the pref does not exist");
   p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 4);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 4);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 4);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 4);
 
   info("Search again in a non-private window after setting the pref to true");
   Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", true);
   p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("another query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 5);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 5);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 5);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 5);
 
   info("Search again in a non-private window after setting the pref to false");
   Services.prefs.setBoolPref("browser.engagement.search_counts.pbm", false);
   p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("another query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 6);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 6);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 6);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 6);
 
   info("Search again in a non-private window after clearing the pref");
   Services.prefs.clearUserPref("browser.engagement.search_counts.pbm");
   p = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
   await searchInAwesomebar("another query", win);
   EventUtils.synthesizeKey("KEY_Enter", undefined, win);
   await p;
 
   // SEARCH_COUNTS should be incremented.
-  checkKeyedHistogram(search_hist, "other-MozSearch.urlbar", 7);
-  checkKeyedHistogram(search_hist, "example.in-content:organic:none", 7);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "other-MozSearch.urlbar", 7);
+  TelemetryTestUtils.assertKeyedHistogramSum(search_hist, "example.in-content:organic:none", 7);
 
   await BrowserTestUtils.closeWindow(win);
 
   // Reset the search provider info.
   SearchTelemetry.overrideSearchTelemetryForTests();
 });
--- a/browser/modules/test/browser/head.js
+++ b/browser/modules/test/browser/head.js
@@ -1,11 +1,13 @@
 
 ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
                                "resource://testing-common/PlacesTestUtils.jsm");
+ChromeUtils.defineModuleGetter(this, "TelemetryTestUtils",
+                               "resource://testing-common/TelemetryTestUtils.jsm");
 
 const SINGLE_TRY_TIMEOUT = 100;
 const NUMBER_OF_TRIES = 30;
 
 function waitForConditionPromise(condition, timeoutMsg, tryCount = NUMBER_OF_TRIES) {
   return new Promise((resolve, reject) => {
     let tries = 0;
     function checkCondition() {
@@ -31,59 +33,16 @@ function waitForConditionPromise(conditi
 
 function waitForCondition(condition, nextTest, errorMsg) {
   waitForConditionPromise(condition, errorMsg).then(nextTest, (reason) => {
     ok(false, reason + (reason.stack ? "\n" + reason.stack : ""));
   });
 }
 
 /**
- * Checks if the snapshotted keyed scalars contain the expected
- * data.
- *
- * @param {Object} scalars
- *        The snapshot of the keyed scalars.
- * @param {String} scalarName
- *        The name of the keyed scalar to check.
- * @param {String} key
- *        The key that must be within the keyed scalar.
- * @param {String|Boolean|Number} expectedValue
- *        The expected value for the provided key in the scalar.
- */
-function checkKeyedScalar(scalars, scalarName, key, expectedValue) {
-  Assert.ok(scalarName in scalars,
-            scalarName + " must be recorded.");
-  Assert.ok(key in scalars[scalarName],
-            scalarName + " must contain the '" + key + "' key.");
-  Assert.equal(scalars[scalarName][key], expectedValue,
-            scalarName + "['" + key + "'] must contain the expected value");
-}
-
-/**
- * An helper that checks the value of a scalar if it's expected to be > 0,
- * otherwise makes sure that the scalar it's not reported.
- *
- * @param {Object} scalars
- *        The snapshot of the scalars.
- * @param {String} scalarName
- *        The name of the scalar to check.
- * @param {Number} value
- *        The expected value for the provided scalar.
- * @param {String} msg
- *        The message to print when checking the value.
- */
-let checkScalar = (scalars, scalarName, value, msg) => {
-  if (value > 0) {
-    is(scalars[scalarName], value, msg);
-    return;
-  }
-  ok(!(scalarName in scalars), scalarName + " must not be reported.");
-};
-
-/**
  * An utility function to write some text in the search input box
  * in a content page.
  * @param {Object} browser
  *        The browser that contains the content.
  * @param {String} text
  *        The string to write in the search field.
  * @param {String} fieldName
  *        The name of the field to write to.
@@ -92,84 +51,16 @@ let typeInSearchField = async function(b
   await ContentTask.spawn(browser, [fieldName, text], async function([contentFieldName, contentText]) {
     // Put the focus on the search box.
     let searchInput = content.document.getElementById(contentFieldName);
     searchInput.focus();
     searchInput.value = contentText;
   });
 };
 
-
-/**
- * Clear and get the named histogram
- * @param {String} name
- *        The name of the histogram
- */
-function getAndClearHistogram(name) {
-  let histogram = Services.telemetry.getHistogramById(name);
-  histogram.clear();
-  return histogram;
-}
-
-
-/**
- * Clear and get the named keyed histogram
- * @param {String} name
- *        The name of the keyed histogram
- */
-function getAndClearKeyedHistogram(name) {
-  let histogram = Services.telemetry.getKeyedHistogramById(name);
-  histogram.clear();
-  return histogram;
-}
-
-
-/**
- * Check that the keyed histogram contains the right value.
- */
-function checkKeyedHistogram(h, key, expectedValue) {
-  const snapshot = h.snapshot();
-  if (expectedValue === undefined) {
-    Assert.ok(!(key in snapshot), `The histogram must not contain ${key}.`);
-    return;
-  }
-  Assert.ok(key in snapshot, `The histogram must contain ${key}.`);
-  Assert.equal(snapshot[key].sum, expectedValue, `The key ${key} must contain ${expectedValue}.`);
-}
-
-/**
- * Return the scalars from the parent-process.
- */
-function getParentProcessScalars(aChannel, aKeyed = false, aClear = false) {
-  const extended = aChannel == Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN;
-  const currentExtended = Services.telemetry.canRecordExtended;
-  Services.telemetry.canRecordExtended = extended;
-  const scalars = aKeyed ?
-    Services.telemetry.getSnapshotForKeyedScalars("main", aClear).parent :
-    Services.telemetry.getSnapshotForScalars("main", aClear).parent;
-  Services.telemetry.canRecordExtended = currentExtended;
-  return scalars || {};
-}
-
-function checkEvents(events, expectedEvents) {
-  if (!Services.telemetry.canRecordExtended) {
-    // Currently we only collect the tested events when extended Telemetry is enabled.
-    return;
-  }
-
-  Assert.equal(events.length, expectedEvents.length, "Should have matching amount of events.");
-
-  // Strip timestamps from the events for easier comparison.
-  events = events.map(e => e.slice(1));
-
-  for (let i = 0; i < events.length; ++i) {
-    Assert.deepEqual(events[i], expectedEvents[i], "Events should match.");
-  }
-}
-
 /**
  * Given a <xul:browser> at some non-internal web page,
  * return something that resembles an nsIContentPermissionRequest,
  * using the browsers currently loaded document to get a principal.
  *
  * @param browser (<xul:browser>)
  *        The browser that we'll create a nsIContentPermissionRequest
  *        for.
--- a/toolkit/components/telemetry/tests/moz.build
+++ b/toolkit/components/telemetry/tests/moz.build
@@ -9,16 +9,20 @@ DIST_INSTALL = False
 SOURCES += [
     'modules-test.cpp',
 ]
 
 SharedLibrary('modules-test')
 
 NO_PGO = True
 
+TESTING_JS_MODULES += [
+    'utils/TelemetryTestUtils.jsm',
+]
+
 if CONFIG['COMPILE_ENVIRONMENT']:
     shared_library = '!%smodules-test%s' % (CONFIG['DLL_PREFIX'], CONFIG['DLL_SUFFIX'])
     TEST_HARNESS_FILES.xpcshell.toolkit.components.telemetry.tests.unit += [shared_library]
 
 if CONFIG['ENABLE_TESTS'] and CONFIG['OS_ARCH'] == 'WINNT':
     DIRS += [
         'untrusted-startup-test-dll',
     ]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/telemetry/tests/utils/TelemetryTestUtils.jsm
@@ -0,0 +1,182 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const EXPORTED_SYMBOLS = ["TelemetryTestUtils"];
+
+ChromeUtils.import("resource://testing-common/Assert.jsm");
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+var TelemetryTestUtils = {
+  /* Scalars */
+
+  /**
+   * An helper that asserts the value of a scalar if it's expected to be > 0,
+   * otherwise makes sure that the scalar has not been reported.
+   *
+   * @param {Object} scalars The snapshot of the scalars.
+   * @param {String} scalarName The name of the scalar to check.
+   * @param {Number} value The expected value for the provided scalar.
+   * @param {String} msg The message to print when checking the value.
+   */
+  assertScalar(scalars, scalarName, value, msg) {
+    if (value > 0) {
+      Assert.equal(scalars[scalarName], value, msg);
+      return;
+    }
+    Assert.ok(!(scalarName in scalars), scalarName + " must not be reported.");
+  },
+
+  /**
+   * Asserts if the snapshotted keyed scalars contain the expected
+   * data.
+   *
+   * @param {Object} scalars The snapshot of the keyed scalars.
+   * @param {String} scalarName The name of the keyed scalar to check.
+   * @param {String} key The key that must be within the keyed scalar.
+   * @param {String|Boolean|Number} expectedValue The expected value for the
+   *        provided key in the scalar.
+   */
+  assertKeyedScalar(scalars, scalarName, key, expectedValue) {
+    Assert.ok(scalarName in scalars,
+              scalarName + " must be recorded.");
+    Assert.ok(key in scalars[scalarName],
+              scalarName + " must contain the '" + key + "' key.");
+    Assert.equal(scalars[scalarName][key], expectedValue,
+              scalarName + "['" + key + "'] must contain the expected value");
+  },
+
+  /**
+   * Returns a snapshot of scalars from the parent-process.
+   *
+   * @param {Number} aChannel The channel dataset type from nsITelemetry.
+   * @param {boolean} [aKeyed] Set to true if keyed scalars rather than normal
+   *   scalars should be snapshotted.
+   * @param {boolean} [aClear] Set to true to clear the scalars once the snapshot
+   *   has been obtained.
+   * @returns {Object} The snapshotted scalars from the parent process.
+   */
+  getParentProcessScalars(aChannel, aKeyed = false, aClear = false) {
+    const extended = aChannel == Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN;
+    const currentExtended = Services.telemetry.canRecordExtended;
+    Services.telemetry.canRecordExtended = extended;
+    const scalars = aKeyed ?
+      Services.telemetry.getSnapshotForKeyedScalars("main", aClear).parent :
+      Services.telemetry.getSnapshotForScalars("main", aClear).parent;
+    Services.telemetry.canRecordExtended = currentExtended;
+    return scalars || {};
+  },
+
+  /* Events */
+
+  /**
+   * Asserts if snapshotted events telemetry match the expected values.
+   *
+   * @param {Array} events Snapshotted telemetry events to test.
+   * @param {Array} expectedEvents The expected event data.
+   */
+  assertEvents(events, expectedEvents) {
+    if (!Services.telemetry.canRecordExtended) {
+      console.log("Not asserting event telemetry - canRecordExtended is disabled.");
+      return;
+    }
+
+    Assert.equal(events.length, expectedEvents.length, "Should have matching amount of events.");
+
+    // Strip timestamps from the events for easier comparison.
+    events = events.map(e => e.slice(1));
+
+    for (let i = 0; i < events.length; ++i) {
+      Assert.deepEqual(events[i], expectedEvents[i], "Events should match.");
+    }
+  },
+
+  /* Histograms */
+
+  /**
+   * Clear and get the named histogram.
+   *
+   * @param {String} name The name of the histogram
+   * @returns {Object} The obtained histogram.
+   */
+  getAndClearHistogram(name) {
+    let histogram = Services.telemetry.getHistogramById(name);
+    histogram.clear();
+    return histogram;
+  },
+
+
+  /**
+   * Clear and get the named keyed histogram.
+   *
+   * @param {String} name The name of the keyed histogram
+   * @returns {Object} The obtained keyed histogram.
+   */
+  getAndClearKeyedHistogram(name) {
+    let histogram = Services.telemetry.getKeyedHistogramById(name);
+    histogram.clear();
+    return histogram;
+  },
+
+  /**
+   * Assert that the histogram index is the right value. It expects that
+   * other indexes are all zero.
+   *
+   * @param {Object} histogram The histogram to check.
+   * @param {Number} index The index to check against the expected value.
+   * @param {Number} expected The expected value of the index.
+   */
+  assertHistogram(histogram, index, expected) {
+    const snapshot = histogram.snapshot();
+    for (let [i, val] of Object.entries(snapshot.values)) {
+      if (i == index) {
+        Assert.equal(val, expected,
+          `expected counts should match for the histogram index ${i}`);
+      } else {
+        Assert.equal(val, 0,
+          `unexpected counts should be zero for the histogram index ${i}`);
+      }
+    }
+  },
+
+  /**
+   * Assert that a key within a keyed histogram contains the required sum.
+   *
+   * @param {Object} histogram The keyed histogram to check.
+   * @param {String} key The key to check.
+   * @param {Number} [expected] The expected sum for the key.
+   */
+  assertKeyedHistogramSum(histogram, key, expected) {
+    const snapshot = histogram.snapshot();
+    if (expected === undefined) {
+      Assert.ok(!(key in snapshot), `The histogram must not contain ${key}.`);
+      return;
+    }
+    Assert.ok(key in snapshot, `The histogram must contain ${key}.`);
+    Assert.equal(snapshot[key].sum, expected,
+      `The key ${key} must contain the expected sum.`);
+  },
+
+  /**
+   * Assert that the value of a key within a keyed histogram is the right value.
+   * It expects that other values are all zero.
+   *
+   * @param {Object} histogram The keyed histogram to check.
+   * @param {String} key The key to check.
+   * @param {Number} index The index to check against the expected value.
+   * @param {Number} [expected] The expected values for the key.
+   */
+  assertKeyedHistogramValue(histogram, key, index, expected) {
+    const snapshot = histogram.snapshot();
+    for (let [i, val] of Object.entries(snapshot[key].values)) {
+      if (i == index) {
+        Assert.equal(val, expected,
+          `expected counts should match for the histogram index ${i}`);
+      } else {
+        Assert.equal(val, 0,
+          `unexpected counts should be zero for the histogram index ${i}`);
+      }
+    }
+  },
+};