blob: 0d24e897ec135c480fec2f120197dfc0ac5a1aa1 [file] [log] [blame]
# Copyright 2019 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.
"""Unittests for xcode_log_parser.py."""
import json
import mock
import os
import unittest
import test_runner
import test_runner_test
import xcode_log_parser
_XTEST_RESULT = '/tmp/temp_file.xcresult'
XCODE11_DICT = {
'path': '/Users/user1/Xcode.app',
'version': '11.0',
'build': '11M336w',
}
REF_ID = """
{
"actions": {
"_values": [{
"actionResult": {
"testsRef": {
"id": {
"_value": "REF_ID"
}
}
}
}]
}
}"""
ACTIONS_RECORD_FAILED_TEST = """
{
"issues": {
"testFailureSummaries": {
"_values": [{
"documentLocationInCreatingWorkspace": {
"url": {
"_value": "file://<unknown>#CharacterRangeLen=0"
}
},
"message": {
"_value": "Fail. Screenshots: {\\n\\"Failure\\": \\"path.png\\"\\n}"
},
"testCaseName": {
"_value": "-[WebUITestCase testBackForwardFromWebURL]"
}
}]
}
}
}"""
PASSED_TESTS = """
{
"summaries": {
"_values": [{
"testableSummaries": {
"_type": {
"_name": "Array"
},
"_values": [{
"tests": {
"_type": {
"_name": "Array"
},
"_values": [{
"subtests": {
"_values": [{
"subtests": {
"_values": [{
"subtests": {
"_values": [{
"testStatus": {
"_value": "Success"
},
"identifier": {
"_value": "TestCase1/testMethod1"
},
"name": {
"_value": "testMethod1"
}
},
{
"testStatus": {
"_value": "Failure"
},
"identifier": {
"_value": "TestCase1/testFailed1"
},
"name": {
"_value": "testFailed1"
}
},
{
"testStatus": {
"_value": "Success"
},
"identifier": {
"_value": "TestCase2/testMethod1"
},
"name": {
"_value": "testMethod1"
}
}]
}
}]
}
}]
}
}]
}
}]
}
}]
}
}
"""
class XCode11LogParserTest(test_runner_test.TestCase):
"""Test case to test Xcode11LogParser."""
def setUp(self):
super(XCode11LogParserTest, self).setUp()
self.mock(test_runner, 'get_current_xcode_info', lambda: XCODE11_DICT)
@mock.patch('subprocess.check_output', autospec=True)
def testXcresulttoolGetRoot(self, mock_process):
mock_process.return_value = '%JSON%'
xcode_log_parser.Xcode11LogParser()._xcresulttool_get('xcresult_path')
self.assertTrue(
os.path.join(XCODE11_DICT['path'], 'usr', 'bin') in os.environ['PATH'])
self.assertEqual(
['xcresulttool', 'get', '--format', 'json', '--path', 'xcresult_path'],
mock_process.mock_calls[0][1][0])
@mock.patch('subprocess.check_output', autospec=True)
def testXcresulttoolGetRef(self, mock_process):
mock_process.side_effect = [REF_ID, 'JSON']
xcode_log_parser.Xcode11LogParser()._xcresulttool_get('xcresult_path',
'testsRef')
self.assertEqual(
['xcresulttool', 'get', '--format', 'json', '--path', 'xcresult_path'],
mock_process.mock_calls[0][1][0])
self.assertEqual([
'xcresulttool', 'get', '--format', 'json', '--path', 'xcresult_path',
'--id', 'REF_ID'], mock_process.mock_calls[1][1][0])
def testXcresulttoolListFailedTests(self):
failure_message = [
'file://<unknown>#CharacterRangeLen=0'
] + 'Fail. Screenshots: {\n\"Failure\": \"path.png\"\n}'.splitlines()
expected = {
'WebUITestCase/testBackForwardFromWebURL': failure_message
}
self.assertEqual(expected,
xcode_log_parser.Xcode11LogParser()._list_of_failed_tests(
json.loads(ACTIONS_RECORD_FAILED_TEST)))
@mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
def testXcresulttoolListPassedTests(self, mock_xcresult):
mock_xcresult.return_value = PASSED_TESTS
expected = ['TestCase1/testMethod1', 'TestCase2/testMethod1']
self.assertEqual(
expected,
xcode_log_parser.Xcode11LogParser()._get_test_statuses(_XTEST_RESULT))
@mock.patch('os.path.exists', autospec=True)
@mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
@mock.patch('xcode_log_parser.Xcode11LogParser._list_of_failed_tests')
@mock.patch('xcode_log_parser.Xcode11LogParser._list_of_passed_tests')
def testCollectTestTesults(self, mock_get_passed_tests, mock_get_failed_tests,
mock_root, mock_exist_file):
metrics_json = """
{
"metrics": {
"testsCount": {
"_value": "7"
},
"testsFailedCount": {
"_value": "14"
}
}
}"""
expected_test_results = {
'passed': [
'TestCase1/testMethod1', 'TestCase2/testMethod1'],
'failed': {
'WebUITestCase/testBackForwardFromWebURL': [
'file://<unknown>#CharacterRangeLen=0',
'Test crashed in <external symbol>'
]
}
}
mock_get_passed_tests.return_value = expected_test_results['passed']
mock_get_failed_tests.return_value = expected_test_results['failed']
mock_root.return_value = metrics_json
mock_exist_file.return_value = True
self.assertEqual(expected_test_results,
xcode_log_parser.Xcode11LogParser().collect_test_results(
_XTEST_RESULT, []))
@mock.patch('os.path.exists', autospec=True)
@mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
def testCollectTestsRanZeroTests(self, mock_root, mock_exist_file):
metrics_json = '{"metrics": {}}'
expected_test_results = {
'passed': [],
'failed': {'TESTS_DID_NOT_START': ['0 tests executed!']}}
mock_root.return_value = metrics_json
mock_exist_file.return_value = True
self.assertEqual(expected_test_results,
xcode_log_parser.Xcode11LogParser().collect_test_results(
_XTEST_RESULT, []))
@mock.patch('os.path.exists', autospec=True)
def testCollectTestsDidNotRun(self, mock_exist_file):
mock_exist_file.return_value = False
expected_test_results = {
'passed': [],
'failed': {'TESTS_DID_NOT_START': [
'%s with test results does not exist.' % _XTEST_RESULT]}}
self.assertEqual(expected_test_results,
xcode_log_parser.Xcode11LogParser().collect_test_results(
_XTEST_RESULT, []))
@mock.patch('os.path.exists', autospec=True)
def testCollectTestsInterruptedRun(self, mock_exist_file):
mock_exist_file.side_effect = [True, False]
expected_test_results = {
'passed': [],
'failed': {'BUILD_INTERRUPTED': [
'%s with test results does not exist.' % os.path.join(
_XTEST_RESULT + '.xcresult', 'Info.plist')]}}
self.assertEqual(expected_test_results,
xcode_log_parser.Xcode11LogParser().collect_test_results(
_XTEST_RESULT, []))
@mock.patch('os.path.exists', autospec=True)
@mock.patch('xcode_log_parser.Xcode11LogParser._xcresulttool_get')
@mock.patch('shutil.copyfile', autospec=True)
def testCopyScreenshots(self, mock_copy, mock_xcresulttool_get,
mock_exist_file):
mock_exist_file.return_value = True
mock_xcresulttool_get.return_value = ACTIONS_RECORD_FAILED_TEST
xcode_log_parser.Xcode11LogParser().copy_screenshots(_XTEST_RESULT)
self.assertEqual(1, mock_copy.call_count)
@mock.patch('os.path.exists', autospec=True)
def testCollectTestResults_interruptedTests(self, mock_path_exists):
mock_path_exists.side_effect = [True, False]
output = [
'[09:03:42:INFO] Test case \'-[TestCase1 method1]\' passed on device.',
'[09:06:40:INFO] Test Case \'-[TestCase2 method1]\' passed on device.',
'[09:09:00:INFO] Test case \'-[TestCase2 method1]\' failed on device.',
'** BUILD INTERRUPTED **',
]
not_found_message = [
'Info.plist.xcresult/Info.plist with test results does not exist.']
res = xcode_log_parser.Xcode11LogParser().collect_test_results(
'Info.plist', output)
self.assertIn('BUILD_INTERRUPTED', res['failed'])
self.assertEqual(not_found_message + output,
res['failed']['BUILD_INTERRUPTED'])
self.assertEqual(['TestCase1/method1', 'TestCase2/method1'],
res['passed'])
if __name__ == '__main__':
unittest.main()