| Index: build/android/coverage_test.py
|
| diff --git a/build/android/coverage_test.py b/build/android/coverage_test.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..c9551b6291f2211941ff8f91e26d7d6614845c28
|
| --- /dev/null
|
| +++ b/build/android/coverage_test.py
|
| @@ -0,0 +1,558 @@
|
| +#!/usr/bin/python
|
| +# Copyright 2015 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +from lxml import etree
|
| +from lxml import html
|
| +import os
|
| +import sys
|
| +import unittest
|
| +
|
| +import coverage
|
| +from pylib import constants
|
| +
|
| +sys.path.append(os.path.join(
|
| + constants.DIR_SOURCE_ROOT, 'third_party', 'pymock'))
|
| +import mock # pylint: disable=F0401
|
| +
|
| +
|
| +class LineCoverageTest(unittest.TestCase):
|
| + """Tests for LineCoverage."""
|
| +
|
| + def testInit(self):
|
| + line_coverage = coverage.LineCoverage(10, 'i++;',
|
| + coverage.LineCoverage.COVERED, 1.0)
|
| + self.assertEqual(line_coverage.lineno, 10)
|
| + self.assertEqual(line_coverage.source, 'i++;')
|
| + self.assertEqual(line_coverage.covered_status,
|
| + coverage.LineCoverage.COVERED)
|
| + self.assertEqual(line_coverage.fractional_line_coverage, 1.0)
|
| +
|
| +
|
| +class _EmmaHtmlParserTest(unittest.TestCase):
|
| + """Tests for _EmmaHtmlParser.
|
| +
|
| + Uses modified EMMA report HTML that contains only the subset of tags needed
|
| + for test verification.
|
| + """
|
| +
|
| + def setUp(self):
|
| + self.emma_dir = 'fake/dir/'
|
| + self.parser = coverage._EmmaHtmlParser(self.emma_dir)
|
| + self.simple_html = '<td class="p">Test HTML</td>'
|
| + self.index_html = """
|
| + <HTML>
|
| + <BODY>
|
| + <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + <TABLE CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + <TABLE CLASS="it" CELLSPACING="0">
|
| + </TABLE>
|
| + <TABLE CELLSPACING="0" WIDTH="100%">
|
| + <TR>
|
| + <TH CLASS="f">name</TH>
|
| + <TH>class, %</TH>
|
| + <TH>method, %</TH>
|
| + <TH>block, %</TH>
|
| + <TH>line, %</TH>
|
| + </TR>
|
| + <TR CLASS="o">
|
| + <TD><A HREF="_files/0.html"
|
| + >org.chromium.chrome.browser</A></TD>
|
| + <TD CLASS="h">0% (0/3)</TD>
|
| + </TR>
|
| + <TR>
|
| + <TD><A HREF="_files/1.html"
|
| + >org.chromium.chrome.browser.tabmodel</A></TD>
|
| + <TD CLASS="h">0% (0/8)</TD>
|
| + </TR>
|
| + </TABLE>
|
| + <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + </BODY>
|
| + </HTML>"""
|
| + self.package_1_class_list_html = """
|
| + <HTML>
|
| + <BODY>
|
| + <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + <TABLE CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + <TABLE CELLSPACING="0" WIDTH="100%">
|
| + <TR>
|
| + <TH CLASS="f">name</TH>
|
| + <TH>class, %</TH>
|
| + <TH>method, %</TH>
|
| + <TH>block, %</TH>
|
| + <TH>line, %</TH>
|
| + </TR>
|
| + <TR CLASS="o">
|
| + <TD><A HREF="1e.html">IntentHelper.java</A></TD>
|
| + <TD CLASS="h">0% (0/3)</TD>
|
| + <TD CLASS="h">0% (0/9)</TD>
|
| + <TD CLASS="h">0% (0/97)</TD>
|
| + <TD CLASS="h">0% (0/26)</TD>
|
| + </TR>
|
| + </TABLE>
|
| + <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + </BODY>
|
| + </HTML>"""
|
| + self.package_2_class_list_html = """
|
| + <HTML>
|
| + <BODY>
|
| + <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + <TABLE CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + <TABLE CELLSPACING="0" WIDTH="100%">
|
| + <TR>
|
| + <TH CLASS="f">name</TH>
|
| + <TH>class, %</TH>
|
| + <TH>method, %</TH>
|
| + <TH>block, %</TH>
|
| + <TH>line, %</TH>
|
| + </TR>
|
| + <TR CLASS="o">
|
| + <TD><A HREF="1f.html">ContentSetting.java</A></TD>
|
| + <TD CLASS="h">0% (0/1)</TD>
|
| + </TR>
|
| + <TR>
|
| + <TD><A HREF="20.html">DevToolsServer.java</A></TD>
|
| + </TR>
|
| + <TR CLASS="o">
|
| + <TD><A HREF="21.html">FileProviderHelper.java</A></TD>
|
| + </TR>
|
| + <TR>
|
| + <TD><A HREF="22.html">ContextualMenuBar.java</A></TD>
|
| + </TR>
|
| + <TR CLASS="o">
|
| + <TD><A HREF="23.html">AccessibilityUtil.java</A></TD>
|
| + </TR>
|
| + <TR>
|
| + <TD><A HREF="24.html">NavigationPopup.java</A></TD>
|
| + </TR>
|
| + </TABLE>
|
| + <TABLE CLASS="hdft" CELLSPACING="0" WIDTH="100%">
|
| + </TABLE>
|
| + </BODY>
|
| + </HTML>"""
|
| + self.partially_covered_tr_html = """
|
| + <tr class="p">
|
| + <td class="l" title="78% line coverage (7 out of 9)">108</td>
|
| + <td title="78% line coverage (7 out of 9 instructions)">
|
| + if (index < 0 || index = mSelectors.size()) index = 0;</td>
|
| + </tr>"""
|
| + self.covered_tr_html = """
|
| + <tr class="c">
|
| + <td class="l">110</td>
|
| + <td> if (mSelectors.get(index) != null) {</td>
|
| + </tr>"""
|
| + self.not_executable_tr_html = """
|
| + <tr>
|
| + <td class="l">109</td>
|
| + <td> </td>
|
| + </tr>"""
|
| + self.tr_with_extra_a_tag = """
|
| + <tr class="z">
|
| + <td class="l">
|
| + <a name="1f">54</a>
|
| + </td>
|
| + <td> }</td>
|
| + </tr>"""
|
| +
|
| + def testInit(self):
|
| + emma_dir = self.emma_dir
|
| + parser = coverage._EmmaHtmlParser(emma_dir)
|
| + self.assertEqual(parser._base_dir, emma_dir)
|
| + self.assertEqual(parser._emma_files_path, 'fake/dir/_files')
|
| + self.assertEqual(parser._index_path, 'fake/dir/index.html')
|
| +
|
| + def testFindElements_basic(self):
|
| + found, _ = MockOpenForFunction(self.parser._FindElements, self.simple_html,
|
| + file_path='fake', _path='//td')
|
| + self.assertIs(type(found), list)
|
| + self.assertIs(type(found[0]), html.HtmlElement)
|
| + self.assertEqual(found[0].text, 'Test HTML')
|
| +
|
| + def testFindElements_noMatch(self):
|
| + found, _ = MockOpenForFunction(self.parser._FindElements, self.simple_html,
|
| + file_path='fake', _path='//tr')
|
| + self.assertEqual(found, [])
|
| +
|
| + def testFindElements_badFilePath(self):
|
| + # Ensure that os.path.exists will fail.
|
| + with mock.patch('os.path.exists', return_value=False):
|
| + found = self.parser._FindElements('fake', _path='//tr')
|
| + self.assertEqual(found, [])
|
| +
|
| + def testGetPackageNameToEmmaFileDict_basic(self):
|
| + expected_dict = {
|
| + 'org.chromium.chrome.browser.AccessibilityUtil.java':
|
| + 'fake/dir/_files/23.html',
|
| + 'org.chromium.chrome.browser.ContextualMenuBar.java':
|
| + 'fake/dir/_files/22.html',
|
| + 'org.chromium.chrome.browser.tabmodel.IntentHelper.java':
|
| + 'fake/dir/_files/1e.html',
|
| + 'org.chromium.chrome.browser.ContentSetting.java':
|
| + 'fake/dir/_files/1f.html',
|
| + 'org.chromium.chrome.browser.DevToolsServer.java':
|
| + 'fake/dir/_files/20.html',
|
| + 'org.chromium.chrome.browser.NavigationPopup.java':
|
| + 'fake/dir/_files/24.html',
|
| + 'org.chromium.chrome.browser.FileProviderHelper.java':
|
| + 'fake/dir/_files/21.html'}
|
| +
|
| + return_dict, mock_open = MockOpenForFunction(
|
| + self.parser.GetPackageNameToEmmaFileDict,
|
| + self.index_html, self.package_1_class_list_html,
|
| + self.package_2_class_list_html)
|
| +
|
| + self.assertDictEqual(return_dict, expected_dict)
|
| + self.assertEqual(mock_open.call_count, 3)
|
| + calls = [mock.call('fake/dir/index.html'),
|
| + mock.call('fake/dir/_files/1.html'),
|
| + mock.call('fake/dir/_files/0.html')]
|
| + mock_open.assert_has_calls(calls)
|
| +
|
| + def testGetPackageNameToEmmaFileDict_badFilePath(self):
|
| + file_path = self.parser.GetPackageNameToEmmaFileDict()
|
| + self.assertEqual(file_path, {})
|
| +
|
| + def testGetLineCoverage_status_basic(self):
|
| + line_coverage = self.GetLineCoverageWithFakeElements(self.covered_tr_html)
|
| + self.assertEqual(line_coverage[0].covered_status,
|
| + coverage.LineCoverage.COVERED)
|
| +
|
| + def testGetLineCoverage_status_statusMissing(self):
|
| + line_coverage = self.GetLineCoverageWithFakeElements(
|
| + self.not_executable_tr_html)
|
| + self.assertEqual(line_coverage[0].covered_status,
|
| + coverage.LineCoverage.NOT_EXECUTABLE)
|
| +
|
| + def testGetLineCoverage_fractionalCoverage_basic(self):
|
| + line_coverage = self.GetLineCoverageWithFakeElements(self.covered_tr_html)
|
| + self.assertEqual(line_coverage[0].fractional_line_coverage, 1.0)
|
| +
|
| + def testGetLineCoverage_fractionalCoverage_partial(self):
|
| + line_coverage = self.GetLineCoverageWithFakeElements(
|
| + self.partially_covered_tr_html)
|
| + self.assertEqual(line_coverage[0].fractional_line_coverage, 0.78)
|
| +
|
| + def testGetLineCoverage_lineno_basic(self):
|
| + line_coverage = self.GetLineCoverageWithFakeElements(self.covered_tr_html)
|
| + self.assertEqual(line_coverage[0].lineno, 110)
|
| +
|
| + def testGetLineCoverage_lineno_withAlternativeHtml(self):
|
| + line_coverage = self.GetLineCoverageWithFakeElements(
|
| + self.tr_with_extra_a_tag)
|
| + self.assertEqual(line_coverage[0].lineno, 54)
|
| +
|
| + def testGetLineCoverage_source(self):
|
| + self.parser._FindElements = mock.Mock(
|
| + return_value=[html.fromstring(self.covered_tr_html)])
|
| + line_coverage = self.parser.GetLineCoverage('fake_path')
|
| + self.assertEqual(line_coverage[0].source,
|
| + ' if (mSelectors.get(index) != null) {')
|
| +
|
| + def testGetLineCoverage_multipleElements(self):
|
| + line_coverage = self.GetLineCoverageWithFakeElements(
|
| + self.covered_tr_html, self.partially_covered_tr_html,
|
| + self.tr_with_extra_a_tag)
|
| + self.assertEqual(len(line_coverage), 3)
|
| +
|
| + def GetLineCoverageWithFakeElements(self, *args):
|
| + """Wraps GetLineCoverage to work with extra whitespace characters.
|
| +
|
| + The test HTML strings include extra whitespace characters to make the HTML
|
| + human readable. This isn't the case with EMMA HTML files, so we need to
|
| + remove all the unnecessary whitespace.
|
| +
|
| + Args:
|
| + *args: Each is a string representing an HTML element.
|
| +
|
| + Returns:
|
| + A list of LineCoverage objects.
|
| + """
|
| + html_elements = [self.MakeElementsWithoutWhitespace(arg) for arg in args]
|
| + with mock.patch('coverage._EmmaHtmlParser._FindElements',
|
| + return_value=html_elements):
|
| + return self.parser.GetLineCoverage('fake_path')
|
| +
|
| + def MakeElementsWithoutWhitespace(self, html_string):
|
| + """Helper to make HtmlElements with excess whitespace removed.
|
| +
|
| + Args:
|
| + html_string: String representing HTML to be used to create elements.
|
| +
|
| + Returns:
|
| + The root element of |html_string| with all extra whitespace removed.
|
| + """
|
| + parser = etree.HTMLParser(remove_blank_text=True)
|
| + root = html.fromstring(html_string, parser=parser)
|
| + for elem in root.iter('*'):
|
| + if elem.text is not None:
|
| + elem.text = elem.text.strip()
|
| + return root
|
| +
|
| +
|
| +class _EmmaCoverageStatsTest(unittest.TestCase):
|
| + """Tests for _EmmaCoverageStats."""
|
| +
|
| + def setUp(self):
|
| + self.good_source_to_emma = {
|
| + '/path/to/1/File1.java': '/emma/1.html',
|
| + '/path/2/File2.java': '/emma/2.html',
|
| + '/path/2/File3.java': '/emma/3.html'
|
| + }
|
| + self.line_coverage = [
|
| + coverage.LineCoverage(1, '', coverage.LineCoverage.COVERED, 1.0),
|
| + coverage.LineCoverage(2, '', coverage.LineCoverage.COVERED, 1.0),
|
| + coverage.LineCoverage(3, '', coverage.LineCoverage.NOT_EXECUTABLE, 1.0),
|
| + coverage.LineCoverage(4, '', coverage.LineCoverage.NOT_COVERED, 1.0),
|
| + coverage.LineCoverage(5, '',
|
| + coverage.LineCoverage.PARTIALLY_COVERED, 0.85),
|
| + coverage.LineCoverage(6, '',
|
| + coverage.LineCoverage.PARTIALLY_COVERED, 0.20)
|
| + ]
|
| + self.lines_for_coverage = [1, 3, 5, 6]
|
| + self.simple_coverage = coverage._EmmaCoverageStats('fake_dir', {})
|
| +
|
| + def testInit(self):
|
| + coverage_stats = self.simple_coverage
|
| + self.assertIsInstance(coverage_stats._emma_parser,
|
| + coverage._EmmaHtmlParser)
|
| + self.assertIsInstance(coverage_stats._source_to_emma, dict)
|
| +
|
| + def testNeedsCoverage_withExistingJavaFile(self):
|
| + test_file = '/path/to/file/File.java'
|
| + with mock.patch('os.path.exists', return_value=True):
|
| + self.assertTrue(coverage._EmmaCoverageStats.NeedsCoverage(test_file))
|
| +
|
| + def testNeedsCoverage_withNonJavaFile(self):
|
| + test_file = '/path/to/file/File.c'
|
| + with mock.patch('os.path.exists', return_value=True):
|
| + self.assertFalse(coverage._EmmaCoverageStats.NeedsCoverage(test_file))
|
| +
|
| + def testNeedsCoverage_fileDoesNotExist(self):
|
| + test_file = '/path/to/file/File.java'
|
| + with mock.patch('os.path.exists', return_value=False):
|
| + self.assertFalse(coverage._EmmaCoverageStats.NeedsCoverage(test_file))
|
| +
|
| + def testGetPackageNameFromFile_basic(self):
|
| + test_file_text = """// Test Copyright
|
| + package org.chromium.chrome.browser;
|
| + import android.graphics.RectF;"""
|
| + result_package, _ = MockOpenForFunction(
|
| + coverage._EmmaCoverageStats.GetPackageNameFromFile, test_file_text,
|
| + file_path='/path/to/file/File.java')
|
| + self.assertEqual(result_package, 'org.chromium.chrome.browser.File.java')
|
| +
|
| + def testGetPackageNameFromFile_noPackageStatement(self):
|
| + result_package, _ = MockOpenForFunction(
|
| + coverage._EmmaCoverageStats.GetPackageNameFromFile,
|
| + 'not a package statement', file_path='/path/to/file/File.java')
|
| + self.assertEqual(result_package, None)
|
| +
|
| + def testGetStatsForLines_basic(self):
|
| + covered, total = self.simple_coverage._GetStatsForLines(
|
| + self.line_coverage, self.lines_for_coverage)
|
| + self.assertEqual(covered, 2.05)
|
| + self.assertEqual(total, 3)
|
| +
|
| + def testGetStatsForLines_noLineNumbersProvided(self):
|
| + covered, total = self.simple_coverage._GetStatsForLines(self.line_coverage)
|
| + self.assertEqual(covered, 3.05)
|
| + self.assertEqual(total, 5)
|
| +
|
| + def testGetSourceFileToEmmaFileDict(self):
|
| + package_names = {
|
| + '/path/to/1/File1.java': 'org.fake.one.File1.java',
|
| + '/path/2/File2.java': 'org.fake.File2.java',
|
| + '/path/2/File3.java': 'org.fake.File3.java'
|
| + }
|
| + package_to_emma = {
|
| + 'org.fake.one.File1.java': '/emma/1.html',
|
| + 'org.fake.File2.java': '/emma/2.html',
|
| + 'org.fake.File3.java': '/emma/3.html'
|
| + }
|
| + with mock.patch('os.path.exists', return_value=True):
|
| + coverage_stats = self.simple_coverage
|
| + coverage_stats._emma_parser.GetPackageNameToEmmaFileDict = mock.MagicMock(
|
| + return_value=package_to_emma)
|
| + coverage_stats.GetPackageNameFromFile = lambda x: package_names[x]
|
| + result_dict = coverage_stats._GetSourceFileToEmmaFileDict(
|
| + package_names.keys())
|
| + self.assertDictEqual(result_dict, self.good_source_to_emma)
|
| +
|
| + def testGetCoverageStatusFromFile_basic(self):
|
| + java_file_path = '/path/to/1/File1.java'
|
| + line_coverage = [
|
| + coverage.LineCoverage(1, '', coverage.LineCoverage.COVERED, 1.0)]
|
| + coverage_stats = self.simple_coverage
|
| + coverage_stats._source_to_emma = self.good_source_to_emma
|
| + coverage_stats._emma_parser.GetLineCoverage = mock.MagicMock(
|
| + return_value=line_coverage)
|
| + coverage_info = coverage_stats._GetCoverageStatusForFile(java_file_path)
|
| + self.assertDictEqual(coverage_info[0].__dict__, line_coverage[0].__dict__)
|
| +
|
| + def testGetCoverageStatusFromFile_noInfo(self):
|
| + coverage_info = self.simple_coverage._GetCoverageStatusForFile('fake_path')
|
| + self.assertIsNone(coverage_info)
|
| +
|
| + def testGetCoverageReportForLines(self):
|
| + line_coverage = self.line_coverage
|
| + lines = self.lines_for_coverage
|
| + expected_dict = {
|
| + 'absolute': {
|
| + 'covered': 3.05,
|
| + 'total': 5
|
| + },
|
| + 'incremental': {
|
| + 'covered': 2.05,
|
| + 'total': 3
|
| + },
|
| + 'source': [
|
| + {
|
| + 'line': line_coverage[0].source,
|
| + 'coverage': line_coverage[0].covered_status,
|
| + 'changed': True
|
| + },
|
| + {
|
| + 'line': line_coverage[1].source,
|
| + 'coverage': line_coverage[1].covered_status,
|
| + 'changed': False
|
| + },
|
| + {
|
| + 'line': line_coverage[2].source,
|
| + 'coverage': line_coverage[2].covered_status,
|
| + 'changed': True
|
| + },
|
| + {
|
| + 'line': line_coverage[3].source,
|
| + 'coverage': line_coverage[3].covered_status,
|
| + 'changed': False
|
| + },
|
| + {
|
| + 'line': line_coverage[4].source,
|
| + 'coverage': line_coverage[4].covered_status,
|
| + 'changed': True
|
| + },
|
| + {
|
| + 'line': line_coverage[5].source,
|
| + 'coverage': line_coverage[5].covered_status,
|
| + 'changed': True
|
| + }
|
| + ]
|
| + }
|
| + result_dict = self.simple_coverage.GetCoverageReportForLines(line_coverage,
|
| + lines)
|
| + self.assertDictEqual(result_dict, expected_dict)
|
| +
|
| + def testGetCoverageReportForLines_emptyCoverage(self):
|
| + expected_dict = {
|
| + 'absolute': {'covered': 0, 'total': 0},
|
| + 'incremental': {'covered': 0, 'total': 0},
|
| + 'source': []
|
| + }
|
| + result_dict = self.simple_coverage.GetCoverageReportForLines({}, [])
|
| + self.assertDictEqual(result_dict, expected_dict)
|
| +
|
| + def testGetCoverageDictForFiles_basic(self):
|
| + files_for_coverage = {
|
| + '/path/to/1/File1.java': [1, 3, 4],
|
| + '/path/2/File2.java': [1, 2]
|
| + }
|
| + coverage_info = {
|
| + '/path/to/1/File1.java': [
|
| + coverage.LineCoverage(1, '', coverage.LineCoverage.COVERED, 1.0),
|
| + coverage.LineCoverage(2, '',
|
| + coverage.LineCoverage.PARTIALLY_COVERED, 0.5),
|
| + coverage.LineCoverage(3, '',
|
| + coverage.LineCoverage.NOT_EXECUTABLE, 1.0),
|
| + coverage.LineCoverage(4, '', coverage.LineCoverage.COVERED, 1.0)
|
| + ],
|
| + '/path/2/File2.java': [
|
| + coverage.LineCoverage(1, '', coverage.LineCoverage.NOT_COVERED, 1.0),
|
| + coverage.LineCoverage(2, '', coverage.LineCoverage.COVERED, 1.0)
|
| + ]
|
| + }
|
| + expected_dict = {
|
| + 'files': {
|
| + '/path/2/File2.java': {
|
| + 'absolute': {'covered': 1, 'total': 2},
|
| + 'incremental': {'covered': 1, 'total': 2},
|
| + 'source': [{'changed': True, 'coverage': 0, 'line': ''},
|
| + {'changed': True, 'coverage': 1, 'line': ''}]
|
| + },
|
| + '/path/to/1/File1.java': {
|
| + 'absolute': {'covered': 2.5, 'total': 3},
|
| + 'incremental': {'covered': 2, 'total': 2},
|
| + 'source': [{'changed': True, 'coverage': 1, 'line': ''},
|
| + {'changed': False, 'coverage': 2, 'line': ''},
|
| + {'changed': True, 'coverage': -1, 'line': ''},
|
| + {'changed': True, 'coverage': 1, 'line': ''}]
|
| + }
|
| + },
|
| + 'patch': {'incremental': {'covered': 3, 'total': 4}}
|
| + }
|
| + self.simple_coverage._GetCoverageStatusForFile = lambda x: coverage_info[x]
|
| + result_dict = self.simple_coverage.GetCoverageDictForFiles(
|
| + files_for_coverage)
|
| + self.assertDictEqual(result_dict, expected_dict)
|
| +
|
| + def testGetCoverageDictForFiles_noCoverage(self):
|
| + expected_dict = {
|
| + 'files': {},
|
| + 'patch': {
|
| + 'incremental': {
|
| + 'covered': 0, 'total': 0
|
| + }
|
| + }
|
| + }
|
| + result_dict = self.simple_coverage.GetCoverageDictForFiles({})
|
| + self.assertDictEqual(result_dict, expected_dict)
|
| +
|
| +
|
| +class CoverageGenerateCoverageReportTest(unittest.TestCase):
|
| + """Tests for GenerateCoverageReport."""
|
| +
|
| + def testGenerateCoverageReport_missingLineCoverageFile(self):
|
| + with self.assertRaises(IOError):
|
| + with mock.patch('os.path.exists', return_value=False):
|
| + coverage.GenerateCoverageReport('', '', '')
|
| +
|
| + def testGenerateCoverageReport_noCoverageRequired(self):
|
| + with self.assertRaises(SystemExit) as cm:
|
| + with mock.patch('os.path.exists', return_value=True):
|
| + MockOpenForFunction(coverage.GenerateCoverageReport, '{}',
|
| + line_coverage_file='', out_file_path='',
|
| + coverage_dir='')
|
| + self.assertEqual(cm.exception.code, 0)
|
| +
|
| +
|
| +def MockOpenForFunction(func, *args, **kwargs):
|
| + """Allows easy mock open and read for callables that open multiple files.
|
| +
|
| + Args:
|
| + func: The callable to invoke once mock files are setup.
|
| + *args: A list of return values for each file to return once read. Length of
|
| + list should be equal to the number calls to open in |func|.
|
| + **kwargs: Keyword arguments to be passed to |func|.
|
| +
|
| + Returns:
|
| + A tuple containing the return value of |func| and the MagicMock object used
|
| + to mock all calls to open respectively.
|
| + """
|
| + mock_open = mock.mock_open()
|
| + mock_open.side_effect = [mock.mock_open(read_data=arg).return_value
|
| + for arg in args]
|
| + with mock.patch('__builtin__.open', mock_open):
|
| + return func(**kwargs), mock_open
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + # Suppress logging messages.
|
| + unittest.main(buffer=True)
|
|
|