robot里面run起来的接口主要有两类
run_cli
1 def run_cli(arguments): 2 """Command line execution entry point for running tests. 3 4 :param arguments: Command line arguments as a list of strings. 5 6 For programmatic usage the :func:`run` function is typically better. It has 7 a better API for that usage and does not call :func:`sys.exit` like this 8 function. 9 10 Example:: 11 12 from robot import run_cli 13 14 run_cli(['--include', 'tag', 'path/to/tests.html']) 15 """ 16 RobotFramework().execute_cli(arguments)
run
def run(*datasources, **options): """Executes given Robot Framework data sources with given options. ... ... ... Example:: from robot import run run('path/to/tests.html', include=['tag1', 'tag2']) with open('stdout.txt', 'w') as stdout: run('t1.txt', 't2.txt', report='r.html', log='NONE', stdout=stdout) Equivalent command line usage:: robot --include tag1 --include tag2 path/to/tests.html robot --report r.html --log NONE t1.txt t2.txt > stdout.txt """ return RobotFramework().execute(*datasources, **options)
我们择其一从 run往下走
return RobotFramework().execute(*datasources, **options)
RobotFramework 继承自Application
class RobotFramework(Application):
Application基类位于 /robot/utils/applicaiton.py
execute 函数执行并进入main函数体,
1 def execute(self, *arguments, **options): 2 with self._logger: 3 self._logger.info('%s %s' % (self._ap.name, self._ap.version)) 4 return self._execute(list(arguments), options) 5 #execute 调用私有函数 _execute 执行操作 6 def _execute(self, arguments, options): 7 try: 8 rc = self.main(arguments, **options) 9 except DataError as err: 10 return self._report_error(err.message, help=True) 11 except (KeyboardInterrupt, SystemExit): 12 return self._report_error('Execution stopped by user.', 13 rc=STOPPED_BY_USER) 14 except: 15 error, details = get_error_details(exclude_robot_traces=False) 16 return self._report_error('Unexpected error: %s' % error, 17 details, rc=FRAMEWORK_ERROR) 18 else: 19 return rc or 0
由于RobotFramwork重写了main() 函数, 所以跳到RobotFramework的main接口执行。
/robot/run.py
1 def main(self, datasources, **options): 2 print "Enter run.main" 3 settings = RobotSettings(options) 4 # print settings 5 LOGGER.register_console_logger(**settings.console_output_config) 6 LOGGER.info('Settings: %s' % unic(settings)) 7 suite = TestSuiteBuilder(settings['SuiteNames'], 8 settings['WarnOnSkipped']).build(*datasources) 9 suite.configure(**settings.suite_config) 10 if settings.pre_run_modifiers: 11 suite.visit(ModelModifier(settings.pre_run_modifiers, 12 settings.run_empty_suite, LOGGER)) 13 with pyloggingconf.robot_handler_enabled(settings.log_level): 14 result = suite.run(settings) 15 print result 16 LOGGER.info("Tests execution ended. Statistics: %s" 17 % result.suite.stat_message) 18 if settings.log or settings.report or settings.xunit: 19 writer = ResultWriter(settings.output if settings.log 20 else result) 21 writer.write_results(settings.get_rebot_settings()) 22 return result.return_code
STEP 1.
[explian]:
settings = RobotSettings(options)
/robot/conf/settings.py 解析传入参数
class RobotSettings(_BaseSettings):
-->继承自 _BaseSettings, 没有单独的__init__ 与基类共用 __init.
STEP 2.
suite = TestSuiteBuilder(settings['SuiteNames'], settings['WarnOnSkipped']).build(*datasources)
[explian]: class TestSuiteBuilder 会初始化StepBuilder
builder.build_steps/builder.build_step 解析suite里面包含的测试steps or step.
23 self._build_steps = builder.build_steps
24 self._build_step = builder.build_step
由TestSuiteBuilder.build 生成 TestSuite
/robot/running/builder.py
1 def build(self, *paths): 2 """ 3 :param paths: Paths to test data files or directories. 4 :return: :class:`~robot.running.model.TestSuite` instance. 5 """ 6 if not paths: 7 raise DataError('One or more source paths required.') 8 if len(paths) == 1: 9 return self._parse_and_build(paths[0]) 10 root = TestSuite() 11 for path in paths: 12 root.suites.append(self._parse_and_build(path)) 13 return root
STEP 3.
/robot/model/testsuite.py
suite.configure(**settings.suite_config)
一些配置参数下发