Package: iParrot
ParrotAutomated test solution for http requests based on recording and playback1. Instructions for use1.1 InstallThe Parrot project is developed based on Python 3， and the recommended version is 3.7.x. Please ensure that the corresponding version of python environment is installed on the target machine.Method One: install viapipcommandiParrot project has been submitted to PyPI.You could install viapip install iParrotcommand.If you need a upgrade, trypip install -U iParrotcommand.Method Two: install using source codeCode Repository:https://github.com/idle-man/iParrotDownload source code pkg and install viapython setup.py installcommand.After the installation is complete, theparrotexecutable will be generated, tryparrot helporparrot -v. If there is a problem, feedback an issue:https://github.com/idle-man/iParrot/issues1.2 Usage1.2.1 View commands supported by Parrot:parrot helpTwo core commands are:recordandplayback$ parrot help
Automated test solution for http requests based on recording and playback
Version: ...

Usage: parrot [-h] [-v] [command] [<args>]

command:
  record   - parse source file and generate test cases
            see detail usage: `parrot help record`
  playback - run standardized test cases and do validations
            see detail usage: `parrot help playback`
  template - generate standardized test case template file
            see detail usage: `parrot help template`
  replace  - replace existing test cases with specified rules
            see detail usage: `parrot help replace`
  home     - show homepage on github
  doc      - show readme on github


optional arguments:
  -h, --help         show this help message and exit
  -v, -V, --version  show version1.2.2 View usage ofrecord:parrot help recordThe purpose of this step is to parse the user-specified source file (currently .har) into a standardized set of use cases.$ parrot help record
...

Usage: parrot record [<args>]

Arguments:
  -s, --source SOURCE   source file with path, *.har or directory [required]
  -t, --target TARGET   target output path, 'ParrotProject' as default
  -i, --include INCLUDE include filter on url, separated by ',' if multiple
  -e, --exclude EXCLUDE exclude filter on url, separated by ',' if multiple
  -vi, --validation-include V_INCLUDE
                        include filter on response validation, separated by ',' if multiple
  -ve, --validation-exclude V_EXCLUDE  
                        exclude filter on response validation, separated by ',' if multiple
  -ae, --auto-extract   automatic identification of interface dependencies or not, False as default

  --log-level LOG_LEVEL log level: debug, info, warn, error, info as default
  --log-mode  LOG_MODE  log mode : 1-on screen, 2-in log file, 3-1&2, 1 as default
  --log-path  LOG_PATH  log path : <project path> as default
  --log-name  LOG_NAME  log name : parrot.log as default1.2.3 View usage ofplayback:parrot help playbackThis step is to execute the specified set of test cases and generate a test report.$ parrot help playback
...

Usage: parrot playback [<args>]

Arguments:
  -s, --suite, -c, --case SUITE_OR_CASE
                        test suite or case with path, *.yml or directory [required]
  -t, --target TARGET   output path for report and log, 'ParrotProject' as default
  -i, --interval INTERVAL
                        interval time(ms) between each step, use the recorded interval as default
  -env, --environment ENVIRONMENT
                        environment tag, defined in project/environments/*.yml, use defined config in test_suites as default
  -reset, --reset-after-case
                        reset runtime environment or not, False as default

  --fail-stop           stop or not when a test step failed on validation, False as default
  --fail-retry-times FAIL_RETRY_TIMES
                        max retry times when a test step failed on validation, 0 as default
  --fail-retry-interval FAIL_RETRY_INTERVAL 
                        retry interval(ms) when a test step failed on validation, 100 as default

  --log-level LOG_LEVEL log level: debug, info, warn, error, info as default
  --log-mode  LOG_MODE  log mode : 1-on screen, 2-in log file, 3-1&2, 1 as default
  --log-path  LOG_PATH  log path : <project path> as default
  --log-name  LOG_NAME  log name : parrot.log as default1.2.4 View usage oftemplate:parrot help templateThis step is to automatically generate standardized test case templates and examples, which is convenient for users to refer to self-built use cases.$ parrot help template
...

Usage: parrot template [<args>]

Arguments:
  -t, --target TARGET   target output path, 'ParrotProject' as default

  --log-level LOG_LEVEL log level: debug, info, warn, error, info as default
  --log-mode  LOG_MODE  log mode : 1-on screen, 2-in log file, 3-1&2, 1 as default
  --log-path  LOG_PATH  log path : <project path> as default
  --log-name  LOG_NAME  log name : parrot.log as default1.2.5 View usage ofreplace:parrot help replaceThis step is to batch replace theconfig.variablesof the generated use cases according to your specified rules.$ parrot help replace
...

Usage: parrot replace [<args>]

Arguments:
  -s, --suite, -c, --case SUITE_OR_CASE
                        test suite or case with path, *.yml or directory [required]
  -t, --target TARGET   target output path, 'ParrotProjectNew' as default
  -r, --rule RULE       replace rules, separated by ',' if multiple [required]
                        'key=>value', 'value1=>value2' or 'apiA::key=>value' only for specified api

  --log-level LOG_LEVEL log level: debug, info, warn, error, info as default
  --log-mode  LOG_MODE  log mode : 1-on screen, 2-in log file, 3-1&2, 1 as default
  --log-path  LOG_PATH  log path : <project path> as default
  --log-name  LOG_NAME  log name : parrot.log as default1.3 Demo1.3.1 Build Sample application and export HARIn order to facilitate the function debugging and operation demonstration, a simple web application(based on Python Flask) was specially built:https://github.com/idle-man/ParrotSamplePlease refer to its README to complete the application setup in the local environment. It provides the "recommended function operations".We use this as an example, using the browser's developer tools, after completing this series of operations, export the HAR file, assuming we named itsample.harand placed it in your working directory.HAR is a common standardized format for storing HTTP requests and responses.Its versatility: can be exported with consistent format from Charles, Fiddler, Chrome, etc.Its standardization: JSON format and UTF-8 coding.1.3.2 Record - Transforming HAR into standardized use casesWe assume that you have completed the installation ofparrotas described in Chapter 1. Now we use the command line tool on the computer and switch to the path wheresample.haris located.It is recommended to usePyCharm, which containsTerminal, which is convenient for operation and helps to view the following use cases.According to the instructions in Section 1.2.2, we have a general understanding of the basic usage of therecordcommand. Now let's make a try onsample.har.# A simple record: -s & -t$ parrot record -s sample.har -t demo0If it is successful, after the execution is complete, you will see the generated use cases set in current directory. The structure is as follows:demo0/
  ├── environments
  │    └── *env*.yml: Project-level environment variable configuration
  ├── test_steps
  │    └── *case_name*.yml: The minimum execution unit, a http request is a step
  ├── test_cases
  │    └── *case_name*.yml: Independent closed-loop unit,  consisting of one or more steps
  └── test_suites
       └── *suite_name*.yml: Test case set, consisting of one or more casesEachEntryin HAR will be converted into a test_step containing the specific request and validation information.Eachtest_steptest_casetest_suitecontains its ownconfigsetup_hooksteardown_hooks.The specific format can be found in theAppendix: Use Case Structure.# Not all recorded requests need to be converted to use cases: -i & -eBecause HAR is a full export without selection, it may contain some requests that we don't need to test, such as*.css*.js. In order to avoid the manual processing, we can filter them out during the record phase.Parrot currently provides -i/--include and -e/--exclude filter modes, specifically:-i, --include: According to the specified parameters, theurlin eachEntryis ambiguously matched, and the matching will be retained. The relationship between multiple include parameters is OR.-e, --exclude: According to the specified parameters, theurlin eachEntryis ambiguously matched, and the matching will be excluded. The relationship between multiple excludes is OR.The two parameters can be used only in one or in combination to achieve your filtering needs.In our above requirement, we want to filter out the unwanted*.cssand*.js, just use -e, --exclude.$ parrot record -s sample.har -t demo1 -e ".css, .js"After that, you can check if the requirement is met in demo1/test_steps.# Not all content in response can be expected: -vi & -veAn example of the validations generated in test_step, the user can also customize this format:validations:
- <comparator>:
    <check>: <expected result>Thecheck: According to the important information in the above Mode One, the unified format is: <PREFIX>.<KEYS>Available PREFIX:status,content,headers,cookies, in lower caseKEYS instatus:codeKEYS inheadersandcookies: Currently only extracting the outer keysKEYS incontent(json format):content.a.b[1].cBy default, automatically generated validations will includestatus.codeand all keys ofcontentand unofficial keys ofheaders.In fact, some of these keys do not need to be verified for reasons such as variability, etc., such as thetagtimestampcontained in the response information of each request insample.har, which is best removed when it is automatically generated.Parrot currently provides -vi/--validation-include and -ve/--validation-exclude filter modes, specifically:-vi, --validation-include: According to the specified parameters, theheadersandcontentin the response in each Entry are fuzzy matched, and the matching will be retained. The relationship between multiple -vi is OR.-ve, --validation-exclude: According to the specified parameters, theheadersandcontentin the response in each Entry are fuzzy matched, the matching will be excluded. The relationship between multiple -ve is OR.The two parameters can be used only in one or in combination to achieve your filtering needs.In our above requirement, we want to filter out unwantedtagandtimestamp, just use -ve, --validation-exclude.$ parrot record -s sample.har -t demo2 -e ".css, .js" -ve "content.tag, timestamp"About thecomparator, the default iseqwhen it is automatically generated, which can be edited manually. Currently, to view all the comparators that parrot supports, seeAppendix: Verification Method Set.# Sometimes we need to generate the parameters in real time.Take thehobby_suggestrequest insample.haras an example. Thetodayparameter of the interface needs the date of the execution time. The default value recorded by the recording is the static value. If we run it in the next day, it will not meet the requirements. At this point, you need to generate this parameter in real time.The way Parrot supports is:${{function(params)}}, where those functions are provided iniparrot.modules.helper, which can be used directly. SeeAppendix: Helper Method Set.Example:config:...variables:p1:ABCp2:123p3:${{today()}}request:method:GET...params:param1:${p1}param2:${p2}today:${p3}...# Sometimes there is a dependency on the response of the previous request.Take thehobby_detailrequest insample.haras an example. Itsnameargument is from the real-time valid return in thehobby_listrequest's response. If the data during recording is directly played back, it is likely that there is a failure sometimes.Parrot's solution is:extractthe specific key in the response of thehobby_listrequest, and use the${variable}format in thehobby_detailrequest.Example:hobby_list:config:...request:...response:extract:hobby:content.hobbies[0].name...hobby_detail:config:...request:...params:name:${hobby}...In iParrot 1.0.6 and later,parrot recordhas the-ae, --auto-extractparameter added.If this parameter is specified, parrot will automatically recognize the parameter dependency between interfaces during the parsing process.Theextractextraction and${variable}references are automatically completed when the use cases are generated.In view of the possibility of many formats in the actual scene, the 'automatic' identification may cause some accidental or omission, and it is recommended to perform artificial inspection and correction after its execution.Regarding the recording phase, the above scenarios should cover most of the use cases. If there are other unsupported questions, welcome feedback an issue:https://github.com/idle-man/iParrot/issues1.3.3 Template - Generate a standardized use case template when no files are recordedIn actual work, there may be cases where there is no HAR file, such as a new project or a new interface before going online.For users who have existing HAR files, you can skip this step.parrot1.1.0 and later provides thetemplatecommand to help you generate standardized use case templates, where you can manually edit your test cases.See section #1.2.4 for specific usage:parrot help templateThe generated use case structure is consistent with therecordingphase, including atest_suite, atest_case, atest_stepand aenvironment.Users can refer above template to write their own formatting use cases, which can also be used for subsequentplayback.1.3.4 Replace - Batch update generated use cases according to specified rulesFor use cases that have already been generated, we sometimes have a large number of update requirements, such as:Need to replace the ID in the argument with another oneNeed to replace a date parameter with a${{today()}}function callNeed to replace the host in the request with a new test addressNeed to replace the token in the request header with the${variable}variable referenceSome of the above updates can be done with the help of an IDE.For the user's convenient use,parrot1.1.0 and later versions provide thereplacecommand, which can be used to batch update the target use case set according to the rules specified by the user.See section #1.2.5 for specific usage:parrot help replaceFor example:parrot replace -s demo/test_suites/test.yml -t demoNew -r 'xxID=>abcd, 2019-01-01=>${{today()}}, host=>example.com'The above command will automatically traverse all the yml files in the specified test_suite and its included test_cases and test_steps,and match the contents ofconfig.variables,request,request.headers,request.cookiesblocks.The content before the '=>' symbol will be absolutely matched with the keys in the above use case block, and if it is missed, it will definitely match the values.If some key or value matches, the value will be replaced with the content after the '=>' symbol.If a replacement rule only needs to be valid for a particular interface, you can do this:parrot replace -s demo/test_suites/test.yml -t demoNew -r 'xxID=>abcd, apiA::2019-01-01=>${{today()}}'The above2019-01-01=>${{today()}}rule only works on the yml of the file name fuzzy matchedapiA.1.3.5 Replay - Execute use cases, verify result, generate reportAccording to the instructions in Section #1.2.3, we have a general understanding of the basic usage of theplaybackcommand. Now let's try to play back thedemo2recorded earlier.# A simple playback: -s & -t$ parrot playback -s demo2/test_suites -t demo2If it is successful, the process output information will be visible on the screen during the execution. After the execution is completed, you will see the generated test report in thedemo2directory:parrot_<timestamp>.html, which could be  viewed via PyCharm or browser.# About the running orderParrot execute the test in the order of cases and steps defined intest_suite.yaml /test_case.yaml, currently only supports serial execution mode.When the use case is automatically generated, the order of the steps defaults to the order of appearance in the recorded sample, which can be edited manually.The detailed execution process:test_suite1
 |-> suite1.setup
 |-> test_case1
   |-> case1.setup
   |-> test_step1
     |-> step1.setup
     |-> request
     |-> validation
     |-> extract
     |-> step1.teardown
   |-> test_step2
     ...
   |-> case1.teardown
 |-> test_case2
   ...
 |-> suite1.teardown
test_suite2
  ...# About the running intervalThe value ofintervalargument is firstly used, otherwise the valuetime.startin step defination.If the playback pass parameter specifies theinterval, it will execute according to the interval (in milliseconds), for example:$ parrot playback -s demo2/test_suites -t demo2 -i 100Otherwise, iftime.startis defined in the request of step (the recording phase will be automatically recorded), the default is to execute according to the interval oftime.startof each step.When the use case is automatically generated, the actual execution time would be recorded astime.startin the step defination.# About the running validationAs mentioned in the recording phase, each request generates some validations, which contain the expected result.In the process of request playback, parrot can get the actual result in real time, so you can check the result in real time, and then check whether the value of eachcheckobject conforms to thecomparatorrule. If there is one failure, the entire step fails.After a single step fails, the current Parrot does not terminate the execution of the playback by default, but the user can perform some intervention by running the parameters:--fail_stop: If specified, the operation will be terminated after a step verification fails--fail_retry_times: The number of retries after a step failed, 0 as default--fail_retry_interval: retry interval after a step failure1.3.6 Adapting multiple sets of environmentsParrot draws on Postman's environmental management mechanism.The environment configuration is automatically reserved during recording and can be edited manually.Take the recorded demo2 in section 1.3.2 as an example. The automatically generated environment is configured asdemo2/environments/sample_env.yml. The default generated content is reserved for several sets of environment identifiers and the content is empty:development: {}
global: {}
production: {}
test: {}At the same time, theconfigpart of the automatically generated test_suites, test_cases and test_steps is referenced byimportandenvironment: global, which can be edited manually.globalis globally shared, the rest are independent, and the new environment identifier can be customized.Suppose we have deployed multiple sets ofParrotSampleapplications, which represent different operating environments, separated by port number:development: 8081
test: 8082
production: 8080We hope that the same set of test cases can be reused in different environments. We can do like below:Firstly, editdemo2/environments/sample_env.yml:development:
  host: 10.10.100.100:8081
global:
  host: 10.10.100.100:8080
production:
  host: 10.10.100.100:8080
test:
  host: 10.10.100.100:8082Then, manually replace all the values ​​of thehostin all generated test_steps ymls with the${host}variable reference.Multiple sets of environment switching during playbackAs mentioned in Section 1.2.3, theparrot playbackcommand provides the-env, --environmentparameter, which specifies the selected environment identifier at execution time.$ parrot playback -s demo2/test_suites -t demo2 -env developmentCurrently, the environment reference is included in the config of test_suites/test_cases/test_steps, and theplaybackparameter can also be specified. The load priority is:parameter > test_suite.config > test_case.config > test_step.config2. Design ideas: starting from the original meaning of software testing2.1 How to define software testingClassic definition of software testing:The process of using amanualorautomatedmeans to run or measure a software system, the purpose of which is to verify that it meetsspecified requirementsor to clarify the difference betweenexpectedandactualresults.--Software engineering terminology from IEEE in 1983A simplified definition:The process of running a system or application in accordance with defined requirements/steps, obtainingactual result, and comparing with theexpected result.2.2 How to do software testingLet's take the use case template of the ZenTao project management platform as an example. Everyone's daily use case design is basically similar, see the figure below:If we want to extract key elements from it, based on the definition of software testing, we can easily find the following content:StepsExpectof eachStepSometimes, in order to ensure complete execution, it is possible to addPrerequisiteOther elements are usually designed to make use cases easier to manage. Think about it, do we usually do like this?2.3 How to automate software testingWe use HTTP(S) interface test as an example to automate. There are usually two ways:2.3.1 Use testing tools, such as: POSTMAN, JMETERTake Postman as an example. The implementation is roughly as shown in the figure below:Advantage of this approach:Collection > Folder > Request, layered design makes the use case organization clearerWith the environment variable management mechanism, it is convenient for common variable extraction and multiple sets of environment switching.Pre-request ScriptandTestssupport pre- and post-actions, whileTestsprovides a richer validation methods that reduces the coding threshold.Insufficient in this way:The cost of creation is high, and each new Request requires a certain amount of effort to complete the addition, especially theQuery ParamsandTestssections. For dependencies between interfaces, it is necessary to writePre-request Scriptmore cumbersomely.The combination and order adjustment between Requests is not convenient enough, especially for Case or Suite with actual business logic.2.3.2 Write your own automation framework, such as: Python+requests+unittestThe rough implementation, as in the example below:# -*- coding: utf-8 -*-

import requests
import unittest


class TestHttpBin(unittest.TestCase):
    def setUp(self) -> None:
        """do something here"""

    def test_get(self):
        url = 'http://httpbin.org/'
        params = {
            'p1': 'v1',
            'p2': 'v2'
        }
        response = requests.get(url=url, params=params)
        self.assertEqual(response.status_code, 200)

    def test_post(self):
        """do something like test_get"""

    def tearDown(self) -> None:
        """do something here"""


if __name__ == '__main__':
    unittest.main()Advantage of this approach:Flexible use case stratification, data-driven, let the use cases be arranged according to their own wishes.requestsmodule encapsulates the underlying capabilities, we only need to write business logic code.unittestsupports pre- and post- actions, while providing a richer verification methods and lowering the coding threshold.Insufficient in this way:The cost of creation/maintenance is high, and each new Request requires a certain amount of effort to complete the coding, especially the more assertions.There are certain technical thresholds for the design and writing of the framework, especially to ensure sufficient ease of use and versatility. For the dependencies between interfaces, the corresponding process variable transfer mechanism needs to be designed.2.4 Is there a more convenient way to automate?Comprehensive #2.3 chapter two kinds of automation methods, a lot of workload is reflected in:A large number of Request/TestCase definitions, especially those with more parameters.A large number of assertion method definitions, different Request verification points have differences.Scenes that depend on other interfaces require more tedious processing of parameter passing."Lazy" is the first driving force of the technological advancement.The design idea of ​​theparrottool is to solve the above problems, greatly improve the efficiency of automatic realization, and make automation easier.A large number of Request/TestCase definitions can be implemented simply and quickly byrecording.Throughplaybackmode, it can support the regular execution of automated use cases, and help you solve problems such as interface dependencies.About verification, based on the recorded Request's Response, automatically generate some regular assertions and support secondary editing.Compare with the definition of software testing:Recording: Get/Define specified requirement andexpected resultPlayback: Perform the recorded script to get theactual resultVerify: Compare theexpectedandactualresultsTraffic playbackis a way to automate the realization ofthe original definition of software testing.The design of this project is based on above idea to automate the interface testing.3. Source Code3.1 GitHubThis project:https://github.com/idle-man/iParrotIts sample project:https://github.com/idle-man/ParrotSampleAll of them contain a detailed README for your reference.If you have any questions or suggestions, please feel free to submit an issue within the project.3.2 Framework Structureiparrot/
  ├── modules
  │    ├── helper.py    : A collection of commonly used methods in which the Function can be used in other modules, also supporting the use of ${{function(params)}} in the cases.
  │    ├── request.py   : Execute HTTP(S) request based on `requests` and get the result
  │    ├── validator.py : The verification engine for request's response information, which supports multiple verification rules, as detailed in Validator.UNIFORM_COMPARATOR
  │    ├── logger.py    : Formatted log printing, support for output to screen or log files
  │    └── reportor.py  : Standardized report printing, support for views of summary results and use case execution details
  ├── extension
  │    └── helper.py    : A collection of common methods that can be customized by the user, where the Function supports use as ${{function(params)}} in the cases
  ├── parser.py : Parse the source file, and automatically generate formatted use cases; parse the specified use case set, load into memory
  ├── player.py : Play back the specified set of use cases, execute them in levels, and finally generate a test report
  └── parrot.py : The main script, you can run `python parrot.py help` to see the specific usage4. Appendix4.1 Use case structureExample:environmentglobal:{}production:{}development:{}test:{}test_stepconfig:environment:<environment flag>import:<environment file>name:step namevariables:p1:ABCp2:123request:method:POSTprotocol:httphost:x.x.x.x:8000url:/path/of/apiparams:{}data:param1:${p1}param2:${p2}headers:Content-Type:application/json; charset=UTF-8cookies:{}time.start:1568757525027response:extract:{}setup_hooks:[]teardown_hooks:[]validations:-eq:status.code:200-exists:headers.token-is_json:content-eq:content.code:100test_caseconfig:environment:<environment flag>import:<environment file>name:case namevariables:{}setup_hooks:[]teardown_hooks:[]test_steps:-<fullname of step1>-<fullname of step2>test_suiteconfig:environment:<evnironment flag>import:<environment file>name:suite namevariables:{}setup_hooks:[]teardown_hooks:[]test_cases:-<fullname of case1>-<fullname of case2>4.2 Verification method setThese methods can be used in validations in specific test_steps, for example:validations:-eq:status.code:200-is_json:content-not_null:headers.token-contains:content.message:succCommonly used verification methods:eq(equals):Example:1 eq 1,'a' eq 'a',[1, 2] eq [1, 2],{'a': 1 } eq {'a': 1},status.code eq 200Usage:validations:
 - eq:
     status.code: 200
 - eq:
     headers.Content-Type: application/json;charset=UTF-8
 - eq:
     content.data[0].id: 1000Similar methods:neq,lt,gt,le,gelen_eq(length equals):Example:'ab' len_eq 2,[1, 2] len_eq 2,{'a': 1} len_eq 1Usage:validations:
 - len_eq:
     headers.token: 32
 - eq:
     content.datalist: 3Similar methods:len_neq,len_lt,len_gttime_le(time spent less than or equals):Example:request 'time.spent' time_le 200 (unit is ms)Usage:validations:
 - time_le:
     time.spent: 200Similar methods:time_lt,time_gt,time_gecontains:Example:'abc' contain 'ab', ['a', 'b'] contain 'a', {'a': 1, 'b': 2} contain {'a': 1}Usage:validations:
 - contains:
     headers.Content-Type: application/json
 - contains:
     content.message: okSimilar methods:not_containsin:Example:'a' in 'ab','a' in ['a', 'b'],'a' in {'a': 1, 'b': 2}Usage:validations:
 - in:
     status.code: [200, 302]Similar methods:not_inis_false:Example:0 is_false,'' is_false,[] is_false,{} is_falseUsage:validations:
 - is_false:
     content.datalist
 - is_json:
     content
 - is_instance:
     status.code: intSimilar methods:is_true,exists,is_instance,is_jsonre(regex):Example:'1900-01-01' re r'\d+-\d+-\d+'Usage:validations:
 - re:
     content.data[0].date: r"\d+-\d+-\d+"Similar methods:not_reMore methods and instructions can be found in the following way:importjsonfromiparrot.modules.validatorimportValidatorprint(json.dumps(Validator.UNIFORM_COMPARATOR,indent=4))4.3 Helper method setThese methods can be applied to the inside of test_step / test_case / test_suite in the form${{function(params)}}, such as:setup_hooksteardown_hooksvariablestoday(form='%Y-%m-%d'): Get today's date

days_ago(days=0, form='%Y-%m-%d'): Get the date a few days ago

days_later(days=0, form='%Y-%m-%d'): Get the date a few days later

now(form='%Y-%m-%d %H:%M:%S'): Get the current time, accurate to the second

now_ms(form='%Y-%m-%d %H:%M:%S'): Get the current time, accurate to the micro second

now_timestamp(): Get the current timestamp, accurate to the second

now_timestamp_ms(): Get the current timestamp, accurate to the micro second

hours_ago(hours=0, form='%Y-%m-%d %H:%M:%S'): Get the time a few hours ago, accurate to the second

hours_later(hours=0, form='%Y-%m-%d %H:%M:%S'): Get the time a few hours later, accurate to the second

get_file_name(file, ext=0): Intercept the file name of the specified file, no suffix by default

get_file_path(file): Intercept the path of the specified file

make_dir(directory): Generate the specified directory

copy_file(source, target): Copy the specified file to the target path

get_random_integer(length=10, head=None, tail=None): Generate random number, with specified length, head, tail

get_random_string(length=10, simple=1, head=None, tail=None): Generate random string, with specified length, head, tail

get_random_phone(head=None, tail=None): Generate random Chinese phone number, with specified length, head, tailIf the above helper methods do not meet your needs, you can use the following method:Define your own module or pip install specified module in your local environment.Addimport xxxorfrom xxx import yyyto the desired step / case / suitesetup_hooks,then you could use the${{function(params)}}format to call the method you want.Any questions, you can feedback an issue:https://github.com/idle-man/iParrot/issuesMore general helper methods, welcome to contribute code or issues, thanks.5. External reference, thanks5.1Postman5.1.1 Environments managementThe mechanism is referenced in theenvironmentof the Parrot use case structure.A project can be configured with multiple sets of environments to hold some common environment variables.

Variable names are consistent between different environments, and values ​​can vary.

In the use case, you can refer to the variable by means of ${variable}, reducing manual modification.

The switching of the operating environment can be specified in the playback phase by the -env/--environment parameter.5.1.2 Use case layering modeCollection => test_suiteFolder => test_caseRequest => test_step5.1.3 Pre and post actionsPre-request Script => setup_hooksTests => teardown_hooks & validations5.2HttpRunner5.2.1HAR2CaseThe files processed by Parrot in the first phase are Charles trace and Fiddler txt. The format is quite different, and the parsing of plain text is cumbersome.Later, in the course of HttpRunner's ideas, I used HAR to reconstruct the record part. At the same time, I made some changes in the parameters.Inspired by HttpRunner's ideas, the record part is rebuilt, and some paramters are updated.For details, to seeparrot help recordandiparrot.parser5.2.2 Use case layering modeThe use case layering mode of HttpRunner, TestSuite>TestCase>TestStep, is clear and a good reference.When Parrot automatically generates use cases, it directly implements the layering mode on the directory structure and changes the specific use case structure.5.2.3 setup hooks & teardown hooksParrot reuses this naming scheme, which supportsset variable,call function,exec code.5.2.4 extract variableParrot in the first phase uses the mode ofstoreandreplace, which is intended to keep all changes in a configuration file, and does not invade the use case at all.In actual use, it is found that the usability is not good and the configuration is slightly cumbersome.Refer to HttpRunner, return the initiative to the user, and the variable can be extracted according toextractdefination and used as${variable}.5.2.5 comparatorThe first version of Parrot diffs results refer to a  configuration file, only supportseqand simplere, and the method set is limited.Now refer to the HttpRunner, automatically generateeqcomparator when recording, and support a variety of comparator customization.Comparators in Parrot combines with the common verification methods of HttpRunner and Postman, and a certain supplement.5.2.6 reportParrot's test report template directly reuses HttpRunner's report style.