Add missing unit tests for report file 71/65271/4
authorStamatis Katsaounis <mokats@intracom-telecom.com>
Tue, 20 Nov 2018 12:49:35 +0000 (14:49 +0200)
committerStamatis Katsaounis <mokats@intracom-telecom.com>
Tue, 20 Nov 2018 13:34:07 +0000 (15:34 +0200)
JIRA: DOVETAIL-724

This patch adds unit tests for report file methods of Dovetail which were
missing.

Change-Id: I2ba7c8f9fcfb962988b2904b01538e9f89a0d849
Signed-off-by: Stamatis Katsaounis <mokats@intracom-telecom.com>
dovetail/report.py
dovetail/tests/unit/test_report.py [new file with mode: 0644]

index 18eeca2..5f925c2 100644 (file)
@@ -11,6 +11,7 @@
 
 from __future__ import division
 
+import collections
 import json
 import re
 import os
@@ -48,13 +49,13 @@ class Report(object):
         result_file = os.path.join(result_path, check_results_file)
         if os.path.isfile(result_file):
             self.logger.info(
-                "Results have been stored with file {}.".format(result_file))
+                'Results have been stored with file {}.'.format(result_file))
             result = self.get_result(testcase, result_file)
             self.check_result(testcase, result)
             return result
         else:
             self.logger.error(
-                "Failed to store results with file {}.".format(result_file))
+                'Failed to store results with file {}.'.format(result_file))
             self.check_result(testcase)
             return None
 
@@ -72,7 +73,7 @@ class Report(object):
         report_obj['version'] = '2018.09'
         report_obj['build_tag'] = dt_cfg.dovetail_config['build_tag']
         report_obj['test_date'] =\
-            datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S UTC")
+            datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S UTC')
         report_obj['duration'] = duration
 
         report_obj['testcases_list'] = []
@@ -117,7 +118,7 @@ class Report(object):
 
         total_num = 0
         pass_num = 0
-        sub_report = {}
+        sub_report = collections.OrderedDict()
         testcase_num = {}
         testcase_passnum = {}
         for area in dt_cfg.dovetail_config['testarea_supported']:
@@ -127,11 +128,11 @@ class Report(object):
 
         testarea_scope = []
         for testcase in report_data['testcases_list']:
-            pattern = re.compile(
-                '|'.join(dt_cfg.dovetail_config['testarea_supported']))
+            supported_areas = dt_cfg.dovetail_config['testarea_supported']
+            pattern = re.compile('|'.join(supported_areas))
             area = pattern.findall(testcase['name'])
-            if not area:
-                self.logger.error("Test case {} not in supported testarea."
+            if not supported_areas or not area:
+                self.logger.error('Test case {} not in supported testarea.'
                                   .format(testcase['name']))
                 return None
             area = area[0]
@@ -180,19 +181,19 @@ class Report(object):
             with open(result_file, 'w') as f:
                 f.write(json.dumps(results) + '\n')
         except Exception as e:
-            self.logger.exception("Failed to add result to file {}, "
-                                  "exception: {}".format(result_file, e))
+            self.logger.exception('Failed to add result to file {}, '
+                                  'exception: {}'.format(result_file, e))
 
     @staticmethod
     def save_logs():
         file_suffix = time.strftime('%Y%m%d_%H%M', time.localtime())
-        logs_gz = "logs_{}.tar.gz".format(file_suffix)
+        logs_gz = 'logs_{}.tar.gz'.format(file_suffix)
         result_dir = dt_cfg.dovetail_config['result_dir']
 
         cwd = os.getcwd()
         os.chdir(os.path.join(result_dir, '..'))
         tar_file = os.path.join(result_dir, '..', logs_gz)
-        with tarfile.open(tar_file, "w:gz") as f_out:
+        with tarfile.open(tar_file, 'w:gz') as f_out:
             files = os.listdir(result_dir)
             for f in files:
                 if f not in ['workspace']:
@@ -273,11 +274,11 @@ class FunctestCrawler(Crawler):
                             success_case = data['details']['success']
                             error_case = data['details']['failures']
                             skipped_case = data['details']['skipped']
-                            details = {"tests": tests,
-                                       "failures": failed_num,
-                                       "success": success_case,
-                                       "errors": error_case,
-                                       "skipped": skipped_case}
+                            details = {'tests': tests,
+                                       'failures': failed_num,
+                                       'success': success_case,
+                                       'errors': error_case,
+                                       'skipped': skipped_case}
                 except KeyError as e:
                     self.logger.exception(
                         "Result data don't have key {}.".format(e))
@@ -318,7 +319,7 @@ class YardstickCrawler(Crawler):
             for jsonfile in f:
                 data = json.loads(jsonfile)
                 try:
-                    criteria = dt_utils.get_value_from_dict("result.criteria",
+                    criteria = dt_utils.get_value_from_dict('result.criteria',
                                                             data)
                     if criteria == 'PASS':
                         valid_tc = testcase.validate_testcase()
@@ -359,7 +360,7 @@ class BottlenecksCrawler(Crawler):
             for jsonfile in f:
                 data = json.loads(jsonfile)
                 try:
-                    if 'PASS' == data["data_body"]["result"]:
+                    if 'PASS' == data['data_body']['result']:
                         criteria = 'PASS'
                     else:
                         criteria = 'FAIL'
diff --git a/dovetail/tests/unit/test_report.py b/dovetail/tests/unit/test_report.py
new file mode 100644 (file)
index 0000000..ad236e9
--- /dev/null
@@ -0,0 +1,1156 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2018 mokats@intracom-telecom.com and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##
+
+import os
+import unittest
+import yaml
+from mock import patch, call, Mock
+
+import dovetail.report as dt_report
+
+__author__ = 'Stamatis Katsaounis <mokats@intracom-telecom.com>'
+
+
+class ReportTesting(unittest.TestCase):
+
+    def setUp(self):
+        test_path = os.path.dirname(os.path.realpath(__file__))
+        with open(os.path.join(test_path, 'test_testcase.yaml')) as f:
+            self.testcase_yaml = yaml.safe_load(f)
+
+    def tearDown(self):
+        pass
+
+    def teardown_method(self, method):
+        dt_report.FunctestCrawler.logger = None
+        dt_report.YardstickCrawler.logger = None
+        dt_report.BottlenecksCrawler.logger = None
+        dt_report.VnftestCrawler.logger = None
+        dt_report.FunctestChecker.logger = None
+        dt_report.YardstickChecker.logger = None
+        dt_report.BottlenecksChecker.logger = None
+        dt_report.VnftestChecker.logger = None
+        dt_report.Report.logger = None
+        dt_report.Report.results = {
+            'functest': {}, 'yardstick': {},
+            'bottlenecks': {}, 'shell': {}, 'vnftest': {}}
+
+    def _produce_report_initial_text(self, report_data):
+        report_txt = ''
+        report_txt += '\n\nDovetail Report\n'
+        report_txt += 'Version: %s\n' % report_data['version']
+        report_txt += 'Build Tag: %s\n' % report_data['build_tag']
+        report_txt += 'Test Date: %s\n' % report_data['test_date']
+        report_txt += 'Duration: %.2f s\n\n' % report_data['duration']
+        return report_txt
+
+    @patch('dovetail.report.dt_logger')
+    def test_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.Report.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.Report.logger)
+
+    @patch('dovetail.report.os.path')
+    @patch('dovetail.report.dt_cfg')
+    @patch('dovetail.report.dt_utils')
+    @patch.object(dt_report.Report, 'get_result')
+    @patch.object(dt_report.Report, 'check_result')
+    def test_check_tc_result(self, mock_check, mock_get, mock_utils,
+                             mock_config, mock_path):
+        report = dt_report.Report()
+        logger_obj = Mock()
+        report.logger = logger_obj
+        testcase_obj = Mock()
+        inner_testcase_obj = Mock()
+        testcase_obj.testcase = inner_testcase_obj
+        mock_config.dovetail_config = {'result_dir': 'result_dir'}
+        mock_utils.get_value_from_dict.return_value = 'check_results_file'
+        mock_path.join.return_value = 'results_file'
+        mock_path.isfile.return_value = True
+        mock_get.return_value = 'result'
+
+        result = report.check_tc_result(testcase_obj)
+
+        mock_utils.get_value_from_dict.assert_called_once_with(
+            'report.check_results_file', inner_testcase_obj)
+        mock_path.join.assert_called_once_with(
+            'result_dir', 'check_results_file')
+        mock_path.isfile.assert_called_once_with('results_file')
+        logger_obj.info.assert_called_once_with(
+            'Results have been stored with file results_file.')
+        mock_get.assert_called_once_with(testcase_obj, 'results_file')
+        mock_check.assert_called_once_with(testcase_obj, 'result')
+        self.assertEquals('result', result)
+
+    @patch('dovetail.report.os.path')
+    @patch('dovetail.report.dt_cfg')
+    @patch('dovetail.report.dt_utils')
+    @patch.object(dt_report.Report, 'get_result')
+    @patch.object(dt_report.Report, 'check_result')
+    def test_check_tc_result_no_file(self, mock_check, mock_get, mock_utils,
+                                     mock_config, mock_path):
+        report = dt_report.Report()
+        logger_obj = Mock()
+        report.logger = logger_obj
+        testcase_obj = Mock()
+        inner_testcase_obj = Mock()
+        testcase_obj.testcase = inner_testcase_obj
+        mock_config.dovetail_config = {'result_dir': 'result_dir'}
+        mock_utils.get_value_from_dict.return_value = 'check_results_file'
+        mock_path.join.return_value = 'results_file'
+        mock_path.isfile.return_value = False
+
+        result = report.check_tc_result(testcase_obj)
+
+        mock_utils.get_value_from_dict.assert_called_once_with(
+            'report.check_results_file', inner_testcase_obj)
+        mock_path.join.assert_called_once_with(
+            'result_dir', 'check_results_file')
+        mock_path.isfile.assert_called_once_with('results_file')
+        logger_obj.error.assert_called_once_with(
+            'Failed to store results with file results_file.')
+        mock_check.assert_called_once_with(testcase_obj)
+        self.assertEquals(None, result)
+
+    @patch('dovetail.report.os.path')
+    @patch('dovetail.report.dt_cfg')
+    @patch('dovetail.report.dt_utils')
+    @patch.object(dt_report.Report, 'get_result')
+    @patch.object(dt_report.Report, 'check_result')
+    def test_check_tc_result_no_check(self, mock_check, mock_get, mock_utils,
+                                      mock_config, mock_path):
+        report = dt_report.Report()
+        logger_obj = Mock()
+        report.logger = logger_obj
+        testcase_obj = Mock()
+        inner_testcase_obj = Mock()
+        testcase_obj.testcase = inner_testcase_obj
+        testcase_obj.name.return_value = 'name'
+        mock_config.dovetail_config = {'result_dir': 'result_dir'}
+        mock_utils.get_value_from_dict.return_value = None
+
+        result = report.check_tc_result(testcase_obj)
+
+        mock_utils.get_value_from_dict.assert_called_once_with(
+            'report.check_results_file', inner_testcase_obj)
+        logger_obj.error.assert_called_once_with(
+            "Failed to get 'check_results_file' from config "
+            "file of test case name")
+        mock_check.assert_called_once_with(testcase_obj)
+        self.assertEquals(None, result)
+
+    @patch('dovetail.report.CheckerFactory')
+    def test_check_result(self, mock_factory):
+        testcase_obj = Mock()
+        testcase_obj.validate_type.return_value = 'type'
+        checker_obj = Mock()
+        mock_factory.create.return_value = checker_obj
+
+        dt_report.Report.check_result(testcase_obj)
+
+        testcase_obj.validate_type.assert_called_once_with()
+        mock_factory.create.assert_called_once_with('type')
+        checker_obj.check.assert_called_once_with(testcase_obj, None)
+
+    @patch('dovetail.report.Testcase')
+    @patch('dovetail.report.datetime.datetime')
+    @patch('dovetail.report.dt_cfg')
+    def test_generate_json(self, mock_config, mock_datetime, mock_testcase):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        testcase_list = ['t_a', 't_b']
+        duration = 42
+        mock_config.dovetail_config = {
+            'build_tag': 'build_tag'
+        }
+        utc_obj = Mock()
+        utc_obj.strftime.return_value = '2018-01-13 13:13:13 UTC'
+        mock_datetime.utcnow.return_value = utc_obj
+        testcase_obj = Mock()
+        testcase_obj.passed.return_value = 'PASS'
+        testcase_obj.objective.return_value = 'objective'
+        testcase_obj.is_mandatory = True
+        testcase_obj.sub_testcase.return_value = ['subt_a']
+        testcase_obj.sub_testcase_passed.return_value = 'PASS'
+        mock_testcase.get.side_effect = [testcase_obj, None]
+
+        result = report.generate_json(testcase_list, duration)
+        expected = {
+            'version': '2018.09',
+            'build_tag': 'build_tag',
+            'test_date': '2018-01-13 13:13:13 UTC',
+            'duration': duration,
+            'testcases_list': [
+                {
+                    'name': 't_a',
+                    'result': 'PASS',
+                    'objective': 'objective',
+                    'mandatory': True,
+                    'sub_testcase': [{
+                        'name': 'subt_a',
+                        'result': 'PASS'
+                    }]
+                },
+                {
+                    'name': 't_b',
+                    'result': 'Undefined',
+                    'objective': '',
+                    'mandatory': False,
+                    'sub_testcase': []
+                }
+            ]
+        }
+
+        self.assertEquals(expected, result)
+
+    @patch('dovetail.report.datetime.datetime')
+    @patch('dovetail.report.dt_cfg')
+    def test_generate_json_no_list(self, mock_config, mock_datetime):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        duration = 42
+        mock_config.dovetail_config = {
+            'build_tag': 'build_tag'
+        }
+        utc_obj = Mock()
+        utc_obj.strftime.return_value = '2018-01-13 13:13:13 UTC'
+        mock_datetime.utcnow.return_value = utc_obj
+
+        result = report.generate_json([], duration)
+        expected = {
+            'version': '2018.09',
+            'build_tag': 'build_tag',
+            'test_date': '2018-01-13 13:13:13 UTC',
+            'duration': duration,
+            'testcases_list': []
+        }
+
+        self.assertEquals(expected, result)
+
+    @patch('dovetail.report.dt_cfg')
+    @patch.object(dt_report.Report, 'generate_json')
+    @patch.object(dt_report.Report, 'save_json_results')
+    def test_generate(self, mock_save, mock_generate, mock_config):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        testcase_list = ['t_a', 't_b']
+        mock_config.dovetail_config = {
+            'testarea_supported': testcase_list
+        }
+        duration = 42
+        report_data = {
+            'version': 'v2',
+            'build_tag': '2.0.0',
+            'test_date': '2018-01-13 13:13:13 UTC',
+            'duration': 42.42,
+            'testcases_list': [
+                {
+                    'name': 't_a',
+                    'result': 'PASS',
+                    'sub_testcase': [{
+                        'name': 'subt_a',
+                        'result': 'PASS'
+                    }]
+                },
+                {
+                    'name': 't_b',
+                    'result': 'SKIP'
+                }
+            ]
+        }
+        mock_generate.return_value = report_data
+
+        result = report.generate(testcase_list, duration)
+        expected = self._produce_report_initial_text(report_data)
+        expected += 'Pass Rate: 100.00% (1/1)\n'
+        expected += '%-25s  pass rate %.2f%%\n' % ('t_a:', 100)
+        expected += '-%-25s %s\n' % ('t_a', 'PASS')
+        expected += '\t%-110s %s\n' % ('subt_a', 'PASS')
+        expected += '%-25s  all skipped\n' % 't_b'
+        expected += '-%-25s %s\n' % ('t_b', 'SKIP')
+
+        mock_generate.assert_called_once_with(testcase_list, duration)
+        mock_save.assert_called_once_with(report_data)
+        report.logger.info.assert_called_once_with(expected)
+        self.assertEquals(expected, result)
+
+    @patch('dovetail.report.dt_cfg')
+    @patch.object(dt_report.Report, 'generate_json')
+    @patch.object(dt_report.Report, 'save_json_results')
+    def test_generate_error(self, mock_save, mock_generate, mock_config):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        mock_config.dovetail_config = {
+            'testarea_supported': []
+        }
+        testcase_list = ['t_a']
+        duration = 42
+        report_data = {
+            'version': 'v2',
+            'build_tag': '2.0.0',
+            'test_date': '2018-01-13 13:13:13 UTC',
+            'duration': 42.42,
+            'testcases_list': [{
+                'name': 't_a',
+                'result': 'PASS'
+            }]
+        }
+        mock_generate.return_value = report_data
+
+        result = report.generate(testcase_list, duration)
+        expected = None
+
+        mock_generate.assert_called_once_with(testcase_list, duration)
+        mock_save.assert_called_once_with(report_data)
+        report.logger.error.assert_called_once_with(
+            'Test case {} not in supported testarea.'
+            .format(report_data['testcases_list'][0]['name']))
+        self.assertEquals(expected, result)
+
+    @patch('dovetail.report.dt_cfg')
+    @patch.object(dt_report.Report, 'generate_json')
+    @patch.object(dt_report.Report, 'save_json_results')
+    def test_generate_no_cases(self, mock_save, mock_generate, mock_config):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        mock_config.dovetail_config = {
+            'testarea_supported': []
+        }
+        duration = 42
+        report_data = {
+            'version': 'v2',
+            'build_tag': '2.0.0',
+            'test_date': '2018-01-13 13:13:13 UTC',
+            'duration': 42.42,
+            'testcases_list': []
+        }
+        mock_generate.return_value = report_data
+
+        result = report.generate([], duration)
+        expected = self._produce_report_initial_text(report_data) +\
+            'no testcase or all testcases are skipped in this testsuite\n'
+
+        mock_generate.assert_called_once_with([], duration)
+        mock_save.assert_called_once_with(report_data)
+        report.logger.info.assert_called_once_with(expected)
+        self.assertEquals(expected, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json')
+    @patch('dovetail.report.os.path')
+    @patch('dovetail.report.dt_cfg')
+    def test_save_json_results(self, mock_config, mock_path, mock_json,
+                               mock_open):
+        mock_config.dovetail_config = {
+            'result_dir': 'a',
+            'result_file': 'b'
+        }
+        mock_path.join.return_value = 'result_file'
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = file_obj
+        mock_json.dumps.return_value = 'results text'
+
+        report = dt_report.Report()
+        report.save_json_results('results')
+
+        mock_path.join.assert_called_once_with('a', 'b')
+        mock_open.assert_called_once_with('result_file', 'w')
+        mock_json.dumps.assert_called_once_with('results')
+        file_obj.write.assert_called_once_with('results text\n')
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json')
+    @patch('dovetail.report.os.path')
+    @patch('dovetail.report.dt_cfg')
+    def test_save_json_results_exception(self, mock_config, mock_path,
+                                         mock_json, mock_open):
+        report = dt_report.Report()
+        logger_obj = Mock()
+        report.logger = logger_obj
+        mock_config.dovetail_config = {
+            'result_dir': 'a',
+            'result_file': 'b'
+        }
+        mock_path.join.return_value = 'result_file'
+        mock_open.return_value.__enter__.side_effect = Exception('error')
+
+        report.save_json_results('results')
+
+        mock_path.join.assert_called_once_with('a', 'b')
+        mock_open.assert_called_once_with('result_file', 'w')
+        report.logger.exception.assert_called_once_with(
+            'Failed to add result to file result_file, exception: error')
+
+    @patch('dovetail.report.dt_cfg')
+    @patch('dovetail.report.time')
+    @patch('dovetail.report.os')
+    @patch('dovetail.report.tarfile')
+    def test_save_logs(self, mock_tar, mock_os, mock_time, mock_config):
+        mock_config.dovetail_config = {'result_dir': 'result_dir'}
+        local_time_obj = Mock()
+        mock_time.localtime.return_value = local_time_obj
+        mock_time.strftime.return_value = '20180113_13:13'
+        mock_os.getcwd.return_value = 'cwd'
+        tar_obj = Mock()
+        tar_file_obj = Mock()
+        mock_tar.open.return_value.__enter__.return_value = tar_file_obj
+        mock_os.path.join.side_effect = ['one', tar_obj, 'three']
+        mock_os.listdir.return_value = ['file']
+
+        dt_report.Report.save_logs()
+
+        mock_time.localtime.assert_called_once_with()
+        mock_time.strftime.assert_called_once_with('%Y%m%d_%H%M',
+                                                   local_time_obj)
+        mock_os.getcwd.assert_called_once_with()
+        mock_os.path.join.assert_has_calls([
+            call('result_dir', '..'),
+            call('result_dir', '..', 'logs_20180113_13:13.tar.gz'),
+            call('results', 'file')])
+        mock_tar.open.assert_called_once_with(tar_obj, 'w:gz')
+        mock_os.listdir.assert_called_once_with('result_dir')
+        tar_file_obj.add.assert_called_once_with('three')
+        mock_os.chdir.assert_has_calls([call('one'), call('cwd')])
+
+    @patch('dovetail.report.CrawlerFactory')
+    def test_get_result(self, mock_crawler):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        testcase_obj = Mock()
+        crawler_obj = Mock()
+        testcase_obj.validate_testcase.return_value = 'validate'
+        testcase_obj.validate_type.return_value = 'functest'
+        mock_crawler.create.return_value = crawler_obj
+        crawler_obj.crawl.return_value = 'result'
+
+        result = report.get_result(testcase_obj, 'check_results_file')
+
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.validate_type.assert_called_once_with()
+        mock_crawler.create.assert_called_once_with('functest')
+        crawler_obj.crawl.assert_called_once_with(
+            testcase_obj, 'check_results_file')
+        logger_obj.debug.assert_called_once_with(
+            'Test case: validate -> result acquired')
+        self.assertEquals({'validate': 'result'},
+                          dt_report.Report.results['functest'])
+        self.assertEquals('result', result)
+
+    @patch('dovetail.report.CrawlerFactory')
+    def test_get_result_no_result(self, mock_crawler):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        testcase_obj = Mock()
+        crawler_obj = Mock()
+        testcase_obj.validate_testcase.return_value = 'validate'
+        testcase_obj.validate_type.return_value = 'functest'
+        testcase_obj.increase_retry.return_value = 'retry'
+        mock_crawler.create.return_value = crawler_obj
+        crawler_obj.crawl.return_value = None
+
+        result = report.get_result(testcase_obj, 'check_results_file')
+
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.validate_type.assert_called_once_with()
+        mock_crawler.create.assert_called_once_with('functest')
+        crawler_obj.crawl.assert_called_once_with(
+            testcase_obj, 'check_results_file')
+        testcase_obj.increase_retry.assert_called_once_with()
+        logger_obj.debug.assert_called_once_with(
+            'Test case: validate -> result acquired retry: retry')
+        self.assertEquals(None, result)
+
+    @patch('dovetail.report.CrawlerFactory')
+    def test_get_result_no_crawler(self, mock_crawler):
+        logger_obj = Mock()
+        report = dt_report.Report()
+        report.logger = logger_obj
+        testcase_obj = Mock()
+        testcase_obj.name.return_value = 'name'
+        testcase_obj.validate_testcase.return_value = 'validate'
+        testcase_obj.validate_type.return_value = 'functest'
+        mock_crawler.create.return_value = None
+
+        result = report.get_result(testcase_obj, 'check_results_file')
+
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.validate_type.assert_called_once_with()
+        mock_crawler.create.assert_called_once_with('functest')
+        logger_obj.error.assert_called_once_with(
+            'Crawler is None: name')
+        self.assertEquals(None, result)
+
+    @patch('dovetail.report.dt_logger')
+    def test_functest_crawler_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.FunctestCrawler.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.FunctestCrawler.logger)
+
+    @patch('dovetail.report.dt_cfg')
+    @patch('dovetail.report.os.path')
+    def test_functest_crawler_crawl_not_exists(self, mock_path, mock_config):
+        logger_obj = Mock()
+        mock_config.dovetail_config = {'build_tag': 'tag'}
+        dt_report.FunctestCrawler.logger = logger_obj
+        mock_path.exists.return_value = False
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        testcase_obj.validate_testcase.return_value = 'validate'
+        testcase_obj.name.return_value = 'name'
+
+        crawler = dt_report.FunctestCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.name.assert_called_once_with()
+        logger_obj.error.assert_called_once_with(
+            'Result file not found: {}'.format(file_path))
+        self.assertEquals(None, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json')
+    @patch('dovetail.report.dt_cfg')
+    @patch('dovetail.report.dt_utils')
+    @patch('dovetail.report.os.path')
+    def test_functest_crawler_crawl(self, mock_path, mock_utils, mock_config,
+                                    mock_json, mock_open):
+        logger_obj = Mock()
+        mock_config.dovetail_config = {'build_tag': 'tag'}
+        dt_report.FunctestCrawler.logger = logger_obj
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        testcase_obj.validate_testcase.return_value = 'name'
+        testcase_obj.name.return_value = 'name'
+        testcase_obj.sub_testcase.return_value = ['subt_a']
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+        data_dict = {
+            'case_name': 'name',
+            'build_tag': 'tag-name',
+            'criteria': 'criteria',
+            'start_date': 'start_date',
+            'stop_date': 'stop_date',
+            'details': {
+                'tests_number': 'tests_number',
+                'failures_number': 'failures_number',
+                'success': 'success',
+                'failures': 'failures',
+                'skipped': 'skipped'
+            }
+        }
+        mock_json.loads.return_value = data_dict
+        mock_utils.get_duration.return_value = 'duration'
+
+        crawler = dt_report.FunctestCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'criteria', 'timestart': 'start_date',
+                    'timestop': 'stop_date', 'duration': 'duration',
+                    'details': {
+                        'tests': 'tests_number', 'failures': 'failures_number',
+                        'success': 'success', 'errors': 'failures',
+                        'skipped': 'skipped'}}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_json.loads.assert_called_once_with(file_obj)
+        mock_utils.get_duration.assert_called_once_with(
+            'start_date', 'stop_date', logger_obj)
+        testcase_obj.set_results.assert_called_once_with(expected)
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.sub_testcase.assert_called_once_with()
+        testcase_obj.name.assert_called_once_with()
+        self.assertEquals(expected, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.dt_cfg')
+    @patch('dovetail.report.dt_utils')
+    @patch('dovetail.report.os.path')
+    def test_functest_crawler_crawl_errors(self, mock_path, mock_utils,
+                                           mock_config, mock_load, mock_open):
+        logger_obj = Mock()
+        mock_config.dovetail_config = {'build_tag': 'tag'}
+        dt_report.FunctestCrawler.logger = logger_obj
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        testcase_obj.validate_testcase.return_value = 'name'
+        testcase_obj.name.return_value = 'name'
+        testcase_obj.sub_testcase.return_value = ['subt_a']
+        file_a = Mock()
+        file_b = Mock()
+        mock_open.return_value.__enter__.return_value = [file_a, file_b]
+        mock_load.side_effect = [ValueError(), {}]
+        mock_utils.get_duration.return_value = 'duration'
+
+        crawler = dt_report.FunctestCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_load.assert_has_calls([call(file_a), call(file_b)])
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.sub_testcase.assert_called_once_with()
+        testcase_obj.name.assert_called_once_with()
+        logger_obj.exception.assert_called_once_with(
+            "Result data don't have key 'case_name'.")
+        self.assertEquals(None, result)
+
+    @patch('dovetail.report.dt_logger')
+    def test_yardstick_crawler_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.YardstickCrawler.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.YardstickCrawler.logger)
+
+    @patch('dovetail.report.os.path')
+    def test_yardstick_crawler_crawl_not_exists(self, mock_path):
+        logger_obj = Mock()
+        dt_report.YardstickCrawler.logger = logger_obj
+        mock_path.exists.return_value = False
+        file_path = 'file_path'
+
+        crawler = dt_report.YardstickCrawler()
+        result = crawler.crawl(None, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        logger_obj.error.assert_called_once_with(
+            'Result file not found: {}'.format(file_path))
+        self.assertEquals(None, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.dt_utils')
+    @patch('dovetail.report.os.path')
+    def test_yardstick_crawler_crawl(self, mock_path, mock_utils, mock_loads,
+                                     mock_open):
+        dt_report.YardstickCrawler.logger = Mock()
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        testcase_obj.validate_testcase.return_value = 'name'
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+        data_dict = {
+            'result': {
+                'testcases': {
+                    'name': {
+                        'tc_data': [{
+                            'data': {
+                                'sla_pass': 0
+                            }
+                        }]
+                    }
+                }
+            }
+        }
+        mock_loads.return_value = data_dict
+        mock_utils.get_value_from_dict.return_value = 'PASS'
+
+        crawler = dt_report.YardstickCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'FAIL'}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_loads.assert_called_once_with(file_obj)
+        mock_utils.get_value_from_dict.assert_called_once_with(
+            'result.criteria', data_dict)
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.set_results.assert_called_once_with(expected)
+        self.assertEquals(expected, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.dt_utils')
+    @patch('dovetail.report.os.path')
+    def test_yardstick_crawler_crawl_key_error(self, mock_path, mock_utils,
+                                               mock_loads, mock_open):
+        logger_obj = Mock()
+        dt_report.YardstickCrawler.logger = logger_obj
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        testcase_obj.validate_testcase.return_value = 'name'
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+
+        mock_loads.return_value = {}
+        mock_utils.get_value_from_dict.return_value = 'PASS'
+
+        crawler = dt_report.YardstickCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'PASS'}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_loads.assert_called_once_with(file_obj)
+        mock_utils.get_value_from_dict.assert_called_once_with(
+            'result.criteria', {})
+        testcase_obj.validate_testcase.assert_called_once_with()
+        testcase_obj.set_results.assert_called_once_with(expected)
+        logger_obj.exception.assert_called_once_with(
+            "Pass flag not found 'result'")
+        self.assertEquals(expected, result)
+
+    @patch('dovetail.report.dt_logger')
+    def test_bottlenecks_crawler_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.BottlenecksCrawler.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.BottlenecksCrawler.logger)
+
+    @patch('dovetail.report.os.path')
+    def test_bottlenecks_crawler_crawl_not_exists(self, mock_path):
+        logger_obj = Mock()
+        dt_report.BottlenecksCrawler.logger = logger_obj
+        mock_path.exists.return_value = False
+        file_path = 'file_path'
+
+        crawler = dt_report.BottlenecksCrawler()
+        result = crawler.crawl(None, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        logger_obj.error.assert_called_once_with(
+            'Result file not found: {}'.format(file_path))
+        self.assertEquals(None, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.os.path')
+    def test_bottlenecks_crawler_crawl_pass(self, mock_path, mock_loads,
+                                            mock_open):
+        dt_report.BottlenecksCrawler.logger = Mock()
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+        data_dict = {
+            'data_body': {
+                'result': 'PASS'
+            }
+        }
+        mock_loads.return_value = data_dict
+
+        crawler = dt_report.BottlenecksCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'PASS'}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_loads.assert_called_once_with(file_obj)
+        testcase_obj.set_results.assert_called_once_with(expected)
+        self.assertEquals(expected, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.os.path')
+    def test_bottlenecks_crawler_crawl_fail(self, mock_path, mock_loads,
+                                            mock_open):
+        dt_report.BottlenecksCrawler.logger = Mock()
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+        data_dict = {
+            'data_body': {
+                'result': 'FAIL'
+            }
+        }
+        mock_loads.return_value = data_dict
+
+        crawler = dt_report.BottlenecksCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'FAIL'}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_loads.assert_called_once_with(file_obj)
+        testcase_obj.set_results.assert_called_once_with(expected)
+        self.assertEquals(expected, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.os.path')
+    def test_bottlenecks_crawler_crawl_key_error(self, mock_path, mock_loads,
+                                                 mock_open):
+        logger_obj = Mock()
+        dt_report.BottlenecksCrawler.logger = logger_obj
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+
+        mock_loads.return_value = {}
+
+        crawler = dt_report.BottlenecksCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'FAIL'}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_loads.assert_called_once_with(file_obj)
+        testcase_obj.set_results.assert_called_once_with(expected)
+        logger_obj.exception.assert_called_once_with(
+            "Pass flag not found 'data_body'")
+        self.assertEquals(expected, result)
+
+    @patch('dovetail.report.os.path')
+    def test_shell_crawler_crawl_not_exists(self, mock_path):
+        mock_path.exists.return_value = False
+        file_path = 'file_path'
+
+        crawler = dt_report.ShellCrawler()
+        result = crawler.crawl(None, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        self.assertEquals(None, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.os.path')
+    def test_shell_crawler_crawl_exception(self, mock_path, mock_open):
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        mock_open.return_value.__enter__.return_value = Exception()
+
+        crawler = dt_report.ShellCrawler()
+        result = crawler.crawl(None, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        self.assertEquals(None, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.load')
+    @patch('dovetail.report.os.path')
+    def test_shell_crawler_crawl(self, mock_path, mock_load,
+                                 mock_open):
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = file_obj
+        mock_load.return_value = 'result'
+
+        crawler = dt_report.ShellCrawler()
+        result = crawler.crawl(None, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_load.assert_called_once_with(file_obj)
+        self.assertEquals('result', result)
+
+    @patch('dovetail.report.dt_logger')
+    def test_vnftest_crawler_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.VnftestCrawler.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.VnftestCrawler.logger)
+
+    @patch('dovetail.report.os.path')
+    def test_vnftest_crawler_crawl_not_exists(self, mock_path):
+        logger_obj = Mock()
+        dt_report.VnftestCrawler.logger = logger_obj
+        mock_path.exists.return_value = False
+        file_path = 'file_path'
+
+        crawler = dt_report.VnftestCrawler()
+        result = crawler.crawl(None, file_path)
+
+        mock_path.exists.assert_called_once_with(file_path)
+        logger_obj.error.assert_called_once_with(
+            'Result file not found: {}'.format(file_path))
+        self.assertEquals(None, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.os.path')
+    def test_vnftest_crawler_crawl(self, mock_path, mock_loads,
+                                   mock_open):
+        dt_report.VnftestCrawler.logger = Mock()
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+        data_dict = {
+            'result': {
+                'criteria': 'PASS'
+            }
+        }
+        mock_loads.return_value = data_dict
+
+        crawler = dt_report.VnftestCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'PASS'}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_loads.assert_called_once_with(file_obj)
+        self.assertEquals(expected, result)
+
+    @patch('__builtin__.open')
+    @patch('dovetail.report.json.loads')
+    @patch('dovetail.report.os.path')
+    def test_vnftest_crawler_crawl_key_error(self, mock_path, mock_loads,
+                                             mock_open):
+        logger_obj = Mock()
+        dt_report.VnftestCrawler.logger = logger_obj
+        mock_path.exists.return_value = True
+        file_path = 'file_path'
+        testcase_obj = Mock()
+        file_obj = Mock()
+        mock_open.return_value.__enter__.return_value = [file_obj]
+
+        mock_loads.return_value = {}
+
+        crawler = dt_report.VnftestCrawler()
+        result = crawler.crawl(testcase_obj, file_path)
+        expected = {'criteria': 'FAIL'}
+
+        mock_path.exists.assert_called_once_with(file_path)
+        mock_open.assert_called_once_with(file_path, 'r')
+        mock_loads.assert_called_once_with(file_obj)
+        logger_obj.exception.assert_called_once_with(
+            "Pass flag not found 'result'")
+        self.assertEquals(expected, result)
+
+    def test_crawler_factory(self):
+        result = dt_report.CrawlerFactory.create('shell')
+        self.assertEquals(dt_report.ShellCrawler, result.__class__)
+
+    def test_crawler_factory_none(self):
+        self.assertEquals(None, dt_report.CrawlerFactory.create('other'))
+
+    def test_result_checker(self):
+        self.assertEquals('PASS', dt_report.ResultChecker.check())
+
+    @patch('dovetail.report.dt_logger')
+    def test_functest_checker_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.FunctestChecker.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.FunctestChecker.logger)
+
+    def test_functest_get_sub_testcase_no_result(self):
+        self.assertEquals(
+            False, dt_report.FunctestChecker.get_sub_testcase(None, None))
+
+    def test_functest_get_sub_testcase_simple_match(self):
+        self.assertEquals(
+            True,
+            dt_report.FunctestChecker.get_sub_testcase('subt_a',
+                                                       ['subt_b', 'subt_a']))
+
+    def test_functest_get_sub_testcase_extended_match(self):
+        self.assertEquals(
+            True,
+            dt_report.FunctestChecker.get_sub_testcase('subt_a',
+                                                       ['subt_b', 'subt_a+']))
+
+    def test_functest_get_sub_no_match(self):
+        self.assertEquals(
+            False,
+            dt_report.FunctestChecker.get_sub_testcase('subt_a',
+                                                       ['subt_b']))
+
+    def test_functest_check_no_db_results(self):
+        testcase_obj = Mock()
+        testcase_obj.sub_testcase.return_value = ['subt_a']
+
+        checker = dt_report.FunctestChecker()
+        checker.check(testcase_obj, None)
+
+        testcase_obj.sub_testcase.assert_called_once_with()
+        testcase_obj.sub_testcase_passed.assert_called_once_with(
+            'subt_a', 'FAIL')
+
+    def test_functest_check_no_subtestcases(self):
+        testcase_obj = Mock()
+        testcase_obj.sub_testcase.return_value = None
+
+        checker = dt_report.FunctestChecker()
+        checker.check(testcase_obj, {'criteria': 'PASS'})
+
+        testcase_obj.sub_testcase.assert_called_once_with()
+        testcase_obj.passed.assert_called_once_with('PASS')
+
+    @patch.object(dt_report.FunctestChecker, 'get_sub_testcase')
+    def test_functest_check(self, mock_get):
+        testcase_obj = Mock()
+        testcase_obj.sub_testcase.return_value = [
+            'subt_a', 'subt_b', 'subt_c', 'subt_d']
+        logger_obj = Mock()
+        dt_report.FunctestChecker.logger = logger_obj
+        db_result = {
+            'criteria': 'PASS',
+            'details': {
+                'success': True,
+                'skipped': False
+            }
+        }
+        mock_get.side_effect = [True, False, True, False, False, KeyError()]
+
+        checker = dt_report.FunctestChecker()
+        checker.check(testcase_obj, db_result)
+
+        testcase_obj.sub_testcase.assert_called_once_with()
+        logger_obj.debug.assert_has_calls([
+            call('Check sub_testcase: subt_a'),
+            call('Check sub_testcase: subt_b'),
+            call('Check sub_testcase: subt_c'),
+            call('Check sub_testcase: subt_d')])
+        testcase_obj.sub_testcase_passed.assert_has_calls([
+            call('subt_a', 'PASS'),
+            call('subt_b', 'SKIP'),
+            call('subt_c', 'FAIL'),
+            call('subt_d', 'FAIL')])
+        testcase_obj.passed.assert_has_calls([call('PASS'), call('FAIL')])
+
+    @patch('dovetail.report.dt_logger')
+    def test_yardstick_checker_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.YardstickChecker.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.YardstickChecker.logger)
+
+    def test_yardstick_check_result(self):
+        testcase_obj = Mock()
+        result = {'criteria': 'PASS'}
+
+        dt_report.YardstickChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with('PASS')
+
+    def test_yardstick_check_result_none(self):
+        testcase_obj = Mock()
+        result = {}
+
+        dt_report.YardstickChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with('FAIL')
+
+    @patch('dovetail.report.dt_logger')
+    def test_bottlenecks_checker_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.BottlenecksChecker.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.BottlenecksChecker.logger)
+
+    def test_bottlenecks_check_result(self):
+        testcase_obj = Mock()
+        result = {'criteria': 'PASS'}
+
+        dt_report.BottlenecksChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with('PASS')
+
+    def test_bottlenecks_check_result_none(self):
+        testcase_obj = Mock()
+        result = {}
+
+        dt_report.BottlenecksChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with('FAIL')
+
+    def test_shell_check_result(self):
+        testcase_obj = Mock()
+        result = {'pass': True}
+
+        dt_report.ShellChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with(True)
+
+    def test_shell_check_result_exception(self):
+        testcase_obj = Mock()
+        result = {}
+
+        dt_report.ShellChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with(False)
+
+    @patch('dovetail.report.dt_logger')
+    def test_vnftest_checker_create_log(self, mock_logger):
+        getlogger_obj = Mock()
+        logger_obj = Mock()
+        logger_obj.getLogger.return_value = getlogger_obj
+        mock_logger.Logger.return_value = logger_obj
+
+        dt_report.VnftestChecker.create_log()
+
+        self.assertEquals(getlogger_obj, dt_report.VnftestChecker.logger)
+
+    def test_vnftest_check_result(self):
+        testcase_obj = Mock()
+        result = {'criteria': 'PASS'}
+
+        dt_report.VnftestChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with('PASS')
+
+    def test_vnftest_check_result_none(self):
+        testcase_obj = Mock()
+        result = {}
+
+        dt_report.VnftestChecker.check(testcase_obj, result)
+
+        testcase_obj.passed.assert_called_once_with('FAIL')
+
+    def test_checker_factory(self):
+        result = dt_report.CheckerFactory.create('shell')
+        self.assertEquals(dt_report.ShellChecker, result.__class__)
+
+    def test_checker_factory_none(self):
+        self.assertEquals(None, dt_report.CheckerFactory.create('other'))