diff --git a/.github/workflows/acceptance_tests_cpython.yml b/.github/workflows/acceptance_tests_cpython.yml index 3f82b6594eb..6cf3cb4275c 100644 --- a/.github/workflows/acceptance_tests_cpython.yml +++ b/.github/workflows/acceptance_tests_cpython.yml @@ -5,6 +5,7 @@ on: branches: - main - master + - v*-maintenance paths: - '.github/workflows/**' - 'src/**' @@ -18,30 +19,26 @@ jobs: fail-fast: false matrix: os: [ 'ubuntu-latest', 'windows-latest' ] - python-version: [ '3.6', '3.7', '3.8', '3.9', 'pypy3' ] + python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', 'pypy-3.10' ] include: - os: ubuntu-latest set_display: export DISPLAY=:99; Xvfb :99 -screen 0 1024x768x24 -ac -noreset & sleep 3 - os: windows-latest set_codepage: chcp 850 - - os: windows-latest - python-version: '3.9' - set_codepage: chcp 850 - atest_args: --exclude require-lxml --exclude require-screenshot exclude: - os: windows-latest - python-version: 'pypy3' + python-version: 'pypy-3.10' runs-on: ${{ matrix.os }} name: Python ${{ matrix.python-version }} on ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup python for starting the tests - uses: actions/setup-python@v3.1.2 + uses: actions/setup-python@v5.4.0 with: - python-version: 3.6 + python-version: '3.13' architecture: 'x64' - name: Get test starter Python at Windows @@ -53,7 +50,7 @@ jobs: if: runner.os != 'Windows' - name: Setup python ${{ matrix.python-version }} for running the tests - uses: actions/setup-python@v3.1.2 + uses: actions/setup-python@v5.4.0 with: python-version: ${{ matrix.python-version }} architecture: 'x64' @@ -66,22 +63,16 @@ jobs: run: echo "BASE_PYTHON=$(which python)" >> $GITHUB_ENV if: runner.os != 'Windows' - - name: Install Report handling tools to Windows - run: | - choco install curl -y --no-progress - choco install zip -y --no-progress - if: runner.os == 'Windows' - - name: Install Ubuntu PyPy dependencies run: | sudo apt-get update sudo apt-get -y -q install libxslt-dev libxml2-dev if: contains(matrix.python-version, 'pypy') && contains(matrix.os, 'ubuntu') - - name: Install screen and report handling tools, and other required libraries to Linux + - name: Install screen and other required libraries to Linux run: | sudo apt-get update - sudo apt-get -y -q install xvfb scrot zip curl libxml2-dev libxslt1-dev + sudo apt-get -y -q install xvfb scrot libxml2-dev libxslt1-dev if: contains(matrix.os, 'ubuntu') - name: Run acceptance tests @@ -92,52 +83,45 @@ jobs: ${{ matrix.set_display }} ${{ env.ATEST_PYTHON }} atest/run.py --interpreter ${{ env.BASE_PYTHON }} --exclude no-ci ${{ matrix.atest_args }} atest/robot - - name: Delete output.xml (on Win) - run: | - Get-ChildItem atest/results -Include output.xml -Recurse | Remove-Item - if: always() && runner.os == 'Windows' - - - name: Delete output.xml (on Unix-like) - run: | - find atest/results -type f -name 'output.xml' -exec rm {} + - if: always() && runner.os != 'Windows' - - name: Archive acceptances test results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: at-results-${{ matrix.python-version }}-${{ matrix.os }} path: atest/results if: always() && job.status == 'failure' - - name: Upload results on *nix - run: | - echo '' > atest/results/index.html - zip -r -j site.zip atest/results > no_output 2>&1 - curl -s -H "Content-Type: application/zip" -H "Authorization: Bearer ${{ secrets.NETLIFY_TOKEN }}" --data-binary "@site.zip" https://api.netlify.com/api/v1/sites > response.json - echo "REPORT_URL=$(cat response.json|python -c "import sys, json; print('https://' + json.load(sys.stdin)['subdomain'] + '.netlify.com')")" >> $GITHUB_ENV - echo "JOB_STATUS=$(python -c "print('${{ job.status }}'.lower())")" >> $GITHUB_ENV - if: always() && job.status == 'failure' && runner.os != 'Windows' - - - name: Upload results on Windows - run: | - echo '' > atest/results/index.html - zip -r -j site.zip atest/results > no_output 2>&1 - curl -s -H "Content-Type: application/zip" -H "Authorization: Bearer ${{ secrets.NETLIFY_TOKEN }}" --data-binary "@site.zip" https://api.netlify.com/api/v1/sites > response.json - echo "REPORT_URL=$(cat response.json|python -c "import sys, json; print('https://' + json.load(sys.stdin)['subdomain'] + '.netlify.com')")" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - echo "JOB_STATUS=$(python -c "print('${{ job.status }}'.lower())")" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - if: always() && job.status == 'failure' && runner.os == 'Windows' - - - uses: octokit/request-action@971ad48f9c40ed001c41c2671b1e6e8e8165d5af - name: Update status with Github Status API - id: update_status - with: - route: POST /repos/:repository/statuses/:sha - repository: ${{ github.repository }} - sha: ${{ github.sha }} - state: "${{env.JOB_STATUS}}" - target_url: "${{env.REPORT_URL}}" - description: "Link to test report." - context: at-results-${{ matrix.python-version }}-${{ matrix.os }} + - name: Install and run rflogs + if: failure() env: - GITHUB_TOKEN: ${{ secrets.STATUS_UPLOAD_TOKEN }} - if: always() && job.status == 'failure' + RFLOGS_API_KEY: ${{ secrets.RFLOGS_API_KEY }} + working-directory: atest/results + shell: python + run: | + import os + import glob + import subprocess + + # Install rflogs + subprocess.check_call(["pip", "install", "rflogs"]) + + # Find the first directory containing log.html + log_files = glob.glob("**/log.html", recursive=True) + if log_files: + result_dir = os.path.dirname(log_files[0]) + print(f"Result directory: {result_dir}") + + # Construct the rflogs command + cmd = [ + "rflogs", "upload", + "--tag", f"workflow:${{ github.workflow }}", + "--tag", f"os:${{ runner.os }}", + "--tag", f"python-version:${{ matrix.python-version }}", + "--tag", f"branch:${{ github.head_ref || github.ref_name }}", + result_dir + ] + + # Run rflogs upload + subprocess.check_call(cmd) + else: + print("No directory containing log.html found") + exit(1) diff --git a/.github/workflows/acceptance_tests_cpython_pr.yml b/.github/workflows/acceptance_tests_cpython_pr.yml index f3f304832f5..d876b2a959a 100644 --- a/.github/workflows/acceptance_tests_cpython_pr.yml +++ b/.github/workflows/acceptance_tests_cpython_pr.yml @@ -1,4 +1,4 @@ -name: Acceptance tests (CPython + PyPy) +name: Acceptance tests (CPython) on: pull_request: @@ -15,32 +15,23 @@ jobs: fail-fast: true matrix: os: [ 'ubuntu-latest', 'windows-latest' ] - python-version: [ '3.6', '3.9' ] + python-version: [ '3.8', '3.13' ] include: - os: ubuntu-latest set_display: export DISPLAY=:99; Xvfb :99 -screen 0 1024x768x24 -ac -noreset & sleep 3 - os: windows-latest set_codepage: chcp 850 - - os: windows-latest - python-version: '3.9' - set_codepage: chcp 850 - atest_args: --exclude require-lxml --exclude require-screenshot - exclude: - - os: windows-latest - python-version: 'pypy2' - - os: windows-latest - python-version: 'pypy3' runs-on: ${{ matrix.os }} name: Python ${{ matrix.python-version }} on ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup python for starting the tests - uses: actions/setup-python@v3.1.2 + uses: actions/setup-python@v5.4.0 with: - python-version: 3.6 + python-version: '3.13' architecture: 'x64' - name: Get test starter Python at Windows @@ -52,7 +43,7 @@ jobs: if: runner.os != 'Windows' - name: Setup python ${{ matrix.python-version }} for running the tests - uses: actions/setup-python@v3.1.2 + uses: actions/setup-python@v5.4.0 with: python-version: ${{ matrix.python-version }} architecture: 'x64' @@ -65,22 +56,10 @@ jobs: run: echo "BASE_PYTHON=$(which python)" >> $GITHUB_ENV if: runner.os != 'Windows' - - name: Install Report handling tools to Windows - run: | - choco install curl -y --no-progress - choco install zip -y --no-progress - if: runner.os == 'Windows' - - - name: Install Ubuntu PyPy dependencies - run: | - sudo apt-get update - sudo apt-get -y -q install libxslt-dev libxml2-dev - if: contains(matrix.python-version, 'pypy') && contains(matrix.os, 'ubuntu') - - - name: Install screen and report handling tools, and other required libraries to Linux + - name: Install screen and other required libraries to Linux run: | sudo apt-get update - sudo apt-get -y -q install xvfb scrot zip curl libxml2-dev libxslt1-dev + sudo apt-get -y -q install xvfb scrot libxml2-dev libxslt1-dev if: contains(matrix.os, 'ubuntu') - name: Run acceptance tests @@ -91,52 +70,45 @@ jobs: ${{ matrix.set_display }} ${{ env.ATEST_PYTHON }} atest/run.py --interpreter ${{ env.BASE_PYTHON }} --exclude no-ci ${{ matrix.atest_args }} atest/robot - - name: Delete output.xml (on Win) - run: | - Get-ChildItem atest/results -Include output.xml -Recurse | Remove-Item - if: always() && runner.os == 'Windows' - - - name: Delete output.xml (on Unix-like) - run: | - find atest/results -type f -name 'output.xml' -exec rm {} + - if: always() && runner.os != 'Windows' - - name: Archive acceptances test results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: at-results-${{ matrix.python-version }}-${{ matrix.os }} path: atest/results if: always() && job.status == 'failure' - - name: Upload results on *nix - run: | - echo '' > atest/results/index.html - zip -r -j site.zip atest/results > no_output 2>&1 - curl -s -H "Content-Type: application/zip" -H "Authorization: Bearer ${{ secrets.NETLIFY_TOKEN }}" --data-binary "@site.zip" https://api.netlify.com/api/v1/sites > response.json - echo "REPORT_URL=$(cat response.json|python -c "import sys, json; print('https://' + json.load(sys.stdin)['subdomain'] + '.netlify.com')")" >> $GITHUB_ENV - echo "JOB_STATUS=$(python -c "print('${{ job.status }}'.lower())")" >> $GITHUB_ENV - if: always() && job.status == 'failure' && runner.os != 'Windows' - - - name: Upload results on Windows - run: | - echo '' > atest/results/index.html - zip -r -j site.zip atest/results > no_output 2>&1 - curl -s -H "Content-Type: application/zip" -H "Authorization: Bearer ${{ secrets.NETLIFY_TOKEN }}" --data-binary "@site.zip" https://api.netlify.com/api/v1/sites > response.json - echo "REPORT_URL=$(cat response.json|python -c "import sys, json; print('https://' + json.load(sys.stdin)['subdomain'] + '.netlify.com')")" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - echo "JOB_STATUS=$(python -c "print('${{ job.status }}'.lower())")" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - if: always() && job.status == 'failure' && runner.os == 'Windows' - - - uses: octokit/request-action@971ad48f9c40ed001c41c2671b1e6e8e8165d5af - name: Update status with Github Status API - id: update_status - with: - route: POST /repos/:repository/statuses/:sha - repository: ${{ github.repository }} - sha: ${{ github.sha }} - state: "${{env.JOB_STATUS}}" - target_url: "${{env.REPORT_URL}}" - description: "Link to test report." - context: at-results-${{ matrix.python-version }}-${{ matrix.os }} + - name: Install and run rflogs + if: failure() env: - GITHUB_TOKEN: ${{ secrets.STATUS_UPLOAD_TOKEN }} - if: always() && job.status == 'failure' + RFLOGS_API_KEY: ${{ secrets.RFLOGS_API_KEY }} + working-directory: atest/results + shell: python + run: | + import os + import glob + import subprocess + + # Install rflogs + subprocess.check_call(["pip", "install", "rflogs"]) + + # Find the first directory containing log.html + log_files = glob.glob("**/log.html", recursive=True) + if log_files: + result_dir = os.path.dirname(log_files[0]) + print(f"Result directory: {result_dir}") + + # Construct the rflogs command + cmd = [ + "rflogs", "upload", + "--tag", f"workflow:${{ github.workflow }}", + "--tag", f"os:${{ runner.os }}", + "--tag", f"python-version:${{ matrix.python-version }}", + "--tag", f"branch:${{ github.head_ref || github.ref_name }}", + result_dir + ] + + # Run rflogs upload + subprocess.check_call(cmd) + else: + print("No directory containing log.html found") + exit(1) diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml index ce04f907db5..ba6aab65ac0 100644 --- a/.github/workflows/unit_tests.yml +++ b/.github/workflows/unit_tests.yml @@ -5,6 +5,7 @@ on: branches: - main - master + - v*-maintenance paths: - '.github/workflows/**' - 'src/**' @@ -19,35 +20,24 @@ jobs: fail-fast: false matrix: os: [ 'ubuntu-latest', 'windows-latest' ] - python-version: [ '3.6', '3.7', '3.8', '3.9', 'pypy3' ] + python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', 'pypy-3.8' ] exclude: - os: windows-latest - python-version: 'pypy3' + python-version: 'pypy-3.8' runs-on: ${{ matrix.os }} name: Python ${{ matrix.python-version }} on ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup python ${{ matrix.python-version }} - uses: actions/setup-python@v3.1.2 + uses: actions/setup-python@v5.4.0 with: python-version: ${{ matrix.python-version }} architecture: 'x64' - - name: Run unit tests with coverage + - name: Run unit tests run: | - python -m pip install coverage python -m pip install -r utest/requirements.txt - python -m coverage run --branch utest/run.py -v - - - name: Prepare HTML/XML coverage report - run: | - python -m coverage xml -i - if: always() - - - uses: codecov/codecov-action@e3c560433a6cc60aec8812599b7844a7b4fa0d71 - with: - name: ${{ matrix.python-version }}-${{ matrix.os }} - if: always() + python utest/run.py -v diff --git a/.github/workflows/unit_tests_pr.yml b/.github/workflows/unit_tests_pr.yml index 0730dab205f..f712918e1c6 100644 --- a/.github/workflows/unit_tests_pr.yml +++ b/.github/workflows/unit_tests_pr.yml @@ -15,19 +15,16 @@ jobs: fail-fast: true matrix: os: [ 'ubuntu-latest', 'windows-latest' ] - python-version: [ '3.6', '3.9' ] - exclude: - - os: windows-latest - python-version: 'pypy3' + python-version: [ '3.8', '3.12' ] runs-on: ${{ matrix.os }} name: Python ${{ matrix.python-version }} on ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup python ${{ matrix.python-version }} - uses: actions/setup-python@v3.1.2 + uses: actions/setup-python@v5.4.0 with: python-version: ${{ matrix.python-version }} architecture: 'x64' diff --git a/.github/workflows/upload_test_reports.yml b/.github/workflows/upload_test_reports.yml deleted file mode 100644 index e05de8214c4..00000000000 --- a/.github/workflows/upload_test_reports.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: Upload test results - -on: [status] - -jobs: - upload_test_results: - runs-on: ubuntu-latest - name: Upload results from ${{ github.event.name }} - steps: - - run: echo ${{ github.event }} diff --git a/.github/workflows/web_tests.yml b/.github/workflows/web_tests.yml new file mode 100644 index 00000000000..8e7cc6f03c9 --- /dev/null +++ b/.github/workflows/web_tests.yml @@ -0,0 +1,30 @@ +name: Web tests with jest + +on: + push: + branches: + - main + - master + - v*-maintenance + + paths: + - '.github/workflows/**' + - 'src/web**' + - '!**/*.rst' + +jobs: + jest_tests: + + runs-on: 'ubuntu-latest' + + name: Jest tests for the web components + steps: + - uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "16" + - name: Run tests + working-directory: ./src/web + run: npm install && npm run test diff --git a/.gitignore b/.gitignore index 0f618b1148a..880555b6da1 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,7 @@ __pycache__ .classpath .settings .jython_cache +.mypy_cache/ +node_modules +.cache/ +.parcel-cache/ diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000000..bd5c3733053 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,25 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3" + +# Build documentation in the doc/api directory with Sphinx +sphinx: + configuration: doc/api/conf.py + +# If using Sphinx, optionally build your docs in additional formats such as PDF +# formats: +# - pdf + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: doc/api/requirements.txt diff --git a/BUILD.rst b/BUILD.rst index 8776b2e5dd2..e1b1e395df3 100644 --- a/BUILD.rst +++ b/BUILD.rst @@ -66,10 +66,17 @@ Testing Make sure that adequate tests are executed before releases are created. See ``_ for details. +If output.xml `schema `_ has changed, remember to +run tests also with `full schema validation`__ enabled:: + + atest/run.py --schema-validation + +__ https://github.com/robotframework/robotframework/tree/master/atest#schema-validation + Preparation ----------- -1. Check that you are on the master branch and have nothing left to commit, +1. Check that you are on the right branch and have nothing left to commit, pull, or push:: git branch @@ -86,13 +93,13 @@ Preparation VERSION= - For example, ``VERSION=3.0.1`` or ``VERSION=3.1a2``. + For example, ``VERSION=7.1.1`` or ``VERSION=7.2a2``. No ``v`` prefix! Release notes ------------- -1. Create personal `GitHub access token`__ to be able to access issue tracker - programmatically. The token needs only the `repo/public_repo` scope. +1. Create a personal `GitHub access token`__ to be able to access issue tracker + programmatically. The token needs only the ``repo/public_repo`` scope. 2. Set GitHub user information into shell variables to ease running the ``invoke release-notes`` command in the next step:: @@ -112,7 +119,7 @@ Release notes `__. Omit the ``-w`` option if you just want to get release notes printed to the console, not written to a file. - When generating release notes for a preview release like ``3.0.2rc1``, + When generating release notes for a preview release like ``7.2rc1``, the list of issues is only going to contain issues with that label (e.g. ``rc1``) or with a label of an earlier preview release (e.g. ``alpha1``, ``beta2``). @@ -144,6 +151,24 @@ Release notes __ https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token + +Update libdoc generated files +----------------------------- + +Run + + invoke build-libdoc + +This step can be skipped if there are no changes to Libdoc. Prerequisites +are listed in ``_. + +This will regenerate the libdoc html template and update libdoc command line +with the latest supported lagnuages. + +Commit & push if there are changes any changes to either +`src/robot/htmldata/libdoc/libdoc.html` or `src/robot/libdocpkg/languages.py`. + + Set version ----------- @@ -182,27 +207,32 @@ Creating distributions invoke clean -3. Create and validate source distribution in zip format and - `wheel `_:: +4. Create and validate source distribution and `wheel `_:: - python setup.py sdist --formats zip bdist_wheel + python setup.py sdist bdist_wheel ls -l dist twine check dist/* Distributions can be tested locally if needed. -4. Upload distributions to PyPI:: +5. Upload distributions to PyPI:: twine upload dist/* -5. Verify that project pages at `PyPI +6. Verify that project pages at `PyPI `_ look good. -6. Test installation:: +7. Test installation:: pip install --pre --upgrade robotframework -7. Documentation +8. Documentation + + - For a reproducible build, set the ``SOURCE_DATE_EPOCH`` + environment variable to a constant value, corresponding to the + date in seconds since the Epoch (also known as Epoch time). For + more information regarding this environment variable, see + https://reproducible-builds.org/docs/source-date-epoch/. - Generate library documentation:: @@ -216,14 +246,14 @@ Creating distributions git checkout gh-pages invoke add-docs $VERSION --push - git checkout master + git checkout master # replace master with v*-maintenance if needed! Post actions ------------ 1. Back to master if needed:: - git checkout master + git checkout master # replace master with v*-maintenance if needed! 2. Set dev version based on the previous version:: diff --git a/INSTALL.rst b/INSTALL.rst index d31ab827367..84f997343e7 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -28,11 +28,13 @@ is having Python or its alternative implementation `PyPy `_ installed. Another recommended precondition is having the pip_ package manager available. -Robot Framework requires Python 3.6 or newer. If you need to use Python 2, +Robot Framework requires Python 3.8 or newer. The latest version that supports +Python 3.6 and 3.7 is `Robot Framework 6.1.1`__. If you need to use Python 2, `Jython `_ or `IronPython `_, you can use `Robot Framework 4.1.3`__. -__ https://github.com/robotframework/robotframework/tree/v4.1.3#readme +__ https://github.com/robotframework/robotframework/blob/v6.1.1/INSTALL.rst +__ https://github.com/robotframework/robotframework/blob/v4.1.3/INSTALL.rst Installing Python on Linux ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -45,10 +47,10 @@ Python version than the one provided by your distribution by default. To check what Python version you have installed, you can run `python --version` command in a terminal: -.. sourcecode:: bash +.. code:: bash $ python --version - Python 3.8.10 + Python 3.10.13 Notice that if your distribution provides also older Python 2, running `python` may use that. To use Python 3, you can use `python3` command or even more version @@ -56,12 +58,12 @@ specific command like `python3.8`. You need to use these version specific varian also if you have multiple Python 3 versions installed and need to pinpoint which one to use: -.. sourcecode:: bash +.. code:: bash - $ python3.9 --version - Python 3.9.10 - $ python3.10 --version - Python 3.10.2 + $ python3.11 --version + Python 3.11.7 + $ python3.12 --version + Python 3.12.1 Installing Robot Framework directly under the system provided Python has a risk that possible problems can affect the whole Python installation @@ -87,21 +89,21 @@ to select the `Add Python 3.x to PATH` checkbox on the first dialog. To make sure Python installation has been successful and Python has been added to `PATH`, you can open the command prompt and execute `python --version`: -.. sourcecode:: batch +.. code:: batch C:\>python --version - Python 3.9.4 + Python 3.10.9 -If you install multiple Python versions on Windows, the Python that is used +If you install multiple Python versions on Windows, the version that is used when you execute `python` is the one first in `PATH`. If you need to use others, the easiest way is using the `py launcher`__: -.. sourcecode:: batch +.. code:: batch C:\>py --version - Python 3.9.4 - C:\>py -3.10 --version - Python 3.10.2 + Python 3.10.9 + C:\>py -3.12 --version + Python 3.12.1 __ https://docs.python.org/3/using/windows.html __ https://docs.python.org/3/using/windows.html#windows-full @@ -198,21 +200,21 @@ To make sure you have pip available, you can run `pip --version` or equivalent. Examples on Linux: -.. sourcecode:: bash +.. code:: bash $ pip --version - pip 20.2 from ... (python 3.8) - $ python3.10 -m pip --version - pip 20.2 from ... (python 3.10) + pip 23.2.1 from ... (python 3.10) + $ python3.12 -m pip --version + pip 23.3.1 from ... (python 3.12) Examples on Windows: -.. sourcecode:: batch +.. code:: batch C:\> pip --version - pip 20.2.2 from ... (python 3.9) - C:\> py -m 3.10 -m pip --version - pip 20.2.1 from ... (python 3.10) + pip 23.2.1 from ... (python 3.10) + C:\> py -m 3.12 -m pip --version + pip 23.3.2 from ... (python 3.12) In the subsequent sections pip is always run using the `pip` command. You may need to use some of the other approaches explained above in your environment. @@ -227,7 +229,7 @@ shown below and pip_ documentation has more information and examples. __ PyPI_ -.. sourcecode:: bash +.. code:: bash # Install the latest version (does not upgrade) pip install robotframework @@ -239,10 +241,10 @@ __ PyPI_ pip install --upgrade --pre robotframework # Install a specific version - pip install robotframework==5.0 + pip install robotframework==7.0 # Install separately downloaded package (no network connection needed) - pip install robotframework-5.0-py3-none-any.whl + pip install robotframework-7.0-py3-none-any.whl # Install latest (possibly unreleased) code directly from GitHub pip install https://github.com/robotframework/robotframework/archive/master.zip @@ -257,13 +259,13 @@ Another installation alternative is getting Robot Framework source code and installing it using the provided `setup.py` script. This approach is recommended only if you do not have pip_ available for some reason. -You can get the source code by downloading a source distribution as a zip -package from PyPI_ and extracting it. An alternative is cloning the GitHub_ +You can get the source code by downloading a source distribution package +from PyPI_ and extracting it. An alternative is cloning the GitHub_ repository and checking out the needed release tag. Once you have the source code, you can install it with the following command: -.. sourcecode:: bash +.. code:: bash python setup.py install @@ -278,10 +280,10 @@ Verifying installation To make sure that the correct Robot Framework version has been installed, run the following command: -.. sourcecode:: bash +.. code:: bash $ robot --version - Robot Framework 5.0 (Python 3.8.10 on linux) + Robot Framework 7.0 (Python 3.10.3 on linux) If running these commands fails with a message saying that the command is not found or recognized, a good first step is double-checking the PATH_ @@ -292,13 +294,13 @@ running `robot` will execute the one first in PATH_. To select explicitly, you can run `python -m robot` and substitute `python` with the right Python version. -.. sourcecode:: bash +.. code:: bash - $ python3.10 -m robot --version - Robot Framework 5.0 (Python 3.10.2 on linux) + $ python3.12 -m robot --version + Robot Framework 7.0 (Python 3.12.1 on linux) - C:\>py -3.10 -m robot --version - Robot Framework 5.0 (Python 3.10.3 on win32) + C:\>py -3.11 -m robot --version + Robot Framework 7.0 (Python 3.11.7 on win32) Virtual environments -------------------- diff --git a/README.rst b/README.rst index eac7d8933f2..a18d3ee8120 100644 --- a/README.rst +++ b/README.rst @@ -22,7 +22,7 @@ http://robotframework.org. Robot Framework project is hosted on GitHub_ where you can find source code, an issue tracker, and some further documentation. Downloads are hosted on PyPI_. -Robot Framework development is sponsored by `Robot Framework Foundation +Robot Framework development is sponsored by non-profit `Robot Framework Foundation `_. If you are using the framework and benefiting from it, consider joining the foundation to help maintaining the framework and developing it further. @@ -49,10 +49,12 @@ you can simply run:: For more detailed installation instructions, including installing Python, see ``__. -Robot Framework requires Python 3.6 or newer and runs also on `PyPy `_. +Robot Framework requires Python 3.8 or newer and runs also on `PyPy `_. +The latest version that supports Python 3.6 and 3.7 is `Robot Framework 6.1.1`__. If you need to use Python 2, `Jython `_ or `IronPython `_, you can use `Robot Framework 4.1.3`__. +__ https://github.com/robotframework/robotframework/tree/v6.1.1#readme __ https://github.com/robotframework/robotframework/tree/v4.1.3#readme Example @@ -113,12 +115,10 @@ Documentation Support and Contact ------------------- -- `Slack `_ - (`click for invite `__) +- `Slack `_ - `Forum `_ - `robotframework-users `_ mailing list -- `@robotframework `_ on Twitter Contributing ------------ diff --git a/atest/README.rst b/atest/README.rst index 5856d5661b2..410ef5cdce8 100644 --- a/atest/README.rst +++ b/atest/README.rst @@ -137,7 +137,7 @@ require-yaml, require-lxml, require-screenshot Require specified Python module or some other external tool to be installed. Exclude like `--exclude require-lxml` if dependencies_ are not met. -require-windows, require-py3.8, ... +require-windows, require-py3.13, ... Tests that require certain operating system or Python interpreter. Excluded automatically outside these platforms. diff --git a/atest/genrunner.py b/atest/genrunner.py index f6e923448a4..c3c94af355d 100755 --- a/atest/genrunner.py +++ b/atest/genrunner.py @@ -46,11 +46,11 @@ def __init__(self, name, tags=None): name = SEPARATOR.split(line)[0].replace('*', '').replace(' ', '').upper() parsing_tests = name in ('TESTCASE', 'TESTCASES', 'TASK', 'TASKS') parsing_settings = name in ('SETTING', 'SETTINGS') - elif parsing_tests and not SEPARATOR.match(line): + elif parsing_tests and not SEPARATOR.match(line) and line[0] != '#': TESTS.append(TestCase(line.split(' ')[0])) elif parsing_tests and line.strip().startswith('[Tags]'): TESTS[-1].tags = line.split('[Tags]', 1)[1].split() - elif parsing_settings and line.startswith(('Force Tags', 'Default Tags')): + elif parsing_settings and line.startswith(('Force Tags', 'Default Tags', 'Test Tags')): name, value = line.split(' ', 1) SETTINGS.append((name, value.strip())) diff --git a/atest/interpreter.py b/atest/interpreter.py index b170e47caf4..0a65a0a42a0 100644 --- a/atest/interpreter.py +++ b/atest/interpreter.py @@ -1,8 +1,8 @@ import os -from pathlib import Path import re import subprocess import sys +from pathlib import Path ROBOT_DIR = Path(__file__).parent.parent / 'src/robot' @@ -33,7 +33,7 @@ def _get_name_and_version(self): stderr=subprocess.STDOUT, encoding='UTF-8') except (subprocess.CalledProcessError, FileNotFoundError) as err: - raise ValueError('Failed to get interpreter version: %s' % err) + raise ValueError(f'Failed to get interpreter version: {err}') name, version = output.split()[:2] name = name if 'PyPy' not in output else 'PyPy' version = re.match(r'\d+\.\d+\.\d+', version).group() @@ -50,13 +50,14 @@ def os(self): @property def output_name(self): - return '{i.name}-{i.version}-{i.os}'.format(i=self).replace(' ', '') + return f'{self.name}-{self.version}-{self.os}'.replace(' ', '') @property def excludes(self): if self.is_pypy: + yield 'no-pypy' yield 'require-lxml' - for require in [(3, 7), (3, 8), (3, 9), (3, 10)]: + for require in [(3, 9), (3, 10), (3, 14)]: if self.version_info < require: yield 'require-py%d.%d' % require if self.is_windows: @@ -104,5 +105,9 @@ def libdoc(self): def testdoc(self): return self.interpreter + [str(ROBOT_DIR / 'testdoc.py')] + @property + def underline(self): + return '-' * len(str(self)) + def __str__(self): return f'{self.name} {self.version} on {self.os}' diff --git a/atest/requirements.txt b/atest/requirements.txt index 5f0a324dfcf..aca4b5078bb 100644 --- a/atest/requirements.txt +++ b/atest/requirements.txt @@ -3,9 +3,10 @@ docutils >= 0.10 pygments - pyyaml +telnetlib-313-and-up; python_version >= '3.13' + # On Linux installing lxml with pip may require compilation and development # headers. Alternatively it can be installed using a package manager like # `sudo apt-get install python-lxml`. diff --git a/atest/resources/TestCheckerLibrary.py b/atest/resources/TestCheckerLibrary.py index 0cb3b1058cb..79351ea64b8 100644 --- a/atest/resources/TestCheckerLibrary.py +++ b/atest/resources/TestCheckerLibrary.py @@ -1,147 +1,235 @@ +import json import os import re +from datetime import datetime +from pathlib import Path +try: + from jsonschema import Draft202012Validator as JSONValidator +except ImportError: + JSONValidator = None from xmlschema import XMLSchema -from robot import utils from robot.api import logger -from robot.utils.asserts import assert_equal -from robot.result import (ExecutionResultBuilder, Result, ResultVisitor, - For, ForIteration, While, WhileIteration, Return, Break, Continue, - If, IfBranch, Try, TryBranch, Keyword, TestCase, TestSuite) -from robot.result.model import Body, Iterations from robot.libraries.BuiltIn import BuiltIn +from robot.libraries.Collections import Collections +from robot.result import ( + Break, Continue, Error, ExecutionResult, ExecutionResultBuilder, For, + ForIteration, Group, If, IfBranch, Keyword, Result, ResultVisitor, Return, + TestCase, TestSuite, Try, TryBranch, Var, While, WhileIteration +) +from robot.result.executionerrors import ExecutionErrors +from robot.result.model import Body, Iterations +from robot.utils.asserts import assert_equal +from robot.utils import eq, get_error_details, is_truthy, Matcher + + +class WithBodyTraversing: + body: Body + + def __getitem__(self, index): + if isinstance(index, str): + index = tuple(int(i) for i in index.split(',')) + if isinstance(index, (int, slice)): + return self.body[index] + if isinstance(index, tuple): + item = self + for i in index: + item = item.body[int(i)] + return item + raise TypeError(f"Invalid index {repr(index)}.") + + @property + def keywords(self): + return self.body.filter(keywords=True) + + @property + def messages(self): + return self.body.filter(messages=True) + + @property + def non_messages(self): + return self.body.filter(messages=False) + + +class ATestKeyword(Keyword, WithBodyTraversing): + pass + + +class ATestFor(For, WithBodyTraversing): + pass + + +class ATestWhile(While, WithBodyTraversing): + pass -class NoSlotsKeyword(Keyword): +class ATestGroup(Group, WithBodyTraversing): pass -class NoSlotsFor(For): +class ATestIf(If, WithBodyTraversing): pass -class NoSlotsWhile(While): +class ATestTry(Try, WithBodyTraversing): pass -class NoSlotsIf(If): +class ATestVar(Var, WithBodyTraversing): pass -class NoSlotsTry(Try): +class ATestReturn(Return, WithBodyTraversing): pass -class NoSlotsReturn(Return): +class ATestBreak(Break, WithBodyTraversing): pass -class NoSlotsBreak(Break): +class ATestContinue(Continue, WithBodyTraversing): pass -class NoSlotsContinue(Continue): +class ATestError(Error, WithBodyTraversing): pass -class NoSlotsBody(Body): - keyword_class = NoSlotsKeyword - for_class = NoSlotsFor - if_class = NoSlotsIf - try_class = NoSlotsTry - while_class = NoSlotsWhile - return_class = NoSlotsReturn - break_class = NoSlotsBreak - continue_class = NoSlotsContinue +class ATestBody(Body): + keyword_class = ATestKeyword + for_class = ATestFor + if_class = ATestIf + try_class = ATestTry + while_class = ATestWhile + group_class = ATestGroup + var_class = ATestVar + return_class = ATestReturn + break_class = ATestBreak + continue_class = ATestContinue + error_class = ATestError -class NoSlotsIfBranch(IfBranch): - body_class = NoSlotsBody +class ATestIfBranch(IfBranch, WithBodyTraversing): + body_class = ATestBody -class NoSlotsTryBranch(TryBranch): - body_class = NoSlotsBody +class ATestTryBranch(TryBranch, WithBodyTraversing): + body_class = ATestBody -class NoSlotsForIteration(ForIteration): - body_class = NoSlotsBody +class ATestForIteration(ForIteration, WithBodyTraversing): + body_class = ATestBody -class NoSlotsWhileIteration(WhileIteration): - body_class = NoSlotsBody +class ATestWhileIteration(WhileIteration, WithBodyTraversing): + body_class = ATestBody -class NoSlotsIterations(Iterations): - keyword_class = NoSlotsKeyword +class ATestIterations(Iterations, WithBodyTraversing): + keyword_class = ATestKeyword -NoSlotsKeyword.body_class = NoSlotsReturn.body_class = NoSlotsBreak.body_class \ - = NoSlotsContinue.body_class = NoSlotsBody -NoSlotsFor.iterations_class = NoSlotsWhile.iterations_class =NoSlotsIterations -NoSlotsFor.iteration_class = NoSlotsForIteration -NoSlotsWhile.iteration_class = NoSlotsWhileIteration -NoSlotsIf.branch_class = NoSlotsIfBranch -NoSlotsTry.branch_class = NoSlotsTryBranch +ATestKeyword.body_class = ATestVar.body_class = ATestReturn.body_class \ + = ATestBreak.body_class = ATestContinue.body_class \ + = ATestError.body_class = ATestGroup.body_class \ + = ATestBody +ATestFor.iterations_class = ATestWhile.iterations_class = ATestIterations +ATestFor.iteration_class = ATestForIteration +ATestWhile.iteration_class = ATestWhileIteration +ATestIf.branch_class = ATestIfBranch +ATestTry.branch_class = ATestTryBranch -class NoSlotsTestCase(TestCase): - fixture_class = NoSlotsKeyword - body_class = NoSlotsBody +class ATestTestCase(TestCase, WithBodyTraversing): + fixture_class = ATestKeyword + body_class = ATestBody -class NoSlotsTestSuite(TestSuite): - fixture_class = NoSlotsKeyword - test_class = NoSlotsTestCase +class ATestTestSuite(TestSuite): + fixture_class = ATestKeyword + test_class = ATestTestCase class TestCheckerLibrary: ROBOT_LIBRARY_SCOPE = 'GLOBAL' def __init__(self): - self.schema = XMLSchema('doc/schema/robot.xsd') + self.xml_schema = XMLSchema('doc/schema/result.xsd') + self.json_schema = self._load_json_schema() + + def _load_json_schema(self): + if not JSONValidator: + return None + with open('doc/schema/result.json', encoding='UTF-8') as f: + return JSONValidator(json.load(f)) - def process_output(self, path, validate=None): + def process_output(self, path: 'None|Path', validate: 'bool|None' = None): set_suite_variable = BuiltIn().set_suite_variable - if not path or path.upper() == 'NONE': + if path is None: set_suite_variable('$SUITE', None) logger.info("Not processing output.") return - path = path.replace('/', os.sep) if validate is None: - validate = os.getenv('ATEST_VALIDATE_OUTPUT', False) - if utils.is_truthy(validate): - self._validate_output(path) + validate = is_truthy(os.getenv('ATEST_VALIDATE_OUTPUT', False)) + if validate: + if path.suffix.lower() == '.json': + self.validate_json_output(path) + else: + self._validate_output(path) try: - logger.info("Processing output '%s'." % path) - result = Result(root_suite=NoSlotsTestSuite()) - ExecutionResultBuilder(path).build(result) + logger.info(f"Processing output '{path}'.") + if path.suffix.lower() == '.json': + result = self._build_result_from_json(path) + else: + result = self._build_result_from_xml(path) except: set_suite_variable('$SUITE', None) - msg, details = utils.get_error_details() + msg, details = get_error_details() logger.info(details) - raise RuntimeError('Processing output failed: %s' % msg) + raise RuntimeError(f'Processing output failed: {msg}') result.visit(ProcessResults()) set_suite_variable('$SUITE', result.suite) set_suite_variable('$STATISTICS', result.statistics) set_suite_variable('$ERRORS', result.errors) + def _build_result_from_xml(self, path): + result = Result(source=path, suite=ATestTestSuite()) + ExecutionResultBuilder(path).build(result) + return result + + def _build_result_from_json(self, path): + with open(path, encoding='UTF-8') as file: + data = json.load(file) + return Result(source=path, + suite=ATestTestSuite.from_dict(data['suite']), + errors=ExecutionErrors(data.get('errors')), + rpa=data.get('rpa'), + generator=data.get('generator'), + generation_time=datetime.fromisoformat(data['generated'])) + def _validate_output(self, path): - schema_version = self._get_schema_version(path) - if schema_version != self.schema.version: - raise AssertionError( - 'Incompatible schema versions. Schema has `version="%s"` ' - 'but output file has `schemaversion="%s"`.' - % (self.schema.version, schema_version) - ) - self.schema.validate(path) + version = self._get_schema_version(path) + if not version: + raise ValueError('Schema version not found from XML output.') + if version != self.xml_schema.version: + raise ValueError(f'Incompatible schema versions. ' + f'Schema has `version="{self.xml_schema.version}"` but ' + f'output file has `schemaversion="{version}"`.') + self.xml_schema.validate(path) def _get_schema_version(self, path): - with open(path, encoding='UTF-8') as f: - for line in f: + with open(path, encoding='UTF-8') as file: + for line in file: if line.startswith('= 0 + ... Length Should Be ${item.body} ${children} Check Keyword Data - [Arguments] ${kw} ${name} ${assign}= ${args}= ${status}=PASS ${tags}= ${type}=KEYWORD - Should Be Equal ${kw.name} ${name} + [Arguments] ${kw} ${name} ${assign}= ${args}= ${status}=PASS ${tags}= ${doc}=* ${message}=* ${type}=KEYWORD ${children}=-1 + Should Be Equal ${kw.full_name} ${name} Should Be Equal ${{', '.join($kw.assign)}} ${assign} Should Be Equal ${{', '.join($kw.args)}} ${args} Should Be Equal ${kw.status} ${status} Should Be Equal ${{', '.join($kw.tags)}} ${tags} + Should Match ${kw.doc} ${doc} + Should Match ${kw.message} ${message} Should Be Equal ${kw.type} ${type} + IF ${children} >= 0 + ... Length Should Be ${kw.body} ${children} + +Check TRY Data + [Arguments] ${try} ${patterns}= ${pattern_type}=${None} ${assign}=${None} ${status}=PASS + Should Be Equal ${try.type} TRY + Should Be Equal ${{', '.join($try.patterns)}} ${patterns} + Should Be Equal ${try.pattern_type} ${pattern_type} + Should Be Equal ${try.assign} ${assign} + Should Be Equal ${try.status} ${status} Test And All Keywords Should Have Passed - [Arguments] ${name}=${TESTNAME} ${allow not run}=False + [Arguments] ${name}=${TESTNAME} ${allow not run}=False ${allowed failure}= ${tc} = Check Test Case ${name} - All Keywords Should Have Passed ${tc} ${allow not run} + All Keywords Should Have Passed ${tc} ${allow not run} ${allowed failure} All Keywords Should Have Passed - [Arguments] ${tc_or_kw} ${allow not run}=False - IF hasattr($tc_or_kw, 'kws') - FOR ${index} ${kw} IN ENUMERATE @{tc_or_kw.kws} - IF ${allow not run} and (${index} > 0 or $kw.type in ['IF', 'ELSE', 'EXCEPT', 'BREAK']) - Should Be True $kw.status in ['PASS', 'NOT RUN'] - ELSE - Log ${kw.type} - Should Be Equal ${kw.status} PASS - END - All Keywords Should Have Passed ${kw} ${allow not run} + [Arguments] ${tc_or_kw} ${allow not run}=False ${allowed failure}= + FOR ${index} ${item} IN ENUMERATE @{tc_or_kw.body.filter(messages=False)} + IF $item.failed and not ($item.message == $allowed_failure) + Fail ${item.type} failed: ${item.message} + ELSE IF $item.not_run and not $allow_not_run + Fail ${item.type} was not run. + ELSE IF $item.skipped + Fail ${item.type} was skipped. + ELSE IF $item.passed and $item.message + Fail ${item.type} has unexpected message: ${item.message} END + All Keywords Should Have Passed ${item} ${allow not run} ${allowed failure} END Get Output File [Arguments] ${path} [Documentation] Output encoding avare helper - ${encoding} = Set Variable If r'${path}' in [r'${STDERR FILE}',r'${STDOUT FILE}'] SYSTEM UTF-8 + ${encoding} = Set Variable If r'${path}' in [r'${STDERR FILE}', r'${STDOUT FILE}'] SYSTEM UTF-8 ${file} = Get File ${path} ${encoding} - [Return] ${file} + RETURN ${file} File Should Contain [Arguments] ${path} @{expected} ${count}=None @@ -254,15 +283,15 @@ Stdout Should Contain Regexp Get Syslog ${file} = Get Output File ${SYSLOG_FILE} - [Return] ${file} + RETURN ${file} Get Stderr ${file} = Get Output File ${STDERR_FILE} - [Return] ${file} + RETURN ${file} Get Stdout ${file} = Get Output File ${STDOUT_FILE} - [Return] ${file} + RETURN ${file} Syslog Should Contain Match [Arguments] @{expected} @@ -294,19 +323,34 @@ Check Names Should Be Equal ${item.longname} ${longprefix}${name} Timestamp Should Be Valid - [Arguments] ${time} - Log ${time} - Should Not Be Equal ${time} ${None} - Should Match Regexp ${time} ^20\\d{6} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}$ Not valid timestamp + [Arguments] ${timestamp} + Should Be True isinstance($timestamp, datetime.datetime) and $timestamp.year > 2000 + +Timestamp Should Be + [Arguments] ${timestamp} ${expected} + IF $expected is not None + ${expected} = Evaluate datetime.datetime.fromisoformat('${expected}') + END + Should Be Equal ${timestamp} ${expected} Elapsed Time Should Be Valid - [Arguments] ${time} - Log ${time} - Should Be True isinstance($time, int) Not valid elapsed time: ${time} - # On CI elapsed time has sometimes been negative. We cannot control system time there, - # so better to log a warning than fail the test in that case. - Run Keyword If $time < 0 - ... Log Negative elapsed time '${time}'. Someone messing with system time? WARN + [Arguments] ${elapsed} ${minimum}=0 ${maximum}=${{sys.maxsize}} + Should Be True isinstance($elapsed, datetime.timedelta) + Should Be True $elapsed.total_seconds() >= ${minimum} + Should Be True $elapsed.total_seconds() <= ${maximum} + +Elapsed Time Should Be + [Arguments] ${elapsed} ${expected} + IF isinstance($expected, str) + ${expected} = Evaluate ${expected} + END + Should Be Equal As Numbers ${elapsed.total_seconds()} ${expected} + +Times Should Be + [Arguments] ${item} ${start} ${end} ${elapsed} + Timestamp Should Be ${item.start_time} ${start} + Timestamp Should Be ${item.end_time} ${end} + Elapsed Time Should Be ${item.elapsed_time} ${elapsed} Previous test should have passed [Arguments] ${name} @@ -316,22 +360,22 @@ Previous test should have passed Get Stat Nodes [Arguments] ${type} ${output}=${OUTFILE} ${nodes} = Get Elements ${output} statistics/${type}/stat - [Return] ${nodes} + RETURN ${nodes} Get Tag Stat Nodes [Arguments] ${output}=${OUTFILE} ${nodes} = Get Stat Nodes tag ${output} - [Return] ${nodes} + RETURN ${nodes} Get Total Stat Nodes [Arguments] ${output}=${OUTFILE} ${nodes} = Get Stat Nodes total ${output} - [Return] ${nodes} + RETURN ${nodes} Get Suite Stat Nodes [Arguments] ${output}=${OUTFILE} ${nodes} = Get Stat Nodes suite ${output} - [Return] ${nodes} + RETURN ${nodes} Tag Statistics Should Be [Arguments] ${tag} ${pass} ${fail} @@ -349,7 +393,7 @@ Reset PYTHONPATH Error in file [Arguments] ${index} ${path} ${lineno} @{message} ${traceback}= - ... ${stacktrace}= ${pattern}=True + ... ${stacktrace}= ${pattern}=True ${level}=ERROR ${path} = Join Path ${DATADIR} ${path} ${message} = Catenate @{message} ${error} = Set Variable Error in file '${path}' on line ${lineno}: ${message} @@ -359,7 +403,7 @@ Error in file ${error} = Set Variable If $stacktrace ... ${error}\n*${stacktrace}* ... ${error} - Check Log Message ${ERRORS}[${index}] ${error} level=ERROR pattern=${pattern} + Check Log Message ${ERRORS}[${index}] ${error} level=${level} pattern=${pattern} Error in library [Arguments] ${name} @{message} ${pattern}=False ${index}=0 @@ -375,3 +419,14 @@ Setup Should Not Be Defined Teardown Should Not Be Defined [Arguments] ${model_object} Should Not Be True ${model_object.teardown} + +Traceback Should Be + [Arguments] ${msg} @{entries} ${error} + ${exp} = Set Variable Traceback (most recent call last): + FOR ${path} ${func} ${text} IN @{entries} + ${path} = Normalize Path ${DATADIR}/${path} + ${exp} = Set Variable ${exp}\n${SPACE*2}File "${path}", line *, in ${func}\n${SPACE*4}${text} + END + # Remove '~~~^^^' lines. + ${msg.message} = Evaluate '\\n'.join(line for line in $msg.message.splitlines() if line.strip('~^ ') or not line) + Check Log Message ${msg} ${exp}\n${error} DEBUG pattern=True traceback=True diff --git a/atest/resources/atest_variables.py b/atest/resources/atest_variables.py index 449bb457c73..f0eeeb2cfb6 100644 --- a/atest/resources/atest_variables.py +++ b/atest/resources/atest_variables.py @@ -1,24 +1,29 @@ -from os.path import abspath, dirname, join, normpath import locale import os +import sys import subprocess +from datetime import datetime, timedelta +from os.path import abspath, dirname, join, normpath import robot __all__ = ['ROBOTPATH', 'ROBOT_VERSION', 'DATADIR', 'SYSTEM_ENCODING', - 'CONSOLE_ENCODING'] + 'CONSOLE_ENCODING', 'datetime', 'timedelta'] ROBOTPATH = dirname(abspath(robot.__file__)) ROBOT_VERSION = robot.version.get_version() DATADIR = normpath(join(dirname(abspath(__file__)), '..', 'testdata')) -SYSTEM_ENCODING = locale.getpreferredencoding(False) +if sys.version_info >= (3, 11): + SYSTEM_ENCODING = locale.getencoding() +else: + SYSTEM_ENCODING = locale.getpreferredencoding(False) # Python 3.6+ uses UTF-8 internally on Windows. We want real console encoding. if os.name == 'nt': output = subprocess.check_output('chcp', shell=True, encoding='ASCII', errors='ignore') CONSOLE_ENCODING = 'cp' + output.split()[-1] else: - CONSOLE_ENCODING = locale.getdefaultlocale()[-1] + CONSOLE_ENCODING = locale.getlocale()[-1] diff --git a/atest/resources/rebot_resource.robot b/atest/resources/rebot_resource.robot index 5faa9d5d468..83291b2cbd5 100644 --- a/atest/resources/rebot_resource.robot +++ b/atest/resources/rebot_resource.robot @@ -1,25 +1,19 @@ -*** Setting *** +*** Settings *** Resource atest_resource.robot -*** Variable *** +*** Variables *** ${ORIG_START} Set in Create Output With Robot ${ORIG_END} -- ;; -- ${ORIG_ELAPSED} -- ;; -- -*** Keyword *** +*** Keywords *** Create Output With Robot [Arguments] ${outputname} ${options} ${sources} Run Tests ${options} ${sources} - Timestamp Should Be Valid ${SUITE.starttime} - Timestamp Should Be Valid ${SUITE.endtime} - Elapsed Time Should Be Valid ${SUITE.elapsedtime} - Set Suite Variable $ORIG_START ${SUITE.starttime} - Set Suite Variable $ORIG_END ${SUITE.endtime} - Set Suite Variable $ORIG_ELAPSED ${SUITE.elapsedtime} - Run Keyword If $outputname Move File ${OUTFILE} ${outputname} - -Check times - [Arguments] ${item} ${start} ${end} ${elapsed} - Should Be Equal ${item.starttime} ${start} - Should Be Equal ${item.endtime} ${end} - Should Be Equal As Integers ${item.elapsedtime} ${elapsed} + Timestamp Should Be Valid ${SUITE.start_time} + Timestamp Should Be Valid ${SUITE.end_time} + Elapsed Time Should Be Valid ${SUITE.elapsed_time} + Set Suite Variable $ORIG_START ${SUITE.start_time} + Set Suite Variable $ORIG_END ${SUITE.end_time} + Set Suite Variable $ORIG_ELAPSED ${SUITE.elapsed_time} + IF $outputname Move File ${OUTFILE} ${outputname} diff --git a/atest/robot/cli/console/colors_and_width.robot b/atest/robot/cli/console/colors_and_width.robot index ea1b139d7ba..e9fbbeb2772 100644 --- a/atest/robot/cli/console/colors_and_width.robot +++ b/atest/robot/cli/console/colors_and_width.robot @@ -5,20 +5,20 @@ Resource console_resource.robot *** Test Cases *** Console Colors Auto - Run Tests With Colors --consolecolors auto - Outputs should not have ANSI colors + Run Tests With Warnings --consolecolors auto + Outputs should not have ANSI codes Console Colors Off - Run Tests With Colors --consolecolors OFF - Outputs should not have ANSI colors + Run Tests With Warnings --consolecolors OFF + Outputs should not have ANSI codes Console Colors On - Run Tests With Colors --ConsoleCol on + Run Tests With Warnings --ConsoleCol on Outputs should have ANSI colors when not on Windows Console Colors ANSI - Run Tests With Colors --ConsoleColors AnSi - Outputs should have ANSI colors + Run Tests With Warnings --Console-Colors AnSi + Outputs should have ANSI codes Invalid Console Colors Run Tests Without Processing Output -C InVaLid misc/pass_and_fail.robot @@ -43,27 +43,43 @@ Invalid Width Run Tests Without Processing Output -W InVaLid misc/pass_and_fail.robot Stderr Should Be Equal To [ ERROR ] Invalid value for option '--consolewidth': Expected integer, got 'InVaLid'.${USAGE TIP}\n +Console links off + [Documentation] Console links being enabled is tested as part of testing console colors. + Run Tests With Warnings --console-links oFF --console-colors on + Outputs should have ANSI colors when not on Windows links=False + +Invalid link config + Run Tests Without Processing Output --ConsoleLinks InVaLid misc/pass_and_fail.robot + Stderr Should Be Equal To [ ERROR ] Invalid console link value 'InVaLid. Available 'AUTO' and 'OFF'.${USAGE TIP}\n + *** Keywords *** -Run Tests With Colors - [Arguments] ${colors} - Run Tests ${colors} --variable LEVEL1:WARN misc/pass_and_fail.robot +Run Tests With Warnings + [Arguments] ${options} + Run Tests ${options} --variable LEVEL1:WARN misc/pass_and_fail.robot -Outputs should not have ANSI colors +Outputs should not have ANSI codes Stdout Should Contain | PASS | Stdout Should Contain | FAIL | Stderr Should Contain [ WARN ] Outputs should have ANSI colors when not on Windows + [Arguments] ${links}=True IF os.sep == '/' - Outputs should have ANSI colors + Outputs should have ANSI codes ${links} ELSE - Outputs should not have ANSI colors + Outputs should not have ANSI codes END -Outputs should have ANSI colors +Outputs should have ANSI codes + [Arguments] ${links}=True Stdout Should Not Contain | PASS | Stdout Should Not Contain | FAIL | Stderr Should Not Contain [ WARN ] - Stdout Should Contain PASS - Stdout Should Contain FAIL - Stderr Should Contain WARN + Stdout Should Contain | \x1b[32mPASS\x1b[0m | + Stdout Should Contain | \x1b[31mFAIL\x1b[0m | + Stderr Should Contain [ \x1b[33mWARN\x1b[0m ] + IF ${links} + Stdout Should Contain \x1b]8;;file:// + ELSE + Stdout Should Not Contain \x1b]8;;file:// + END diff --git a/atest/robot/cli/console/console_resource.robot b/atest/robot/cli/console/console_resource.robot index c2b190576f5..5003b40a338 100644 --- a/atest/robot/cli/console/console_resource.robot +++ b/atest/robot/cli/console/console_resource.robot @@ -13,7 +13,7 @@ ${MSG_110} 1 test, 1 passed, 0 failed *** Keywords *** Create Status Line [Arguments] ${name} ${padding} ${status} - [Return] ${name}${SPACE * ${padding}}| ${status} | + RETURN ${name}${SPACE * ${padding}}| ${status} | Stdout Should Be [Arguments] ${expected} &{replaced} diff --git a/atest/robot/cli/console/console_type.robot b/atest/robot/cli/console/console_type.robot index fd171a5d919..1483a6e7fe6 100644 --- a/atest/robot/cli/console/console_type.robot +++ b/atest/robot/cli/console/console_type.robot @@ -69,7 +69,7 @@ Dotted does not show details for skipped after fatal error --Dotted --ExitOnFailure with empty test case Run tests -X. core/empty_testcase_and_uk.robot Stdout Should Be dotted_exitonfailure_empty_test.txt - Stderr Should Be empty.txt + Stderr Should Be dotted_exitonfailure_empty_test_stderr.txt Check test tags ${EMPTY} ${tc} = Check test case Empty Test Case FAIL ... Failure occurred and exit-on-failure mode is in use. diff --git a/atest/robot/cli/console/disable_standard_streams.py b/atest/robot/cli/console/disable_standard_streams.py new file mode 100644 index 00000000000..fc898f4f1cd --- /dev/null +++ b/atest/robot/cli/console/disable_standard_streams.py @@ -0,0 +1,3 @@ +import sys + +sys.stdin = sys.stdout = sys.stderr = sys.__stdin__ = sys.__stdout__ = sys.__stderr__ = None diff --git a/atest/robot/cli/console/encoding.robot b/atest/robot/cli/console/encoding.robot index 3dc94dd6a93..00194b8e242 100644 --- a/atest/robot/cli/console/encoding.robot +++ b/atest/robot/cli/console/encoding.robot @@ -26,7 +26,7 @@ PYTHONIOENCODING is honored in console output Should Contain ${result.stdout} ???-????? T??t ??d K?yw?rd N?m?s, Спасибо${SPACE*29}| PASS | Invalid encoding configuration - [Tags] no-windows no-osx + [Tags] no-windows no-osx no-pypy ${cmd} = Join command line ... LANG=invalid ... LC_TYPE=invalid diff --git a/atest/robot/cli/console/expected_output/ExpectedOutputLibrary.py b/atest/robot/cli/console/expected_output/ExpectedOutputLibrary.py index f7851a42b6c..ec340edcb57 100644 --- a/atest/robot/cli/console/expected_output/ExpectedOutputLibrary.py +++ b/atest/robot/cli/console/expected_output/ExpectedOutputLibrary.py @@ -25,7 +25,7 @@ def output_should_be(actual, expected, **replaced): def _read_file(path, title, replaced=None): - with open(path) as file: + with open(path, encoding='UTF-8') as file: content = file.read() if replaced: for item in replaced: diff --git a/atest/robot/cli/console/expected_output/dotted_exitonfailure_empty_test_stderr.txt b/atest/robot/cli/console/expected_output/dotted_exitonfailure_empty_test_stderr.txt new file mode 100644 index 00000000000..c7397fa047f --- /dev/null +++ b/atest/robot/cli/console/expected_output/dotted_exitonfailure_empty_test_stderr.txt @@ -0,0 +1,3 @@ +[[] ERROR ] Error in file '*[/\]empty_testcase_and_uk.robot' on line 42: Creating keyword '' failed: User keyword name cannot be empty. +[[] WARN ] Error in file '*[/\]empty_testcase_and_uk.robot' on line 60: The '[[]Return]' setting is deprecated. Use the 'RETURN' statement instead. +[[] WARN ] Error in file '*[/\]empty_testcase_and_uk.robot' on line 63: The '[[]Return]' setting is deprecated. Use the 'RETURN' statement instead. diff --git a/atest/robot/cli/console/max_assign_length.robot b/atest/robot/cli/console/max_assign_length.robot index 8d9e866805b..587c9f1b86f 100644 --- a/atest/robot/cli/console/max_assign_length.robot +++ b/atest/robot/cli/console/max_assign_length.robot @@ -4,7 +4,7 @@ Test Template Assignment messages should be Resource atest_resource.robot *** Variables *** -@{TESTS} 10 chars 200 chars 201 chars 1000 chars 1001 chars +@{TESTS} 10 chars 200 chars 201 chars 1000 chars 1001 chars VAR *** Test Cases *** Default limit @@ -14,6 +14,7 @@ Default limit ... '0123456789' * 20 + '...' ... '0123456789' * 20 + '...' ... '0123456789' * 20 + '...' + ... '0123456789' * 20 + '...' Custom limit 10 @@ -22,18 +23,21 @@ Custom limit ... '0123456789' + '...' ... '0123456789' + '...' ... '0123456789' + '...' + ... '0123456789' + '...' 1000 ... '0123456789' ... '0123456789' * 20 ... '0123456789' * 20 + '0' ... '0123456789' * 100 ... '0123456789' * 100 + '...' + ... '0123456789' * 100 10000 ... '0123456789' ... '0123456789' * 20 ... '0123456789' * 20 + '0' ... '0123456789' * 100 ... '0123456789' * 100 + '0' + ... '0123456789' * 100 Hide value 0 @@ -42,12 +46,14 @@ Hide value ... '...' ... '...' ... '...' + ... '...' -666 ... '...' ... '...' ... '...' ... '...' ... '...' + ... '...' Invalid [Template] NONE @@ -65,9 +71,8 @@ Assignment messages should be ELSE Run Tests ${EMPTY} cli/console/max_assign_length.robot END - Length Should Be ${messages} 5 - FOR ${name} ${msg} IN ZIP ${TESTS} ${MESSAGES} + FOR ${name} ${msg} IN ZIP ${TESTS} ${messages} mode=STRICT ${tc} = Check Test Case ${name} ${msg} = Evaluate ${msg} - Check Log Message ${tc.body[0].messages[0]} \${value} = ${msg} + Check Log Message ${tc[0, 0]} \${value} = ${msg} END diff --git a/atest/robot/cli/console/max_error_lines.robot b/atest/robot/cli/console/max_error_lines.robot index 88abce98564..a2790f577cb 100644 --- a/atest/robot/cli/console/max_error_lines.robot +++ b/atest/robot/cli/console/max_error_lines.robot @@ -38,20 +38,21 @@ Has Been Cut Should Contain ${test.message} ${EXPLANATION} Should Match Non Empty Regexp ${test.message} ${eol_dots} Should Match Non Empty Regexp ${test.message} ${bol_dots} - Error Message In Log Should Not Have Been Cut ${test.kws} - [Return] ${test} + Error Message In Log Should Not Have Been Cut ${test.body} + RETURN ${test} Error Message In Log Should Not Have Been Cut - [Arguments] ${kws} - @{keywords} = Set Variable ${kws} - FOR ${kw} IN @{keywords} - Run Keyword If ${kw.msgs} Should Not Contain ${kw.msgs[-1].message} ${EXPLANATION} - Error Message In Log Should Not Have Been Cut ${kw.kws} + [Arguments] ${items} + FOR ${item} IN @{items} + FOR ${msg} IN @{item.messages} + Should Not Contain ${msg.message} ${EXPLANATION} + END + Error Message In Log Should Not Have Been Cut ${item.non_messages} END Should Match Non Empty Regexp [Arguments] ${message} ${pattern} - Run Keyword If '${pattern}' Should Match Regexp ${message} ${pattern} + IF $pattern Should Match Regexp ${message} ${pattern} Has Not Been Cut [Arguments] ${testname} diff --git a/atest/robot/cli/console/piping.robot b/atest/robot/cli/console/piping.robot index ca5963844c8..15a50291753 100644 --- a/atest/robot/cli/console/piping.robot +++ b/atest/robot/cli/console/piping.robot @@ -14,7 +14,7 @@ ${TARGET} ${CURDIR}${/}piping.py *** Test Cases *** Pipe to command consuming all data Run with pipe and validate results read_all - Should Be Equal ${STDOUT} 17 lines with 'FAIL' found! + Should Be Equal ${STDOUT} 20 lines with 'FAIL' found! Pipe to command consuming some data Run with pipe and validate results read_some @@ -28,8 +28,7 @@ Pipe to command consuming no data Run with pipe and validate results [Arguments] ${pipe style} ${command} = Join Command Line @{COMMAND} - ${result} = Run Process ${command} | python ${TARGET} ${pipe style} - ... shell=true + ${result} = Run Process ${command} | python ${TARGET} ${pipe style} shell=True Log Many RC: ${result.rc} STDOUT:\n${result.stdout} STDERR:\n${result.stderr} Should Be Equal ${result.rc} ${0} Process Output ${OUTPUT} diff --git a/atest/robot/cli/console/standard_streams_disabled.robot b/atest/robot/cli/console/standard_streams_disabled.robot new file mode 100644 index 00000000000..44af45e78b2 --- /dev/null +++ b/atest/robot/cli/console/standard_streams_disabled.robot @@ -0,0 +1,23 @@ +*** Settings *** +Suite Setup Run tests with standard streams disabled +Resource console_resource.robot + +*** Test Cases *** +Execution succeeds + Should Be Equal ${SUITE.name} Log + +Console outputs are disabled + Stdout Should Be empty.txt + Stderr Should Be empty.txt + +Log To Console keyword succeeds + Check Test Case Log to console + +*** Keywords *** +Run tests with standard streams disabled + [Documentation] Streams are disabled by using the sitecustomize module: + ... https://docs.python.org/3/library/site.html#module-sitecustomize + Copy File ${CURDIR}/disable_standard_streams.py %{TEMPDIR}/sitecustomize.py + Set Environment Variable PYTHONPATH %{TEMPDIR} + Run Tests ${EMPTY} standard_libraries/builtin/log.robot + [Teardown] Remove File %{TEMPDIR}/sitecustomize.py diff --git a/atest/robot/cli/dryrun/dryrun.robot b/atest/robot/cli/dryrun/dryrun.robot index a48b4e54116..f6e0c24269c 100644 --- a/atest/robot/cli/dryrun/dryrun.robot +++ b/atest/robot/cli/dryrun/dryrun.robot @@ -6,39 +6,51 @@ Resource dryrun_resource.robot *** Test Cases *** Passing keywords ${tc}= Check Test Case ${TESTNAME} - Length Should Be ${tc.kws} 4 - Check Keyword Data ${tc.kws[0]} BuiltIn.Log status=NOT RUN args=Hello from test - Check Keyword Data ${tc.kws[1]} OperatingSystem.List Directory status=NOT RUN assign=\${contents} args=. - Check Keyword Data ${tc.kws[2]} resource.Simple UK - Check Keyword Data ${tc.kws[2].kws[0]} BuiltIn.Log status=NOT RUN args=Hello from UK + Length Should Be ${tc.body} 4 + Check Keyword Data ${tc[0]} BuiltIn.Log status=NOT RUN args=Hello from test + Check Keyword Data ${tc[1]} OperatingSystem.List Directory status=NOT RUN assign=\${contents} args=. + Check Keyword Data ${tc[2]} resource.Simple UK + Check Keyword Data ${tc[2, 0]} BuiltIn.Log status=NOT RUN args=Hello from UK Keywords with embedded arguments ${tc}= Check Test Case ${TESTNAME} - Length Should Be ${tc.kws} 3 - Check Keyword Data ${tc.kws[0]} Embedded arguments here - Check Keyword Data ${tc.kws[0].kws[0]} BuiltIn.No Operation status=NOT RUN - Check Keyword Data ${tc.kws[1]} Embedded args rock here - Check Keyword Data ${tc.kws[1].kws[0]} BuiltIn.No Operation status=NOT RUN + Length Should Be ${tc.body} 5 + Check Keyword Data ${tc[0]} Embedded arguments here + Check Keyword Data ${tc[0, 0]} BuiltIn.No Operation status=NOT RUN + Check Keyword Data ${tc[1]} Embedded args rock here + Check Keyword Data ${tc[1, 0]} BuiltIn.No Operation status=NOT RUN + Check Keyword Data ${tc[2]} Some embedded and normal args args=42 + Check Keyword Data ${tc[2, 0]} BuiltIn.No Operation status=NOT RUN + Check Keyword Data ${tc[3]} Some embedded and normal args args=\${does not exist} + Check Keyword Data ${tc[3, 0]} BuiltIn.No Operation status=NOT RUN + +Keywords with types + Check Test Case ${TESTNAME} + +Keywords with types that would fail + Check Test Case ${TESTNAME} + Error In File 1 cli/dryrun/dryrun.robot 214 + ... Creating keyword 'Invalid type' failed: Invalid argument specification: Invalid argument '\${arg: bad}': Unrecognized type 'bad'. Library keyword with embedded arguments ${tc}= Check Test Case ${TESTNAME} - Length Should Be ${tc.kws} 2 - Check Keyword Data ${tc.kws[0]} EmbeddedArgs.Log 42 times status=NOT RUN + Length Should Be ${tc.body} 2 + Check Keyword Data ${tc[0]} EmbeddedArgs.Log 42 times status=NOT RUN Keywords that would fail ${tc}= Check Test Case ${TESTNAME} - Length Should Be ${tc.kws} 3 - Check Keyword Data ${tc.kws[0]} BuiltIn.Fail status=NOT RUN args=Not actually executed so won't fail. - Check Keyword Data ${tc.kws[1]} resource.Fail In UK - Length Should Be ${tc.kws[1].kws} 2 - Check Keyword Data ${tc.kws[1].kws[0]} BuiltIn.Fail status=NOT RUN args= - Check Keyword Data ${tc.kws[1].kws[1]} BuiltIn.Fail status=NOT RUN args=And again + Length Should Be ${tc.body} 3 + Check Keyword Data ${tc[0]} BuiltIn.Fail status=NOT RUN args=Not actually executed so won't fail. + Check Keyword Data ${tc[1]} resource.Fail In UK + Length Should Be ${tc[1].body} 2 + Check Keyword Data ${tc[1, 0]} BuiltIn.Fail status=NOT RUN args= + Check Keyword Data ${tc[1, 1]} BuiltIn.Fail status=NOT RUN args=And again Scalar variables are not checked in keyword arguments [Documentation] Variables are too often set somehow dynamically that we cannot expect them to always exist. ${tc}= Check Test Case ${TESTNAME} - Check Keyword Data ${tc.kws[0]} BuiltIn.Log status=NOT RUN args=\${TESTNAME} - Check Keyword Data ${tc.kws[1]} BuiltIn.Log status=NOT RUN args=\${this does not exist} + Check Keyword Data ${tc[0]} BuiltIn.Log status=NOT RUN args=\${TESTNAME} + Check Keyword Data ${tc[1]} BuiltIn.Log status=NOT RUN args=\${this does not exist} List variables are not checked in keyword arguments [Documentation] See the doc of the previous test @@ -51,22 +63,22 @@ Dict variables are not checked in keyword arguments Variables are not checked in when arguments are embedded [Documentation] See the doc of the previous test ${tc}= Check Test Case ${TESTNAME} - Check Keyword Data ${tc.kws[0]} Embedded \${TESTNAME} here - Check Keyword Data ${tc.kws[0].kws[0]} BuiltIn.No Operation status=NOT RUN - Check Keyword Data ${tc.kws[1]} Embedded \${nonex} here - Check Keyword Data ${tc.kws[1].kws[0]} BuiltIn.No Operation status=NOT RUN + Check Keyword Data ${tc[0]} Embedded \${TESTNAME} here + Check Keyword Data ${tc[0, 0]} BuiltIn.No Operation status=NOT RUN + Check Keyword Data ${tc[1]} Embedded \${nonex} here + Check Keyword Data ${tc[1, 0]} BuiltIn.No Operation status=NOT RUN Setup/teardown with non-existing variable is ignored ${tc} = Check Test Case ${TESTNAME} - Setup Should Not Be Defined ${SUITE} - Setup Should Not Be Defined ${tc} + Setup Should Not Be Defined ${SUITE} + Setup Should Not Be Defined ${tc} Teardown Should Not Be Defined ${tc} Setup/teardown with existing variable is resolved and executed ${tc} = Check Test Case ${TESTNAME} - Check Keyword Data ${tc.setup} BuiltIn.No Operation status=NOT RUN type=SETUP - Check Keyword Data ${tc.teardown} Teardown args=\${nonex arg} type=TEARDOWN - Check Keyword Data ${tc.teardown.body[0]} BuiltIn.Log args=\${arg} status=NOT RUN + Check Keyword Data ${tc.setup} BuiltIn.No Operation status=NOT RUN type=SETUP + Check Keyword Data ${tc.teardown} Teardown args=\${nonex arg} type=TEARDOWN + Check Keyword Data ${tc.teardown[0]} BuiltIn.Log args=\${arg} status=NOT RUN User keyword return value Check Test Case ${TESTNAME} @@ -76,51 +88,52 @@ Non-existing variable in user keyword return value Test Setup and Teardown ${tc}= Check Test Case ${TESTNAME} - Length Should Be ${tc.kws} 2 - Check Keyword Data ${tc.setup} BuiltIn.Log args=Hello Setup status=NOT RUN type=SETUP - Check Keyword Data ${tc.teardown} Does not exist status=FAIL type=TEARDOWN + Length Should Be ${tc.body} 2 + Check Keyword Data ${tc.setup} BuiltIn.Log args=Hello Setup status=NOT RUN type=SETUP + Check Keyword Data ${tc.teardown} Does not exist status=FAIL type=TEARDOWN Keyword Teardown ${tc}= Check Test Case ${TESTNAME} - Length Should Be ${tc.kws} 2 - Check Keyword Data ${tc.kws[0].teardown} Does not exist status=FAIL type=TEARDOWN + Length Should Be ${tc.body} 2 + Check Keyword Data ${tc[0].teardown} Does not exist status=FAIL type=TEARDOWN Keyword teardown with non-existing variable is ignored Check Test Case ${TESTNAME} Keyword teardown with existing variable is resolved and executed ${tc}= Check Test Case ${TESTNAME} - Check Keyword Data ${tc.kws[0].teardown} Teardown args=\${I DO NOT EXIST} type=TEARDOWN - Check Keyword Data ${tc.kws[0].teardown.kws[0]} BuiltIn.Log args=\${arg} status=NOT RUN + Check Keyword Data ${tc[0].teardown} Teardown args=\${I DO NOT EXIST} type=TEARDOWN + Check Keyword Data ${tc[0].teardown[0]} BuiltIn.Log args=\${arg} status=NOT RUN Non-existing keyword name Check Test Case ${TESTNAME} Invalid syntax in UK Check Test Case ${TESTNAME} - Error In File 0 cli/dryrun/dryrun.robot 155 - ... Creating keyword 'Invalid Syntax UK' failed: - ... Invalid argument specification: - ... Invalid argument syntax '\${arg'. + Error In File 0 cli/dryrun/dryrun.robot 210 + ... SEPARATOR=\n + ... Creating keyword 'Invalid Syntax UK' failed: Invalid argument specification: Multiple errors: + ... - Invalid argument syntax '\${oops'. + ... - Non-default argument after default arguments. Multiple Failures Check Test Case ${TESTNAME} Avoid keyword in dry-run ${tc} = Check Test Case ${TESTNAME} - Keyword should have been skipped with tag ${tc.kws[0]} Keyword not run in dry-run robot:no-dry-run - Keyword should have been skipped with tag ${tc.kws[1]} Another keyword not run in dry-run ROBOT: no-dry-run - Keyword should have been skipped with tag ${tc.kws[2].kws[0]} Keyword not run in dry-run robot:no-dry-run - Keyword should have been skipped with tag ${tc.kws[2].kws[1]} Another keyword not run in dry-run ROBOT: no-dry-run - Keyword should have been validated ${tc.kws[2].kws[2]} - Keyword should have been validated ${tc.kws[3]} + Keyword should have been skipped with tag ${tc[0]} Keyword not run in dry-run robot:no-dry-run + Keyword should have been skipped with tag ${tc[1]} Another keyword not run in dry-run ROBOT: no-dry-run + Keyword should have been skipped with tag ${tc[2, 0]} Keyword not run in dry-run robot:no-dry-run + Keyword should have been skipped with tag ${tc[2, 1]} Another keyword not run in dry-run ROBOT: no-dry-run + Keyword should have been validated ${tc[2, 2]} + Keyword should have been validated ${tc[3]} Invalid imports - Error in file 1 cli/dryrun/dryrun.robot 7 + Error in file 2 cli/dryrun/dryrun.robot 7 ... Importing library 'DoesNotExist' failed: *Error: * - Error in file 2 cli/dryrun/dryrun.robot 8 + Error in file 3 cli/dryrun/dryrun.robot 8 ... Variable file 'wrong_path.py' does not exist. - Error in file 3 cli/dryrun/dryrun.robot 9 + Error in file 4 cli/dryrun/dryrun.robot 9 ... Resource file 'NonExisting.robot' does not exist. [Teardown] NONE diff --git a/atest/robot/cli/dryrun/dryrun_resource.robot b/atest/robot/cli/dryrun/dryrun_resource.robot index 0c87de0da49..3591a4168fd 100644 --- a/atest/robot/cli/dryrun/dryrun_resource.robot +++ b/atest/robot/cli/dryrun/dryrun_resource.robot @@ -4,14 +4,13 @@ Resource atest_resource.robot *** Keywords *** Keyword should have been skipped with tag [Arguments] ${kw} ${name} ${tags} - Check Keyword Data ${kw} ${name} status=PASS tags=${tags} - Should Be Empty ${kw.kws} + Check Keyword Data ${kw} ${name} status=PASS tags=${tags} children=0 Keyword should have been validated [Arguments] ${kw} - Check Keyword Data ${kw} resource.This is validated - Check Keyword Data ${kw.kws[0]} BuiltIn.Log status=NOT RUN args=This is validated + Check Keyword Data ${kw} resource.This is validated + Check Keyword Data ${kw[0]} BuiltIn.Log status=NOT RUN args=This is validated Last keyword should have been validated - ${tc} = Get test case ${TEST NAME} - Keyword should have been validated ${tc.kws[-1]} + ${tc} = Get Test Case ${TEST NAME} + Keyword should have been validated ${tc[-1]} diff --git a/atest/robot/cli/dryrun/executed_builtin_keywords.robot b/atest/robot/cli/dryrun/executed_builtin_keywords.robot index 7ad5f635a39..7aa269847e3 100644 --- a/atest/robot/cli/dryrun/executed_builtin_keywords.robot +++ b/atest/robot/cli/dryrun/executed_builtin_keywords.robot @@ -4,18 +4,28 @@ Resource atest_resource.robot *** Test Cases *** Import Library - Check Test Case ${TESTNAME} + ${tc} = Check Test Case ${TESTNAME} + Check Keyword Data ${tc[0]} BuiltIn.Import Library args=String Syslog Should Contain Imported library 'String' with arguments [ ] Syslog Should Contain Imported library 'ParameterLibrary' with arguments [ value | 42 ] +Import Resource + ${tc} = Check Test Case ${TESTNAME} + Check Keyword Data ${tc[0]} BuiltIn.Import Resource args=\${RESOURCE} + ${resource} = Normalize Path ${DATADIR}/cli/dryrun/resource.robot + Syslog Should Contain Imported resource file '${resource}' (6 keywords). + Set Library Search Order ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[1].name} Second.Parameters - Should Be Equal ${tc.kws[2].name} First.Parameters - Should Be Equal ${tc.kws[4].name} Dynamic.Parameters + Check Keyword Data ${tc[0]} BuiltIn.Set Library Search Order args=Second + Should Be Equal ${tc[1].full_name} Second.Parameters + Should Be Equal ${tc[2].full_name} First.Parameters + Should Be Equal ${tc[4].full_name} Dynamic.Parameters Set Tags - Check Test Tags ${TESTNAME} \${2} \${var} Tag0 Tag1 Tag2 + ${tc} = Check Test Tags ${TESTNAME} \${2} \${var} Tag0 Tag1 Tag2 + Check Keyword Data ${tc[0]} BuiltIn.Set Tags args=Tag1, Tag2, \${var}, \${2} Remove Tags - Check Test Tags ${TESTNAME} Tag1 Tag3 + ${tc} = Check Test Tags ${TESTNAME} Tag1 Tag3 + Check Keyword Data ${tc[0]} BuiltIn.Remove Tags args=Tag2, \${var} diff --git a/atest/robot/cli/dryrun/for.robot b/atest/robot/cli/dryrun/for.robot index 0b34d8d1c91..879609609d5 100644 --- a/atest/robot/cli/dryrun/for.robot +++ b/atest/robot/cli/dryrun/for.robot @@ -6,11 +6,11 @@ Resource dryrun_resource.robot *** Test Cases *** FOR ${tc} = Check Test Case ${TESTNAME} - Validate loops ${tc} 4 - Length should be ${tc.kws[2].kws} 3 - Length should be ${tc.kws[2].kws[0].kws} 0 - Length should be ${tc.kws[2].kws[1].kws} 1 - Length should be ${tc.kws[2].kws[2].kws} 0 + Validate loops ${tc} 4 + Length should be ${tc[2].body} 3 + Length should be ${tc[2, 0].body} 0 + Length should be ${tc[2, 1].body} 1 + Length should be ${tc[2, 2].body} 0 FOR IN RANGE ${tc} = Check Test Case ${TESTNAME} @@ -27,8 +27,8 @@ FOR IN ZIP *** Keywords *** Validate loops [Arguments] ${tc} ${kws}=3 - Length should be ${tc.kws} ${kws} - Length should be ${tc.kws[0].kws} 1 - Length should be ${tc.kws[0].kws[0].kws} 2 - Length should be ${tc.kws[1].kws} 1 - Length should be ${tc.kws[1].kws[0].kws} 1 + Length should be ${tc.body} ${kws} + Length should be ${tc[0].body} 1 + Length should be ${tc[0, 0].body} 2 + Length should be ${tc[1].body} 1 + Length should be ${tc[1, 0].body} 1 diff --git a/atest/robot/cli/dryrun/if.robot b/atest/robot/cli/dryrun/if.robot index 24db7db4b32..31bf7359c26 100644 --- a/atest/robot/cli/dryrun/if.robot +++ b/atest/robot/cli/dryrun/if.robot @@ -6,18 +6,18 @@ Resource dryrun_resource.robot *** Test Cases *** IF will not recurse in dry run ${tc}= Check Test Case ${TESTNAME} - Check Branch Statuses ${tc.body[0]} Recursive if PASS - Check Branch Statuses ${tc.body[0].body[0].body[0].body[0]} Recursive if NOT RUN + Check Branch Statuses ${tc[0]} Recursive if PASS + Check Branch Statuses ${tc[0, 0, 0, 0]} Recursive if NOT RUN ELSE IF will not recurse in dry run ${tc}= Check Test Case ${TESTNAME} - Check Branch Statuses ${tc.body[0]} Recursive else if PASS - Check Branch Statuses ${tc.body[0].body[0].body[1].body[0]} Recursive else if NOT RUN + Check Branch Statuses ${tc[0]} Recursive else if PASS + Check Branch Statuses ${tc[0, 0, 1, 0]} Recursive else if NOT RUN ELSE will not recurse in dry run ${tc}= Check Test Case ${TESTNAME} - Check Branch Statuses ${tc.body[0]} Recursive else PASS - Check Branch Statuses ${tc.body[0].body[0].body[2].body[0]} Recursive else NOT RUN + Check Branch Statuses ${tc[0]} Recursive else PASS + Check Branch Statuses ${tc[0, 0, 2, 0]} Recursive else NOT RUN Dryrun fail inside of IF Check Test Case ${TESTNAME} @@ -44,9 +44,9 @@ Dryrun fail empty IF in non executed branch Check Branch Statuses [Arguments] ${kw} ${name} ${status} Should Be Equal ${kw.name} ${name} - Should Be Equal ${kw.body[0].body[0].type} IF - Should Be Equal ${kw.body[0].body[0].status} ${status} - Should Be Equal ${kw.body[0].body[1].type} ELSE IF - Should Be Equal ${kw.body[0].body[1].status} ${status} - Should Be Equal ${kw.body[0].body[2].type} ELSE - Should Be Equal ${kw.body[0].body[2].status} ${status} + Should Be Equal ${kw[0, 0].type} IF + Should Be Equal ${kw[0, 0].status} ${status} + Should Be Equal ${kw[0, 1].type} ELSE IF + Should Be Equal ${kw[0, 1].status} ${status} + Should Be Equal ${kw[0, 2].type} ELSE + Should Be Equal ${kw[0, 2].status} ${status} diff --git a/atest/robot/cli/dryrun/run_keyword_variants.robot b/atest/robot/cli/dryrun/run_keyword_variants.robot index fcbbfe40791..8d53a67d722 100644 --- a/atest/robot/cli/dryrun/run_keyword_variants.robot +++ b/atest/robot/cli/dryrun/run_keyword_variants.robot @@ -1,108 +1,130 @@ *** Settings *** -Suite Setup Run Tests --dryrun cli/dryrun/run_keyword_variants.robot -Resource atest_resource.robot +Suite Setup Run Tests --dryrun --listener ${LISTENER} cli/dryrun/run_keyword_variants.robot +Resource atest_resource.robot + +*** Variables *** +${LISTENER} ${DATADIR}/cli/dryrun/LinenoListener.py *** Test Cases *** Run Keyword With Keyword with Invalid Number of Arguments - Check Test Case ${TESTNAME} + ${tc} = Check Test Case ${TESTNAME} + Check Keyword Data ${tc[0]} BuiltIn.Run Keyword args=Log status=FAIL + Check Keyword Data ${tc[0, 0]} BuiltIn.Log args= status=FAIL Run Keyword With Missing Keyword - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Keywords with variable in name are ignored - Test Should Have Correct Keywords kw_index=0 - Test Should Have Correct Keywords BuiltIn.No Operation kw_index=1 - Test Should Have Correct Keywords kw_index=2 - Test Should Have Correct Keywords BuiltIn.No Operation kw_index=3 + Test Should Have Correct Keywords kw_index=0 + Test Should Have Correct Keywords BuiltIn.No Operation kw_index=1 + Test Should Have Correct Keywords kw_index=2 + Test Should Have Correct Keywords BuiltIn.No Operation kw_index=3 Keywords with variable in name are ignored also when variable is argument - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword With UK - Check Test Case ${TESTNAME} + ${tc} = Check Test Case ${TESTNAME} + Check Keyword Data ${tc[0]} BuiltIn.Run Keyword If args=True, UK status=PASS + Check Keyword Data ${tc[0, 0]} UK status=PASS + Check Keyword Data ${tc[0, 0, 0]} BuiltIn.No Operation status=NOT RUN Run Keyword With Failing UK - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Comment - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Set Test/Suite/Global Variable - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Variable Should (Not) Exist - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Get Variable Value - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Set Variable If - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keywords When All Keywords Pass - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keywords When One Keyword Fails - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keywords When Multiple Keyword Fails - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keywords With Arguments When All Keywords Pass - Test Should Have Correct Keywords BuiltIn.Log Many BuiltIn.No Operation + Test Should Have Correct Keywords BuiltIn.Log Many BuiltIn.No Operation Run Keywords With Arguments When One Keyword Fails - Test Should Have Correct Keywords BuiltIn.Log BuiltIn.Log + Test Should Have Correct Keywords BuiltIn.Log BuiltIn.Log Run Keywords With Arguments When Multiple Keyword Fails - Test Should Have Correct Keywords BuiltIn.Log Unknown Keyword + Test Should Have Correct Keywords BuiltIn.Log Unknown Keyword Run Keywords With Arguments With Variables - Test Should Have Correct Keywords BuiltIn.Log + Test Should Have Correct Keywords BuiltIn.Log Run Keyword in For Loop Pass - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword in For Loop Fail - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Wait Until Keyword Succeeds Pass - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Wait Until Keyword Succeeds Fail - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If Pass - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If Fail - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If with ELSE - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If with ELSE IF - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If with ELSE IF and ELSE - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If with ELSE IF and ELSE without keywords - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If with escaped or non-caps ELSE IF and ELSE - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Run Keyword If with list variable in ELSE IF and ELSE - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Test Teardown Related Run Keyword Variants - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Given/When/Then - ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.kws[0].kws} 1 - Length Should Be ${tc.kws[1].kws} 3 - Length Should Be ${tc.kws[2].kws} 2 - Length Should Be ${tc.kws[3].kws} 3 - Length Should Be ${tc.kws[4].kws} 3 + ${tc} = Check Test Case ${TESTNAME} + Length Should Be ${tc[0].body} 1 + Length Should Be ${tc[1].body} 3 + Length Should Be ${tc[2].body} 2 + Length Should Be ${tc[3].body} 3 + Length Should Be ${tc[4].body} 3 + +Line number + Should Be Empty ${ERRORS} + ${tc} = Check Test Case Run Keyword With Missing Keyword + Should Be Equal ${tc[0].doc} Keyword 'Run Keyword' on line 14. + Should Be Equal ${tc[0, 0].doc} Keyword 'Missing' on line 14. + ${tc} = Check Test Case Run Keywords When One Keyword Fails + Should Be Equal ${tc[0].doc} Keyword 'Run Keywords' on line 68. + Should Be Equal ${tc[0, 0].doc} Keyword 'Fail' on line 68. + Should Be Equal ${tc[0, 2].doc} Keyword 'Log' on line 68. + Should Be Equal ${tc[0, 3].doc} Keyword 'UK' on line 68. + ${tc} = Check Test Case Run Keyword If Pass + Should Be Equal ${tc[0].doc} Keyword 'Run Keyword If' on line 114. + Should Be Equal ${tc[0, 0].doc} Keyword 'No Operation' on line 114. diff --git a/atest/robot/cli/dryrun/try_except.robot b/atest/robot/cli/dryrun/try_except.robot index a5e9738dc0e..be64c9590eb 100644 --- a/atest/robot/cli/dryrun/try_except.robot +++ b/atest/robot/cli/dryrun/try_except.robot @@ -6,11 +6,11 @@ Resource dryrun_resource.robot *** Test Cases *** TRY ${tc} = Check Test Case ${TESTNAME} - Check Keyword Data ${tc.body[0].body[0]} ${EMPTY} type=TRY - Check Keyword Data ${tc.body[0].body[0].body[0]} resource.Simple UK - Check Keyword Data ${tc.body[0].body[0].body[0].body[0]} BuiltIn.Log args=Hello from UK status=NOT RUN - Check Keyword Data ${tc.body[0].body[1].body[0]} BuiltIn.Log args=handling it status=NOT RUN - Check Keyword Data ${tc.body[0].body[2].body[0]} BuiltIn.Log args=in the else status=NOT RUN - Check Keyword Data ${tc.body[0].body[3].body[0]} BuiltIn.Log args=in the finally status=NOT RUN - Check Keyword Data ${tc.body[1].body[0]} ${EMPTY} status=FAIL type=TRY - Check Keyword Data ${tc.body[1].body[0].body[0]} resource.Anarchy in the UK status=FAIL args=1, 2 + Check TRY Data ${tc[0, 0]} + Check Keyword Data ${tc[0, 0, 0]} resource.Simple UK + Check Keyword Data ${tc[0, 0, 0, 0]} BuiltIn.Log args=Hello from UK status=NOT RUN + Check Keyword Data ${tc[0, 1, 0]} BuiltIn.Log args=handling it status=NOT RUN + Check Keyword Data ${tc[0, 2, 0]} BuiltIn.Log args=in the else status=NOT RUN + Check Keyword Data ${tc[0, 3, 0]} BuiltIn.Log args=in the finally status=NOT RUN + Check TRY Data ${tc[1, 0]} status=FAIL + Check Keyword Data ${tc[1, 0, 0]} resource.Anarchy in the UK status=FAIL args=1, 2 diff --git a/atest/robot/cli/dryrun/type_conversion.robot b/atest/robot/cli/dryrun/type_conversion.robot index 3d5b9b0f2b5..3ed4f230cf4 100644 --- a/atest/robot/cli/dryrun/type_conversion.robot +++ b/atest/robot/cli/dryrun/type_conversion.robot @@ -3,7 +3,9 @@ Resource atest_resource.robot *** Test Cases *** Annotations - Run Tests --dryrun keywords/type_conversion/annotations.robot + # Exclude test requiring Python 3.14 unconditionally to avoid a failure with + # older versions. It can be included once Python 3.14 is our minimum versoin. + Run Tests --dryrun --exclude require-py3.14 keywords/type_conversion/annotations.robot Should be equal ${SUITE.status} PASS Keyword Decorator diff --git a/atest/robot/cli/dryrun/while.robot b/atest/robot/cli/dryrun/while.robot index 3ed2f40d78c..65a1bda2f29 100644 --- a/atest/robot/cli/dryrun/while.robot +++ b/atest/robot/cli/dryrun/while.robot @@ -6,16 +6,16 @@ Resource dryrun_resource.robot *** Test Cases *** WHILE ${tc} = Check Test Case ${TESTNAME} - Length should be ${tc.body[1].body} 1 - Length should be ${tc.body[1].body[0].body} 3 - Length should be ${tc.body[2].body} 1 - Length should be ${tc.body[1].body[0].body} 3 - Length should be ${tc.body[3].body} 3 - Length should be ${tc.body[3].body[0].body} 0 - Length should be ${tc.body[3].body[1].body} 1 - Length should be ${tc.body[3].body[2].body} 0 + Length should be ${tc[1].body} 1 + Length should be ${tc[1, 0].body} 3 + Length should be ${tc[2].body} 1 + Length should be ${tc[1, 0].body} 3 + Length should be ${tc[3].body} 3 + Length should be ${tc[3, 0].body} 0 + Length should be ${tc[3, 1].body} 1 + Length should be ${tc[3, 2].body} 0 WHILE with BREAK and CONTINUE ${tc} = Check Test Case ${TESTNAME} - Length should be ${tc.body[1].body} 1 - Length should be ${tc.body[2].body} 1 + Length should be ${tc[1].body} 1 + Length should be ${tc[2].body} 1 diff --git a/atest/robot/cli/model_modifiers/ModelModifier.py b/atest/robot/cli/model_modifiers/ModelModifier.py index 23f8fb5f9c4..fdd32c19920 100644 --- a/atest/robot/cli/model_modifiers/ModelModifier.py +++ b/atest/robot/cli/model_modifiers/ModelModifier.py @@ -1,4 +1,6 @@ from robot.model import SuiteVisitor +from robot.running import TestCase as RunningTestCase +from robot.running.model import Argument class ModelModifier(SuiteVisitor): @@ -13,7 +15,20 @@ def start_suite(self, suite): if config[0] == 'FAIL': raise RuntimeError(' '.join(self.config[1:])) elif config[0] == 'CREATE': - suite.tests.create(**dict(conf.split('-', 1) for conf in config[1:])) + tc = suite.tests.create(**dict(conf.split('-', 1) for conf in config[1:])) + tc.body.create_keyword('Log', args=['Hello', 'level=INFO']) + if isinstance(tc, RunningTestCase): + # robot.running.model.Argument is a private/temporary API for creating + # named arguments with non-string values programmatically. It was added + # in RF 7.0.1 (#5031) after a failed attempt to add an API for this + # purpose in RF 7.0 (#5000). + tc.body.create_keyword('Log', args=[Argument(None, 'Argument object!'), + Argument('level', 'INFO')]) + tc.body.create_keyword('Should Contain', + args=[(1, 2, 3), Argument('item', 2)]) + # Passing named args separately is supported since RF 7.1 (#5143). + tc.body.create_keyword('Log', args=['Named args separately'], + named_args={'html': True, 'level': '${{"INFO"}}'}) self.config = [] elif config == ('REMOVE', 'ALL', 'TESTS'): suite.tests = [] @@ -21,20 +36,31 @@ def start_suite(self, suite): suite.tests = [t for t in suite.tests if not t.tags.match('fail')] def start_test(self, test): + self.make_non_empty(test, 'Test') + if hasattr(test.parent, 'resource'): + for kw in test.parent.resource.keywords: + self.make_non_empty(kw, 'Keyword') test.tags.add(self.config) + def make_non_empty(self, item, kind): + if not item.name: + item.name = f'{kind} name made non-empty by modifier' + item.body.clear() + if not item.body: + item.body.create_keyword('Log', [f'{kind} body made non-empty by modifier']) + def start_for(self, for_): - if for_.parent.name == 'FOR IN RANGE loop in test': + if for_.parent.name == 'FOR IN RANGE': for_.flavor = 'IN' for_.values = ['FOR', 'is', 'modified!'] def start_for_iteration(self, iteration): - for name, value in iteration.variables.items(): - iteration.variables[name] = value + ' (modified)' - iteration.variables['${x}'] = 'new' + for name, value in iteration.assign.items(): + iteration.assign[name] = value + ' (modified)' + iteration.assign['${x}'] = 'new' def start_if_branch(self, branch): - if branch.condition == "'IF' == 'WRONG'": + if branch.condition == "'${x}' == 'wrong'": branch.condition = 'True' # With Robot if not hasattr(branch, 'status'): diff --git a/atest/robot/cli/model_modifiers/pre_rebot.robot b/atest/robot/cli/model_modifiers/pre_rebot.robot index 82908d75f66..a648d50c498 100644 --- a/atest/robot/cli/model_modifiers/pre_rebot.robot +++ b/atest/robot/cli/model_modifiers/pre_rebot.robot @@ -59,26 +59,26 @@ Modifiers are used before normal configuration Modify FOR [Setup] Modify FOR and IF - ${tc} = Check Test Case For In Range Loop In Test - Should Be Equal ${tc.body[0].flavor} IN - Should Be Equal ${tc.body[0].values} ${{('FOR', 'is', 'modified!')}} - Should Be Equal ${tc.body[0].body[0].variables['\${i}']} 0 (modified) - Should Be Equal ${tc.body[0].body[0].variables['\${x}']} new - Check Log Message ${tc.body[0].body[0].body[0].msgs[0]} 0 - Should Be Equal ${tc.body[0].body[1].variables['\${i}']} 1 (modified) - Should Be Equal ${tc.body[0].body[1].variables['\${x}']} new - Check Log Message ${tc.body[0].body[1].body[0].msgs[0]} 1 - Should Be Equal ${tc.body[0].body[2].variables['\${i}']} 2 (modified) - Should Be Equal ${tc.body[0].body[2].variables['\${x}']} new - Check Log Message ${tc.body[0].body[2].body[0].msgs[0]} 2 + ${tc} = Check Test Case FOR IN RANGE + Should Be Equal ${tc[0].flavor} IN + Should Be Equal ${tc[0].values} ${{('FOR', 'is', 'modified!')}} + Should Be Equal ${tc[0, 0].assign['\${i}']} 0 (modified) + Should Be Equal ${tc[0, 0].assign['\${x}']} new + Check Log Message ${tc[0, 0, 0, 0]} 0 + Should Be Equal ${tc[0, 1].assign['\${i}']} 1 (modified) + Should Be Equal ${tc[0, 1].assign['\${x}']} new + Check Log Message ${tc[0, 1, 0, 0]} 1 + Should Be Equal ${tc[0, 2].assign['\${i}']} 2 (modified) + Should Be Equal ${tc[0, 2].assign['\${x}']} new + Check Log Message ${tc[0, 2, 0, 0]} 2 Modify IF [Setup] Should Be Equal ${PREV TEST NAME} Modify FOR ${tc} = Check Test Case If structure - Should Be Equal ${tc.body[0].body[0].condition} modified - Should Be Equal ${tc.body[0].body[0].status} PASS - Should Be Equal ${tc.body[0].body[0].body[0].args[0]} got here! - Should Be Equal ${tc.body[0].body[1].status} PASS + Should Be Equal ${tc[1, 0].condition} modified + Should Be Equal ${tc[1, 0].status} PASS + Should Be Equal ${tc[1, 0, 0].args[0]} got here! + Should Be Equal ${tc[1, 1].status} PASS *** Keywords *** Modify FOR and IF diff --git a/atest/robot/cli/model_modifiers/pre_run.robot b/atest/robot/cli/model_modifiers/pre_run.robot index 66c7dcd4d6e..b935aedab44 100644 --- a/atest/robot/cli/model_modifiers/pre_run.robot +++ b/atest/robot/cli/model_modifiers/pre_run.robot @@ -44,19 +44,39 @@ Error if all tests removed Stderr Should Be Empty Length Should Be ${SUITE.tests} 0 +Modifier can fix empty test and keyword + Run Tests --RunEmptySuite --PreRun ${CURDIR}/ModelModifier.py core/empty_testcase_and_uk.robot + ${tc} = Check Test Case Empty Test Case PASS ${EMPTY} + Check Log Message ${tc[0, 0]} Test body made non-empty by modifier + ${tc} = Check Test Case Empty User Keyword PASS ${EMPTY} + Check Log Message ${tc[0, 0, 0]} Keyword body made non-empty by modifier + Check Test Case Test name made non-empty by modifier PASS ${EMPTY} + Modifiers are used before normal configuration - ${result} = Run Tests - ... --include added --prerun ${CURDIR}/ModelModifier.py:CREATE:name=Created:tags=added ${TEST DATA} + Run Tests --include added --prerun ${CURDIR}/ModelModifier.py:CREATE:name=Created:tags=added ${TEST DATA} Stderr Should Be Empty Length Should Be ${SUITE.tests} 1 - ${tc} = Check test case Created FAIL Test contains no keywords. + ${tc} = Check Test Case Created + Check Log Message ${tc[0, 0]} Hello + Check Keyword Data ${tc[0]} BuiltIn.Log args=Hello, level=INFO Lists should be equal ${tc.tags} ${{['added']}} +Modifiers can use special Argument objects in arguments + ${tc} = Check Test Case Created + Check Log Message ${tc[1, 0]} Argument object! + Check Keyword Data ${tc[1]} BuiltIn.Log args=Argument object!, level=INFO + Check Keyword Data ${tc[2]} BuiltIn.Should Contain args=(1, 2, 3), item=2 + +Modifiers can pass positional and named arguments separately + ${tc} = Check Test Case Created + Check Log Message ${tc[3, 0]} Named args separately html=True + Check Keyword Data ${tc[3]} BuiltIn.Log args=Named args separately, html=True, level=\${{"INFO"}} + Modify FOR and IF Run Tests --prerun ${CURDIR}/ModelModifier.py misc/for_loops.robot misc/if_else.robot - ${tc} = Check Test Case For In Range Loop In Test - Check Log Message ${tc.body[0].body[0].body[0].msgs[0]} FOR - Check Log Message ${tc.body[0].body[1].body[0].msgs[0]} is - Check Log Message ${tc.body[0].body[2].body[0].msgs[0]} modified! + ${tc} = Check Test Case FOR IN RANGE + Check Log Message ${tc[0, 0, 0, 0]} FOR + Check Log Message ${tc[0, 1, 0, 0]} is + Check Log Message ${tc[0, 2, 0, 0]} modified! ${tc} = Check Test Case If structure - Check Log Message ${tc.body[0].body[0].body[0].msgs[0]} going here! + Check Log Message ${tc[1, 0, 0, 0]} going here! diff --git a/atest/robot/cli/rebot/invalid_usage.robot b/atest/robot/cli/rebot/invalid_usage.robot index c149bef3fc4..57b5a0acfb1 100644 --- a/atest/robot/cli/rebot/invalid_usage.robot +++ b/atest/robot/cli/rebot/invalid_usage.robot @@ -20,6 +20,10 @@ Non-Existing Input Existing And Non-Existing Input Reading XML source '.*nönéx.xml' failed: .* source=${INPUTFILE} nönéx.xml nonex2.xml +No tests in output + [Setup] Create File %{TEMPDIR}/no_tests.xml + Suite 'No Tests!' contains no tests. source=%{TEMPDIR}/no_tests.xml + Non-XML Input [Setup] Create File %{TEMPDIR}/invalid.robot Hello, world (\\[Fatal Error\\] .*: Content is not allowed in prolog.\\n)?Reading XML source '.*invalid.robot' failed: .* @@ -62,7 +66,7 @@ Invalid --RemoveKeywords *** Keywords *** Rebot Should Fail [Arguments] ${error} ${options}= ${source}=${INPUT} - ${result} = Run Rebot ${options} ${source} default options= output= - Should Be Equal As Integers ${result.rc} 252 + ${result} = Run Rebot ${options} ${source} default options= output=None + Should Be Equal ${result.rc} 252 type=int Should Be Empty ${result.stdout} Should Match Regexp ${result.stderr} ^\\[ .*ERROR.* \\] ${error}${USAGETIP}$ diff --git a/atest/robot/cli/rebot/log_level.robot b/atest/robot/cli/rebot/log_level.robot index 5677f86d996..4282351e68d 100644 --- a/atest/robot/cli/rebot/log_level.robot +++ b/atest/robot/cli/rebot/log_level.robot @@ -7,29 +7,29 @@ ${LOG NAME} logfile.html *** Test Cases *** By default all messages are included ${tc} = Rebot - Check Log Message ${tc.kws[0].msgs[0]} Arguments: [ 'Test 1' ] TRACE - Check Log Message ${tc.kws[0].msgs[1]} Test 1 INFO - Check Log Message ${tc.kws[0].msgs[2]} Return: None TRACE - Check Log Message ${tc.kws[1].msgs[0]} Arguments: [ 'Logging with debug level' | 'DEBUG' ] TRACE - Check Log Message ${tc.kws[1].msgs[1]} Logging with debug level DEBUG - Check Log Message ${tc.kws[1].msgs[2]} Return: None TRACE + Check Log Message ${tc[0, 0]} Arguments: [ 'Test 1' ] TRACE + Check Log Message ${tc[0, 1]} Test 1 INFO + Check Log Message ${tc[0, 2]} Return: None TRACE + Check Log Message ${tc[1, 0]} Arguments: [ 'Logging with debug level' | 'DEBUG' ] TRACE + Check Log Message ${tc[1, 1]} Logging with debug level DEBUG + Check Log Message ${tc[1, 2]} Return: None TRACE Min level should be 'TRACE' and default 'TRACE' Levels below given level are ignored ${tc} = Rebot --loglevel debug - Check Log Message ${tc.kws[0].msgs[0]} Test 1 INFO - Check Log Message ${tc.kws[1].msgs[0]} Logging with debug level DEBUG + Check Log Message ${tc[0, 0]} Test 1 INFO + Check Log Message ${tc[1, 0]} Logging with debug level DEBUG Min level should be 'DEBUG' and default 'DEBUG' ${tc} = Rebot -L INFO - Check Log Message ${tc.kws[0].msgs[0]} Test 1 INFO - Should Be Empty ${tc.kws[1].msgs} - Should Be Empty ${tc.kws[2].kws[0].msgs} + Check Log Message ${tc[0, 0]} Test 1 INFO + Should Be Empty ${tc[1].body} + Should Be Empty ${tc[2, 0].body} Min level should be 'INFO' and default 'INFO' All messages are ignored when NONE level is used ${tc} = Rebot --loglevel NONE - Should Be Empty ${tc.kws[0].msgs} - Should Be Empty ${tc.kws[1].msgs} + Should Be Empty ${tc[0].body} + Should Be Empty ${tc[1].body} Min level should be 'NONE' and default 'NONE' Configure visible log level @@ -40,7 +40,7 @@ Configure visible log level Rebot [Arguments] ${options}=${EMPTY} Run Rebot ${options} --log ${LOGNAME} ${INPUT FILE} - [Return] ${SUITE.tests[0]} + RETURN ${SUITE.tests[0]} Min level should be '${min}' and default '${default}' ${log}= Get file ${OUTDIR}/${LOG NAME} diff --git a/atest/robot/cli/rebot/rebot_cli_resource.robot b/atest/robot/cli/rebot/rebot_cli_resource.robot index 4701032a360..fb96e02d13f 100644 --- a/atest/robot/cli/rebot/rebot_cli_resource.robot +++ b/atest/robot/cli/rebot/rebot_cli_resource.robot @@ -18,7 +18,7 @@ Run tests to create input file for Rebot Run rebot and return outputs [Arguments] ${options} Create Output Directory - ${result} = Run Rebot --outputdir ${CLI OUTDIR} ${options} ${INPUT FILE} default options= output= + ${result} = Run Rebot --outputdir ${CLI OUTDIR} ${options} ${INPUT FILE} default options= output=None Should Be Equal ${result.rc} ${0} @{outputs} = List Directory ${CLI OUTDIR} - [Return] @{outputs} + RETURN @{outputs} diff --git a/atest/robot/cli/rebot/remove_keywords/all_passed_tag_and_name.robot b/atest/robot/cli/rebot/remove_keywords/all_passed_tag_and_name.robot index 5593caf2803..9c8de17fbaa 100644 --- a/atest/robot/cli/rebot/remove_keywords/all_passed_tag_and_name.robot +++ b/atest/robot/cli/rebot/remove_keywords/all_passed_tag_and_name.robot @@ -6,156 +6,201 @@ Resource remove_keywords_resource.robot *** Test Cases *** All Mode [Setup] Run Rebot and set My Suite --RemoveKeywords ALL 0 - Keyword Should Be Empty ${MY SUITE.setup} My Keyword Suite Setup - Keyword Should Contain Removal Message ${MY SUITE.setup} ${tc1} = Check Test Case Pass ${tc2} = Check Test Case Fail - Length Should Be ${tc1.body} 1 - Keyword Should Be Empty ${tc1.body[0]} My Keyword Pass - Length Should Be ${tc2.body} 2 - Keyword Should Be Empty ${tc2.body[0]} My Keyword Fail - Keyword Should Be Empty ${tc2.body[1]} BuiltIn.Fail Expected failure - Keyword Should Contain Removal Message ${tc2.body[1]} Fails the test with the given message and optionally alters its tags. + ${tc3} = Check Test Case Test with setup and teardown + Keyword Should Be Empty ${MY SUITE.setup} My Keyword Suite Setup + Keyword Should Contain Removal Message ${MY SUITE.setup} + Length Should Be ${tc1.body} 3 + Keyword Should Be Empty ${tc1[0]} My Keyword Pass + Length Should Be ${tc2.body} 2 + Keyword Should Be Empty ${tc2[0]} My Keyword Fail + Keyword Should Be Empty ${tc2[1]} BuiltIn.Fail Expected failure + Keyword Should Contain Removal Message ${tc2[1]} Expected failure + Keyword Should Be Empty ${tc3.setup} Test Setup + Keyword Should Contain Removal Message ${tc3.setup} + Keyword Should Be Empty ${tc3.teardown} Test Teardown + Keyword Should Contain Removal Message ${tc3.teardown} Warnings Are Removed In All Mode [Setup] Verify previous test and set My Suite All Mode 1 - Keyword Should Be Empty ${MY SUITE.setup} Warning in suite setup - Keyword Should Be Empty ${MY SUITE.teardown} Warning in suite teardown ${tc1} ${tc2}= Set Variable ${MY SUITE.tests[:2]} - Length Should Be ${tc1.body} 1 - Length Should Be ${tc2.body} 1 - Keyword Should Be Empty ${tc1.body[0]} Warning in test case - Keyword Should Be Empty ${tc2.body[0]} No warning + Keyword Should Be Empty ${MY SUITE.setup} Warning in suite setup + Keyword Should Be Empty ${MY SUITE.teardown} Warning in suite teardown + Length Should Be ${tc1.body} 1 + Keyword Should Be Empty ${tc1[0]} Warning in test case + Length Should Be ${tc2.body} 1 + Keyword Should Be Empty ${tc2[0]} No warning Logged Warnings Are Preserved In Execution Errors Errors Are Removed In All Mode - [Setup] Previous test should have passed Warnings Are Removed In All Mode ${tc} = Check Test Case Error in test case - Keyword Should Be Empty ${tc.body[0]} Error in test case + Keyword Should Be Empty ${tc[0]} Error in test case Logged Errors Are Preserved In Execution Errors IF/ELSE in All mode - [Setup] Previous test should have passed Errors Are Removed In All Mode ${tc} = Check Test Case IF structure - Length Should Be ${tc.body} 1 - Length Should Be ${tc.body[0].body} 3 - IF Branch Should Be Empty ${tc.body[0].body[0]} IF 'IF' == 'WRONG' - IF Branch Should Be Empty ${tc.body[0].body[1]} ELSE IF 'ELSE IF' == 'ELSE IF' - IF Branch Should Be Empty ${tc.body[0].body[2]} ELSE + Length Should Be ${tc.body} 2 + Length Should Be ${tc[1].body} 3 + IF Branch Should Be Empty ${tc[1, 0]} IF '\${x}' == 'wrong' + IF Branch Should Be Empty ${tc[1, 1]} ELSE IF '\${x}' == 'value' + IF Branch Should Be Empty ${tc[1, 2]} ELSE FOR in All mode - [Setup] Previous test should have passed IF/ELSE in All mode - ${tc} = Check Test Case FOR Loop In Test - Length Should Be ${tc.body} 1 - FOR Loop Should Be Empty ${tc.body[0]} IN - ${tc} = Check Test Case FOR IN RANGE Loop In Test - Length Should Be ${tc.body} 1 - FOR Loop Should Be Empty ${tc.body[0]} IN RANGE + ${tc1} = Check Test Case FOR + ${tc2} = Check Test Case FOR IN RANGE + Length Should Be ${tc1.body} 1 + FOR Loop Should Be Empty ${tc1[0]} IN + Length Should Be ${tc2.body} 1 + FOR Loop Should Be Empty ${tc2[0]} IN RANGE + +TRY/EXCEPT in All mode + ${tc} = Check Test Case Everything + Length Should Be ${tc.body} 1 + Length Should Be ${tc[0].body} 5 + TRY Branch Should Be Empty ${tc[0, 0]} TRY Ooops!
+ TRY Branch Should Be Empty ${tc[0, 1]} EXCEPT + TRY Branch Should Be Empty ${tc[0, 2]} EXCEPT + TRY Branch Should Be Empty ${tc[0, 3]} ELSE + TRY Branch Should Be Empty ${tc[0, 4]} FINALLY + +WHILE and VAR in All mode + ${tc} = Check Test Case WHILE loop executed multiple times + Length Should Be ${tc.body} 2 + Should Be Equal ${tc[1].type} WHILE + Should Be Empty ${tc[1].body} + Should Be Equal ${tc[1].message} *HTML* ${DATA REMOVED} + +VAR in All mode + ${tc1} = Check Test Case IF structure + ${tc2} = Check Test Case WHILE loop executed multiple times + Should Be Equal ${tc1[0].type} VAR + Should Be Empty ${tc1[0].body} + Should Be Equal ${tc1[0].message} *HTML* ${DATA REMOVED} + Should Be Equal ${tc2[0].type} VAR + Should Be Empty ${tc2[0].body} + Should Be Equal ${tc2[0].message} *HTML* ${DATA REMOVED} Passed Mode [Setup] Run Rebot and set My Suite --removekeywords passed 0 - Keyword Should Not Be Empty ${MY SUITE.setup} My Keyword Suite Setup ${tc1} = Check Test Case Pass ${tc2} = Check Test Case Fail - Length Should Be ${tc1.body} 1 - Keyword Should Be Empty ${tc1.body[0]} My Keyword Pass - Keyword Should Contain Removal Message ${tc1.body[0]} - Length Should Be ${tc2.body} 2 - Keyword Should Not Be Empty ${tc2.body[0]} My Keyword Fail - Keyword Should Not Be Empty ${tc2.body[1]} BuiltIn.Fail Expected failure + ${tc3} = Check Test Case Test with setup and teardown + Keyword Should Not Be Empty ${MY SUITE.setup} My Keyword Suite Setup + Length Should Be ${tc1.body} 3 + Keyword Should Be Empty ${tc1[0]} My Keyword Pass + Keyword Should Contain Removal Message ${tc1[0]} + Length Should Be ${tc2.body} 4 + Check Log message ${tc2[0]} Hello 'Fail', says listener! + Keyword Should Not Be Empty ${tc2[1]} My Keyword Fail + Keyword Should Not Be Empty ${tc2[2]} BuiltIn.Fail Expected failure + Check Log message ${tc2[3]} Bye 'Fail', says listener! + Keyword Should Be Empty ${tc3.setup} Test Setup + Keyword Should Contain Removal Message ${tc3.setup} + Keyword Should Be Empty ${tc3.teardown} Test Teardown + Keyword Should Contain Removal Message ${tc3.teardown} Warnings Are Not Removed In Passed Mode [Setup] Verify previous test and set My Suite Passed Mode 1 - Keyword Should Not Be Empty ${MY SUITE.setup} Warning in suite setup - Keyword Should Not Be Empty ${MY SUITE.teardown} Warning in suite teardown ${tc1} ${tc2}= Set Variable ${MY SUITE.tests[:2]} - Length Should Be ${tc1.body} 1 - Keyword Should Not Be Empty ${tc1.body[0]} Warning in test case - Keyword Should Not Be Empty ${tc1.body[0].body[0].body[0].body[0]} BuiltIn.Log Warning in \${where} WARN - Length Should Be ${tc2.body} 1 - Keyword Should Be Empty ${tc2.body[0]} No warning + Keyword Should Not Be Empty ${MY SUITE.setup} Warning in suite setup + Keyword Should Not Be Empty ${MY SUITE.teardown} Warning in suite teardown + Length Should Be ${tc1.body} 3 + Check Log message ${tc1[0]} Hello 'Warning in test case', says listener! + Keyword Should Not Be Empty ${tc1[1]} Warning in test case + Check Log message ${tc1[2]} Bye 'Warning in test case', says listener! + Keyword Should Not Be Empty ${tc1[1, 0, 0, 0]} BuiltIn.Log Warning in \${where} WARN + Length Should Be ${tc2.body} 1 + Keyword Should Be Empty ${tc2[0]} No warning Logged Warnings Are Preserved In Execution Errors Errors Are Not Removed In Passed Mode [Setup] Previous test should have passed Warnings Are Not Removed In Passed Mode ${tc} = Check Test Case Error in test case - Check Log Message ${tc.body[0].body[0].msgs[0]} Logged errors supported since 2.9 ERROR + Length Should Be ${tc.body} 3 + Check Log message ${tc[0]} Hello 'Error in test case', says listener! + Check Log Message ${tc[1, 0, 0]} Logged errors supported since 2.9 ERROR + Check Log message ${tc[2]} Bye 'Error in test case', says listener! Logged Errors Are Preserved In Execution Errors Name Mode [Setup] Run Rebot and set My Suite ... --removekeywords name:BuiltIn.Fail --RemoveK NAME:??_KEYWORD --RemoveK NaMe:*WARN*IN* --removek name:errorin* 0 - Keyword Should Be Empty ${MY SUITE.setup} My Keyword Suite Setup - Keyword Should Contain Removal Message ${MY SUITE.setup} ${tc1} = Check Test Case Pass ${tc2} = Check Test Case Fail - Length Should Be ${tc1.body} 1 - Keyword Should Be Empty ${tc1.body[0]} My Keyword Pass - Keyword Should Contain Removal Message ${tc1.body[0]} - Length Should Be ${tc2.body} 2 - Keyword Should Be Empty ${tc2.body[0]} My Keyword Fail - Keyword Should Contain Removal Message ${tc2.body[0]} - Keyword Should Be Empty ${tc2.body[1]} BuiltIn.Fail Expected failure - Keyword Should Contain Removal Message ${tc2.body[0]} + Keyword Should Be Empty ${MY SUITE.setup} My Keyword Suite Setup + Keyword Should Contain Removal Message ${MY SUITE.setup} + Length Should Be ${tc1.body} 5 + Keyword Should Be Empty ${tc1[1]} My Keyword Pass + Keyword Should Contain Removal Message ${tc1[1]} + Length Should Be ${tc2.body} 4 + Keyword Should Be Empty ${tc2[1]} My Keyword Fail + Keyword Should Contain Removal Message ${tc2[1]} + Keyword Should Be Empty ${tc2[2]} BuiltIn.Fail Expected failure Warnings Are Not Removed In Name Mode [Setup] Verify previous test and set My Suite Name Mode 1 - Keyword Should Not Be Empty ${MY SUITE.setup} Warning in suite setup - Keyword Should Not Be Empty ${MY SUITE.teardown} Warning in suite teardown ${tc1} ${tc2}= Set Variable ${MY SUITE.tests[:2]} - Length Should Be ${tc1.body} 1 - Length Should Be ${tc2.body} 1 - Keyword Should Not Be Empty ${tc1.body[0]} Warning in test case - Keyword Should Not Be Empty ${tc1.body[0].body[0].body[0].body[0]} BuiltIn.Log Warning in \${where} WARN - Keyword Should Be Empty ${tc2.body[0]} No warning + Keyword Should Not Be Empty ${MY SUITE.setup} Warning in suite setup + Keyword Should Not Be Empty ${MY SUITE.teardown} Warning in suite teardown + Length Should Be ${tc1.body} 3 + Length Should Be ${tc2.body} 3 + Keyword Should Not Be Empty ${tc1[1]} Warning in test case + Keyword Should Not Be Empty ${tc1[1, 0, 0, 0]} BuiltIn.Log Warning in \${where} WARN + Keyword Should Be Empty ${tc2[1]} No warning Logged Warnings Are Preserved In Execution Errors Errors Are Not Removed In Name Mode [Setup] Previous test should have passed Warnings Are Not Removed In Name Mode ${tc} = Check Test Case Error in test case - Check Log Message ${tc.body[0].body[0].msgs[0]} Logged errors supported since 2.9 ERROR + Check Log Message ${tc[1, 0, 0]} Logged errors supported since 2.9 ERROR Logged Errors Are Preserved In Execution Errors Tag Mode [Setup] Run Rebot and set My Suite --removekeywords tag:force --RemoveK TAG:warn 0 - Keyword Should Be Empty ${MY SUITE.setup} My Keyword Suite Setup - Keyword Should Contain Removal Message ${MY SUITE.setup} ${tc1} = Check Test Case Pass ${tc2} = Check Test Case Fail - Length Should Be ${tc1.body} 1 - Keyword Should Be Empty ${tc1.body[0]} My Keyword Pass - Keyword Should Contain Removal Message ${tc1.body[0]} - Length Should Be ${tc2.body} 2 - Keyword Should Be Empty ${tc2.body[0]} My Keyword Fail - Keyword Should Contain Removal Message ${tc2.body[0]} - Keyword Should Not Be Empty ${tc2.body[1]} BuiltIn.Fail Expected failure + Keyword Should Be Empty ${MY SUITE.setup} My Keyword Suite Setup + Keyword Should Contain Removal Message ${MY SUITE.setup} + Length Should Be ${tc1.body} 5 + Keyword Should Be Empty ${tc1[1]} My Keyword Pass + Keyword Should Contain Removal Message ${tc1[1]} + Length Should Be ${tc2.body} 4 + Keyword Should Be Empty ${tc2[1]} My Keyword Fail + Keyword Should Contain Removal Message ${tc2[1]} + Keyword Should Not Be Empty ${tc2[2]} BuiltIn.Fail Expected failure Warnings Are Not Removed In Tag Mode [Setup] Verify previous test and set My Suite Tag Mode 1 - Keyword Should Not Be Empty ${MY SUITE.setup} Warning in suite setup - Keyword Should Not Be Empty ${MY SUITE.teardown} Warning in suite teardown ${tc1} ${tc2}= Set Variable ${MY SUITE.tests[:2]} - Length Should Be ${tc1.body} 1 - Length Should Be ${tc2.body} 1 - Keyword Should Not Be Empty ${tc1.body[0]} Warning in test case - Keyword Should Not Be Empty ${tc1.body[0].body[0].body[0].body[0]} BuiltIn.Log Warning in \${where} WARN - Keyword Should Be Empty ${tc2.body[0]} No warning + Keyword Should Not Be Empty ${MY SUITE.setup} Warning in suite setup + Keyword Should Not Be Empty ${MY SUITE.teardown} Warning in suite teardown + Length Should Be ${tc1.body} 3 + Keyword Should Not Be Empty ${tc1[1]} Warning in test case + Keyword Should Not Be Empty ${tc1[1, 0, 0, 0]} BuiltIn.Log Warning in \${where} WARN + Length Should Be ${tc2.body} 3 + Keyword Should Be Empty ${tc2[1]} No warning Logged Warnings Are Preserved In Execution Errors Errors Are Not Removed In Tag Mode [Setup] Previous test should have passed Warnings Are Not Removed In Tag Mode ${tc} = Check Test Case Error in test case - Check Log Message ${tc.body[0].body[0].msgs[0]} Logged errors supported since 2.9 ERROR + Check Log Message ${tc[1, 0, 0]} Logged errors supported since 2.9 ERROR Logged Errors Are Preserved In Execution Errors *** Keywords *** Run Some Tests - ${suites} = Catenate + VAR ${options} + ... --listener AddMessagesToTestBody + VAR ${suites} ... misc/pass_and_fail.robot ... misc/warnings_and_errors.robot ... misc/if_else.robot ... misc/for_loops.robot - Create Output With Robot ${INPUTFILE} ${EMPTY} ${suites} + ... misc/try_except.robot + ... misc/while.robot + ... misc/setups_and_teardowns.robot + Create Output With Robot ${INPUTFILE} ${options} ${suites} Run Rebot And Set My Suite [Arguments] ${rebot params} ${suite index} @@ -169,9 +214,11 @@ Verify previous test and set My Suite Set Test Variable ${MY SUITE} ${SUITE.suites[${suite index}]} Keyword Should Contain Removal Message - [Arguments] ${keyword} ${doc}=${EMPTY} - ${expected} = Set Variable ${doc}\n\n_Keyword data removed using --RemoveKeywords option._ - Should Be Equal ${keyword.doc} ${expected.strip()} + [Arguments] ${keyword} ${message}= + IF $message + ${message} = Set Variable ${message}
+ END + Should Be Equal ${keyword.message} *HTML* ${message}${DATA REMOVED} Logged Warnings Are Preserved In Execution Errors Check Log Message ${ERRORS[1]} Warning in suite setup WARN diff --git a/atest/robot/cli/rebot/remove_keywords/for_loop_keywords.robot b/atest/robot/cli/rebot/remove_keywords/for_loop_keywords.robot index 10af4a534df..05bc9148bd2 100644 --- a/atest/robot/cli/rebot/remove_keywords/for_loop_keywords.robot +++ b/atest/robot/cli/rebot/remove_keywords/for_loop_keywords.robot @@ -4,55 +4,58 @@ Suite Teardown Remove File ${INPUTFILE} Resource remove_keywords_resource.robot *** Variables *** -${0 REMOVED} ${EMPTY} -${1 REMOVED} _1 passing step removed using --RemoveKeywords option._ -${2 REMOVED} _2 passing steps removed using --RemoveKeywords option._ -${3 REMOVED} _3 passing steps removed using --RemoveKeywords option._ -${4 REMOVED} _4 passing steps removed using --RemoveKeywords option._ +${1 REMOVED} 1 passing item removed using the --remove-keywords option. +${2 REMOVED} 2 passing items removed using the --remove-keywords option. +${3 REMOVED} 3 passing items removed using the --remove-keywords option. +${4 REMOVED} 4 passing items removed using the --remove-keywords option. *** Test Cases *** Passed Steps Are Removed Except The Last One ${tc}= Check Test Case Simple loop - Length Should Be ${tc.kws[1].kws} 1 - Should Be Equal ${tc.kws[1].doc} ${1 REMOVED} - Should Be Equal ${tc.kws[1].kws[0].status} PASS + Length Should Be ${tc[1].body} 1 + Should Be Equal ${tc[1].message} *HTML* ${1 REMOVED} + Should Be Equal ${tc[1, 0].status} PASS Failed Steps Are Not Removed ${tc}= Check Test Case Failure inside FOR 2 - Length Should Be ${tc.kws[0].kws} 1 - Should Be Equal ${tc.kws[0].doc} ${3 REMOVED} - Should Be Equal ${tc.kws[0].kws[0].name} \${num} = 4 - Should Be Equal ${tc.kws[0].kws[0].status} FAIL - Length Should Be ${tc.kws[0].kws[0].kws} 3 - Should Be Equal ${tc.kws[0].kws[0].kws[-1].status} NOT RUN + Length Should Be ${tc[0].body} 1 + Should Be Equal ${tc[0].message} *HTML* Failure with <4>
${3 REMOVED} + Should Be Equal ${tc[0, 0].type} ITERATION + Should Be Equal ${tc[0, 0].assign['\${num}']} 4 + Should Be Equal ${tc[0, 0].status} FAIL + Length Should Be ${tc[0, 0].body} 3 + Should Be Equal ${tc[0, 0, -1].status} NOT RUN Steps With Warning Are Not Removed ${tc}= Check Test Case Variables in values - Length Should Be ${tc.kws[0].kws} 2 - Should Be Equal ${tc.kws[0].doc} ${4 REMOVED} - Check Log Message ${tc.kws[0].kws[0].kws[-1].kws[0].msgs[0]} Presidential Candidate! WARN - Check Log Message ${tc.kws[0].kws[1].kws[-1].kws[0].msgs[0]} Presidential Candidate! WARN + Length Should Be ${tc[0].body} 2 + Should Be Equal ${tc[0].message} *HTML* ${4 REMOVED} + Check Log Message ${tc[0, 0, -1, 0, 0]} Presidential Candidate! WARN + Check Log Message ${tc[0, 1, -1, 0, 0]} Presidential Candidate! WARN Steps From Nested Loops Are Removed ${tc}= Check Test Case Nested Loop Syntax - Length Should Be ${tc.kws[0].kws} 1 - Should Be Equal ${tc.kws[0].doc} ${2 REMOVED} - Length Should Be ${tc.kws[0].kws[0].kws[1].kws} 1 - Should Be Equal ${tc.kws[0].kws[0].kws[1].doc} ${2 REMOVED} + Length Should Be ${tc[0].body} 1 + Should Be Equal ${tc[0].message} *HTML* ${2 REMOVED} + Length Should Be ${tc[0, 0, 1].body} 1 + Should Be Equal ${tc[0, 0, 1].message} *HTML* ${2 REMOVED} Steps From Loops In Keywords From Loops Are Removed ${tc}= Check Test Case Keyword with loop calling other keywords with loops - Length Should Be ${tc.kws[0].kws[0].kws} 1 - Should Be Equal ${tc.kws[0].kws[0].doc} ${0 REMOVED} - Length Should Be ${tc.kws[0].kws[0].kws[0].kws[0].kws[1].kws} 1 - Should Be Equal ${tc.kws[0].kws[0].kws[0].kws[0].kws[1].doc} ${1 REMOVED} - Length Should Be ${tc.kws[0].kws[0].kws[0].kws[1].kws[0].kws} 1 - Should Be Equal ${tc.kws[0].kws[0].kws[0].kws[1].kws[0].doc} ${1 REMOVED} + Length Should Be ${tc[0, 0].body} 1 + Should Be Equal ${tc[0, 0].message} This ought to be enough + Length Should Be ${tc[0, 0, 0, 0, 1].body} 1 + Should Be Equal ${tc[0, 0, 0, 0, 1].message} *HTML* ${1 REMOVED} + Length Should Be ${tc[0, 0, 0, 1, 0].body} 1 + Should Be Equal ${tc[0, 0, 0, 1, 0].message} *HTML* ${1 REMOVED} Empty Loops Are Handled Correctly ${tc}= Check Test Case Empty body - Should Be Empty ${tc.kws[0].kws} - Should Be Equal ${tc.kws[0].doc} ${0 REMOVED} + Should Be Equal ${tc[0].status} FAIL + Should Be Equal ${tc[0].message} FOR loop cannot be empty. + Should Be Equal ${tc[0, 0].type} ITERATION + Should Be Equal ${tc[0, 0].status} NOT RUN + Should Be Empty ${tc[0, 0].body} *** Keywords *** Remove For Loop Keywords With Rebot diff --git a/atest/robot/cli/rebot/remove_keywords/remove_keywords_resource.robot b/atest/robot/cli/rebot/remove_keywords/remove_keywords_resource.robot index 8e7bdb12364..f11bebb58fe 100644 --- a/atest/robot/cli/rebot/remove_keywords/remove_keywords_resource.robot +++ b/atest/robot/cli/rebot/remove_keywords/remove_keywords_resource.robot @@ -3,36 +3,41 @@ Resource rebot_resource.robot *** Variables *** ${INPUTFILE} %{TEMPDIR}${/}rebot-test-rmkw.xml +${DATA REMOVED} Content removed using the --remove-keywords option. *** Keywords *** Keyword Should Be Empty [Arguments] ${kw} ${name} @{args} - Should End With ${kw.doc} _Keyword data removed using --RemoveKeywords option._ + Should End With ${kw.message} ${DATA REMOVED} Check Keyword Name And Args ${kw} ${name} @{args} Should Be Empty ${kw.body} IF Branch Should Be Empty [Arguments] ${branch} ${type} ${condition}=${None} - Should Be Equal ${branch.doc} _Keyword data removed using --RemoveKeywords option._ - Should Be Equal ${branch.type} ${type} + Should Be Equal ${branch.message} *HTML* ${DATA REMOVED} + Should Be Equal ${branch.type} ${type} Should Be Equal ${branch.condition} ${condition} Should Be Empty ${branch.body} FOR Loop Should Be Empty [Arguments] ${loop} ${flavor} - Should Be Equal ${loop.doc} _Keyword data removed using --RemoveKeywords option._ - Should Be Equal ${loop.type} FOR - Should Be Equal ${loop.flavor} ${flavor} + Should Be Equal ${loop.message} *HTML* ${DATA REMOVED} + Should Be Equal ${loop.type} FOR + Should Be Equal ${loop.flavor} ${flavor} Should Be Empty ${loop.body} +TRY Branch Should Be Empty + [Arguments] ${branch} ${type} ${message}= + Should Be Equal ${branch.message} *HTML* ${message}${DATA REMOVED} + Should Be Equal ${branch.type} ${type} + Should Be Empty ${branch.body} + Keyword Should Not Be Empty [Arguments] ${kw} ${name} @{args} Check Keyword Name And Args ${kw} ${name} @{args} - ${num_keywords}= Get Length ${kw.kws} - ${num_messages}= Get Length ${kw.messages} - Should Be True ${num_keywords} + ${num_messages} > 0 + Should Not Be Empty ${kw.body} Check Keyword Name And Args [Arguments] ${kw} ${name} @{args} - Should Be Equal ${kw.name} ${name} + Should Be Equal ${kw.full_name} ${name} Lists Should Be Equal ${kw.args} ${args} diff --git a/atest/robot/cli/rebot/remove_keywords/wait_until_keyword_succeeds.robot b/atest/robot/cli/rebot/remove_keywords/wait_until_keyword_succeeds.robot index 7c90afd0766..8bdec7783e2 100644 --- a/atest/robot/cli/rebot/remove_keywords/wait_until_keyword_succeeds.robot +++ b/atest/robot/cli/rebot/remove_keywords/wait_until_keyword_succeeds.robot @@ -2,27 +2,28 @@ Suite Setup Remove Wait Until Keyword Succeeds with Rebot Resource remove_keywords_resource.robot -*** Variables *** -${DOC} Runs the specified keyword and retries if it fails. - *** Test Cases *** Last failing Step is not removed ${tc}= Check Number Of Keywords Fail Until The End 1 - Should Match ${tc.kws[0].doc} ${DOC}\n\n_? failing step* removed using --RemoveKeywords option._ + ${expected} = Catenate + ... [*]HTML[*] Keyword 'Fail' failed after retrying for 50 milliseconds. + ... The last error was: Not gonna happen
? failing item* removed using the --remove-keywords option. + Should Match ${tc[0].message} ${expected} Last passing Step is not removed ${tc}= Check Number Of Keywords Passes before timeout 2 - Should Be Equal ${tc.kws[0].doc} ${DOC}\n\n_1 failing step removed using --RemoveKeywords option._ + Should Be Equal ${tc[0].message} *HTML* 1 failing item removed using the --remove-keywords option. Steps containing warnings are not removed ${tc}= Check Number Of Keywords Warnings 3 - Should be Equal ${tc.kws[0].doc} ${DOC} + Should be Equal ${tc[0].message} ${EMPTY} Check Number Of Keywords One Warning 2 Nested Wait Until keywords are removed ${tc}= Check Test Case Nested - Length Should Be ${tc.kws[0].kws} 1 - Length Should Be ${tc.kws[0].kws[0].kws} 1 + Length Should Be ${tc[0].messages} 1 + Length Should Be ${tc[0].non_messages} 1 + Length Should Be ${tc[0, 0].body} 1 *** Keywords *** Remove Wait Until Keyword Succeeds with Rebot @@ -30,8 +31,7 @@ Remove Wait Until Keyword Succeeds with Rebot Run Rebot --removekeywords wuKs ${INPUTFILE} Check Number Of Keywords - [Arguments] ${test name} ${expected number} - ${tc}= Check Test Case ${test name} - Length Should Be ${tc.kws[0].kws} ${expected number} - [Return] ${tc} - + [Arguments] ${name} ${expected} + ${tc}= Check Test Case ${name} + Length Should Be ${tc[0].non_messages} ${expected} + RETURN ${tc} diff --git a/atest/robot/cli/rebot/remove_keywords/while_loop_keywords.robot b/atest/robot/cli/rebot/remove_keywords/while_loop_keywords.robot index efd72cc711a..ea36561aef8 100644 --- a/atest/robot/cli/rebot/remove_keywords/while_loop_keywords.robot +++ b/atest/robot/cli/rebot/remove_keywords/while_loop_keywords.robot @@ -1,39 +1,35 @@ *** Settings *** -Suite Setup Remove For Loop Keywords With Rebot +Suite Setup Remove WHILE Keywords With Rebot Suite Teardown Remove File ${INPUTFILE} Resource remove_keywords_resource.robot *** Variables *** -${0 REMOVED} ${EMPTY} -${1 REMOVED} _1 passing step removed using --RemoveKeywords option._ -${2 REMOVED} _2 passing steps removed using --RemoveKeywords option._ -${3 REMOVED} _3 passing steps removed using --RemoveKeywords option._ -${4 REMOVED} _4 passing steps removed using --RemoveKeywords option._ +${2 REMOVED} 2 passing items removed using the --remove-keywords option. +${4 REMOVED} 4 passing items removed using the --remove-keywords option. *** Test Cases *** Passed Steps Are Removed Except The Last One ${tc}= Check Test Case Loop executed multiple times - Length Should Be ${tc.kws[0].kws} 1 - Should Be Equal ${tc.kws[0].doc} ${4 REMOVED} - Should Be Equal ${tc.kws[0].kws[0].status} PASS + Length Should Be ${tc[0].body} 1 + Should Be Equal ${tc[0].message} *HTML* ${4 REMOVED} + Should Be Equal ${tc[0, 0].status} PASS Failed Steps Are Not Removed ${tc}= Check Test Case Execution fails after some loops - Length Should Be ${tc.kws[0].kws} 1 - Should Be Equal ${tc.kws[0].doc} ${2 REMOVED} - Should Be Equal ${tc.kws[0].kws[0].status} FAIL - Length Should Be ${tc.kws[0].kws[0].kws} 3 - Should Be Equal ${tc.kws[0].kws[0].kws[-1].status} NOT RUN + Length Should Be ${tc[0].body} 1 + Should Be Equal ${tc[0].message} *HTML* Oh no, got 4
${2 REMOVED} + Should Be Equal ${tc[0, 0].status} FAIL + Length Should Be ${tc[0, 0].body} 3 + Should Be Equal ${tc[0, 0, -1].status} NOT RUN Steps From Nested Loops Are Removed ${tc}= Check Test Case Loop in loop - Length Should Be ${tc.kws[0].kws} 1 - Should Be Equal ${tc.kws[0].doc} ${4 REMOVED} - Length Should Be ${tc.kws[0].kws[0].kws[2].kws} 1 - Should Be Equal ${tc.kws[0].kws[0].kws[2].doc} ${2 REMOVED} - + Length Should Be ${tc[0].body} 1 + Should Be Equal ${tc[0].message} *HTML* ${4 REMOVED} + Length Should Be ${tc[0, 0, 2].body} 1 + Should Be Equal ${tc[0, 0, 2].message} *HTML* ${2 REMOVED} *** Keywords *** -Remove For Loop Keywords With Rebot +Remove WHILE Keywords With Rebot Create Output With Robot ${INPUTFILE} ${EMPTY} running/while/while.robot Run Rebot --removekeywords while ${INPUTFILE} diff --git a/atest/robot/cli/rebot/suite_name_doc_and_metadata.robot b/atest/robot/cli/rebot/suite_name_doc_and_metadata.robot index 6fc5b0e9f6a..861dddf3cfe 100644 --- a/atest/robot/cli/rebot/suite_name_doc_and_metadata.robot +++ b/atest/robot/cli/rebot/suite_name_doc_and_metadata.robot @@ -34,14 +34,20 @@ Documentation and metadata from external file Check All Names ${SUITE} Normal Should Be Equal ${SUITE.doc} ${value.rstrip()} Should Be Equal ${SUITE.metadata['name']} ${value.rstrip()} - Run Rebot --doc " ${path}" --metadata "name: ${path}" ${INPUT FILE} + Run Rebot --doc " ${path}" --metadata "name: ${path}" -M dir:. ${INPUT FILE} Check All Names ${SUITE} Normal Should Be Equal ${SUITE.doc} ${path} Should Be Equal ${SUITE.metadata['name']} ${path} + Should Be Equal ${SUITE.metadata['dir']} . Invalid external file - Run Rebot Without Processing Output --doc . ${INPUT FILE} - Stderr Should Match [[] ERROR []] Invalid value for option '--doc': Reading documentation from '.' failed: *${USAGE TIP}\n + [Tags] no-windows + ${path} = Normalize Path %{TEMPDIR}/file.txt + Create File ${path} + Evaluate os.chmod('${path}', 0) + Run Rebot Without Processing Output --doc ${path} ${INPUT FILE} + Stderr Should Match [[] ERROR []] Invalid value for option '--doc': Reading documentation from '${path}' failed: *${USAGE TIP}\n + [Teardown] Remove File ${path} *** Keywords *** Check All Names diff --git a/atest/robot/cli/runner/ROBOT_OPTIONS.robot b/atest/robot/cli/runner/ROBOT_OPTIONS.robot index 731d3c5a052..60a569aec2b 100644 --- a/atest/robot/cli/runner/ROBOT_OPTIONS.robot +++ b/atest/robot/cli/runner/ROBOT_OPTIONS.robot @@ -8,10 +8,10 @@ Use defaults Run Tests ${EMPTY} misc/pass_and_fail.robot Should Be Equal ${SUITE.name} Default ${tc} = Check Test Tags Pass force pass default with spaces - Should Be Equal ${tc.kws[0].kws[0].status} NOT RUN + Should Be Equal ${tc[0, 0].status} NOT RUN Override defaults Run Tests -N Given -G given --nodryrun misc/pass_and_fail.robot Should Be Equal ${SUITE.name} Given ${tc} = Check Test Tags Pass force pass default with spaces given - Should Be Equal ${tc.kws[0].kws[0].status} PASS + Should Be Equal ${tc[0, 0].status} PASS diff --git a/atest/robot/cli/runner/argumentfile.robot b/atest/robot/cli/runner/argumentfile.robot index 122474cfc5d..d71c7519296 100644 --- a/atest/robot/cli/runner/argumentfile.robot +++ b/atest/robot/cli/runner/argumentfile.robot @@ -33,7 +33,7 @@ Argument File Two Argument Files Create Argument File ${ARGFILE} --metadata A1:Value1 --metadata A2:to be overridden Create Argument File ${ARGFILE2} --metadata A2:Value2 - ${result} = Run Tests -A ${ARGFILE} --ArgumentFile ${ARGFILE2} ${TESTFILE} + ${result} = Run Tests -A ${ARGFILE} --Argument-File ${ARGFILE2} ${TESTFILE} Execution Should Have Succeeded ${result} Should Be Equal ${SUITE.metadata['A1']} Value1 Should Be Equal ${SUITE.metadata['A2']} Value2 diff --git a/atest/robot/cli/runner/cli_resource.robot b/atest/robot/cli/runner/cli_resource.robot index b538b718a50..9d060098af3 100644 --- a/atest/robot/cli/runner/cli_resource.robot +++ b/atest/robot/cli/runner/cli_resource.robot @@ -24,20 +24,24 @@ Output Directory Should Be Empty Run Some Tests [Arguments] ${options}=-l none -r none - ${result} = Run Tests -d ${CLI OUTDIR} ${options} ${TEST FILE} default options= output= + ${result} = Run Tests -d ${CLI OUTDIR} ${options} ${TEST FILE} default options= output=None Should Be Equal ${result.rc} ${0} - [Return] ${result} + RETURN ${result} Tests Should Pass Without Errors [Arguments] ${options} ${datasource} ${result} = Run Tests ${options} ${datasource} Should Be Equal ${SUITE.status} PASS Should Be Empty ${result.stderr} - [Return] ${result} + RETURN ${result} Run Should Fail - [Arguments] ${options} ${error} - ${result} = Run Tests ${options} default options= output= + [Arguments] ${options} ${error} ${regexp}=False + ${result} = Run Tests ${options} default options= output=None Should Be Equal As Integers ${result.rc} 252 Should Be Empty ${result.stdout} - Should Match Regexp ${result.stderr} ^\\[ .*ERROR.* \\] ${error}${USAGETIP}$ + IF ${regexp} + Should Match Regexp ${result.stderr} ^\\[ ERROR \\] ${error}${USAGETIP}$ + ELSE + Should Be Equal ${result.stderr} [ ERROR ] ${error}${USAGETIP} + END diff --git a/atest/robot/cli/runner/debugfile.robot b/atest/robot/cli/runner/debugfile.robot index 984e3e8773b..1fb5462bcba 100644 --- a/atest/robot/cli/runner/debugfile.robot +++ b/atest/robot/cli/runner/debugfile.robot @@ -3,7 +3,7 @@ Test Setup Create Output Directory Resource cli_resource.robot *** Variables *** -${TIMESTAMP} ???????? ??:??:??.??? +${TIMESTAMP} 20??-??-?? ??:??:??.?????? *** Test Cases *** Debugfile @@ -23,8 +23,8 @@ Debugfile Debug file should contain ${content} + END SUITE: Normal Syslog Should Contain DebugFile: DeBug.TXT ${path} = Set Variable [:.\\w /\\\\~+-]*DeBug\\.TXT - Stdout Should Match Regexp (?s).*Debug: {3}${path}.* - Syslog Should Match Regexp (?s).*Debug: ${path}.* + Stdout Should Match Regexp .*Debug: {3}${path}.* + Syslog Should Match Regexp .*Debug: ${path}.* Debugfile Log Level Should Always Be Debug [Documentation] --loglevel option should not affect what's written to debugfile @@ -45,8 +45,8 @@ Debugfile timestamps are accurate ${tc} = Check Test Case LibraryAddsTimestampAsInteger ${content} = Get file ${CLI OUTDIR}/debug.txt Debug file should contain ${content} - ... ${tc.kws[0].msgs[0].timestamp} - INFO - Known timestamp - ... ${tc.kws[0].msgs[1].timestamp} - INFO - Current + ... ${tc[0, 0].timestamp} - INFO - Known timestamp + ... ${tc[0, 1].timestamp} - INFO - Current Writing Non-ASCII To Debugfile [Documentation] Tests also that '.txt' is appended if no extension given @@ -55,7 +55,7 @@ Writing Non-ASCII To Debugfile Stderr Should Be Empty ${content} = Get File ${CLI OUTDIR}/debug.txt Debugfile should contain ${content} ${TIMESTAMP} - FAIL - Circle is 360°, Hyvää üötä, উৄ ৰ ৺ ট ৫ ৪ হ - Debugfile should contain ${content} ${TIMESTAMP} - INFO - +- START TEST: Ñöñ-ÄŚÇÏÏ Tëśt äņd Këywörd Nämës, Спасибо ? ? + Debugfile should contain ${content} ${TIMESTAMP} - INFO - +- START TEST: Ñöñ-ÄŚÇÏÏ Tëśt äņd Këywörd Nämës, Спасибо No Debugfile Run Tests Without Processing Output --outputdir ${CLI OUTDIR} --debugfile NoNe -o o.xml ${TESTFILE} diff --git a/atest/robot/cli/runner/exit_on_error.robot b/atest/robot/cli/runner/exit_on_error.robot index 23538336dbd..b97367680f1 100644 --- a/atest/robot/cli/runner/exit_on_error.robot +++ b/atest/robot/cli/runner/exit_on_error.robot @@ -64,6 +64,6 @@ Teardowns not executed Teardowns executed [Arguments] ${name} ${suite} = Get Test Suite ${name} - Should Be Equal ${suite.teardown.name} BuiltIn.No Operation + Should Be Equal ${suite.teardown.full_name} BuiltIn.No Operation ${tc} = Check Test Case ${name} FAIL ${MESSAGE} - Should Be Equal ${tc.teardown.name} BuiltIn.No Operation + Should Be Equal ${tc.teardown.full_name} BuiltIn.No Operation diff --git a/atest/robot/cli/runner/exit_on_failure.robot b/atest/robot/cli/runner/exit_on_failure.robot index 18cdfa863af..c11932cfe3b 100644 --- a/atest/robot/cli/runner/exit_on_failure.robot +++ b/atest/robot/cli/runner/exit_on_failure.robot @@ -38,9 +38,9 @@ Imports in subsequent suites are skipped Correct Suite Teardown Is Executed When ExitOnFailure Is Used [Setup] Run Tests -X misc/suites ${tsuite} = Get Test Suite Suites - Should Be Equal ${tsuite.teardown.name} BuiltIn.Log + Should Be Equal ${tsuite.teardown.full_name} BuiltIn.Log ${tsuite} = Get Test Suite Fourth - Should Be Equal ${tsuite.teardown.name} BuiltIn.Log + Should Be Equal ${tsuite.teardown.full_name} BuiltIn.Log ${tsuite} = Get Test Suite Tsuite3 Teardown Should Not Be Defined ${tsuite} @@ -73,12 +73,12 @@ Suite setup fails [Setup] Run Tests ... --ExitOnFail --variable SUITE_SETUP:Fail ... misc/setups_and_teardowns.robot misc/pass_and_fail.robot - Test Should Not Have Been Run Test with setup and teardown - Test Should Not Have Been Run Test with failing setup - Test Should Not Have Been Run Test with failing teardown - Test Should Not Have Been Run Failing test with failing teardown - Test Should Not Have Been Run Pass - Test Should Not Have Been Run Fail + Parent Setup Should Have Failed Test with setup and teardown + Test Should Not Have Been Run Test with failing setup + Test Should Not Have Been Run Test with failing teardown + Test Should Not Have Been Run Failing test with failing teardown + Test Should Not Have Been Run Pass + Test Should Not Have Been Run Fail Suite teardown fails [Setup] Run Tests @@ -96,6 +96,11 @@ Failure set by listener can initiate exit-on-failure Test Should Not Have Been Run Fail *** Keywords *** +Parent Setup Should Have Failed + [Arguments] ${name} + ${tc} = Check Test Case ${name} FAIL Parent suite setup failed:\nAssertionError + Should Not Contain ${tc.tags} robot:exit + Test Should Not Have Been Run [Arguments] ${name} ${tc} = Check Test Case ${name} FAIL ${EXIT ON FAILURE} diff --git a/atest/robot/cli/runner/exit_on_failure_with_skip_on_failure.robot b/atest/robot/cli/runner/exit_on_failure_with_skip_on_failure.robot new file mode 100644 index 00000000000..44ccf986f97 --- /dev/null +++ b/atest/robot/cli/runner/exit_on_failure_with_skip_on_failure.robot @@ -0,0 +1,49 @@ +*** Settings *** +Resource atest_resource.robot + +*** Test Cases *** +Exit-on-failure is not initiated if test fails and skip-on-failure is active + Run Tests --exit-on-failure --skip-on-failure skip-on-failure --include skip-on-failure running/skip/skip.robot + Should Contain Tests ${SUITE} + ... Skipped with --SkipOnFailure + ... Skipped with --SkipOnFailure when failure in setup + ... Skipped with --SkipOnFailure when failure in teardown + +Exit-on-failure is not initiated if suite setup fails and skip-on-failure is active with all tests + Run Tests --exit-on-failure --skip-on-failure tag1 --variable SUITE_SETUP:Fail + ... misc/setups_and_teardowns.robot misc/pass_and_fail.robot misc/pass_and_fail.robot + VAR ${message} + ... Failed test skipped using 'tag1' tag. + ... + ... Original failure: + ... Parent suite setup failed: + ... AssertionError + ... separator=\n + Should Contain Tests ${SUITE.suites[0]} + ... Test with setup and teardown=SKIP:${message} + ... Test with failing setup=SKIP:${message} + ... Test with failing teardown=SKIP:${message} + ... Failing test with failing teardown=SKIP:${message} + Should Contain Tests ${SUITE.suites[1]} + ... Pass + ... Fail + Should Contain Tests ${SUITE.suites[2]} + ... Pass=FAIL:Failure occurred and exit-on-failure mode is in use. + ... Fail=FAIL:Failure occurred and exit-on-failure mode is in use. + +Exit-on-failure is initiated if suite setup fails and skip-on-failure is not active with all tests + Run Tests --exit-on-failure --skip-on-failure tag2 --variable SUITE_SETUP:Fail + ... misc/setups_and_teardowns.robot misc/pass_and_fail.robot + VAR ${prefix} + ... Failed test skipped using 'tag2' tag. + ... + ... Original failure: + ... separator=\n + Should Contain Tests ${SUITE.suites[0]} + ... Test with setup and teardown=SKIP:${prefix}\nParent suite setup failed:\nAssertionError + ... Test with failing setup=FAIL:Parent suite setup failed:\nAssertionError + ... Test with failing teardown=SKIP:${prefix}\nFailure occurred and exit-on-failure mode is in use. + ... Failing test with failing teardown=SKIP:${prefix}\nFailure occurred and exit-on-failure mode is in use. + Should Contain Tests ${SUITE.suites[1]} + ... Pass=FAIL:Failure occurred and exit-on-failure mode is in use. + ... Fail=FAIL:Failure occurred and exit-on-failure mode is in use. diff --git a/atest/robot/cli/runner/extension.robot b/atest/robot/cli/runner/extension.robot index 659d63a6b06..e124abfc09a 100644 --- a/atest/robot/cli/runner/extension.robot +++ b/atest/robot/cli/runner/extension.robot @@ -7,11 +7,11 @@ ${DATA FORMATS} ${DATADIR}/parsing/data_formats *** Test Cases *** One extension - --extension robot 27 + --extension robot 29 --EXTENSION .TXT 23 Multiple extensions - -F robot:txt:.ROBOT 50 + -F robot:txt:.ROBOT 52 Any extension is accepted --extension bar 1 diff --git a/atest/robot/cli/runner/included_files.robot b/atest/robot/cli/runner/included_files.robot new file mode 100644 index 00000000000..681442d40b1 --- /dev/null +++ b/atest/robot/cli/runner/included_files.robot @@ -0,0 +1,37 @@ +*** Settings *** +Test Template Expected number of tests should be run +Resource atest_resource.robot + +*** Test Cases *** +File name + --parseinclude sample.robot 18 + +File path + -I ${DATADIR}/parsing/data_formats${/}robot${/}SAMPLE.robot 18 + +Pattern with name + --ParseInclude *.robot --parse-include sample.rb? -I no.match 47 + +Pattern with path + --parse-include ${DATADIR}/parsing/data_formats/*/[st]???le.ROBOT 18 + +Single '*' is not recursive + --parse-include ${DATADIR}/*/sample.robot 0 + +Recursive glob requires '**' + --parse-include ${DATADIR}/**/sample.robot 18 + +Directories are recursive + --parse-include ${DATADIR}/parsing/data_formats/robot 20 + --parse-include ${DATADIR}/parsing/*/robot 20 + +Non-standard files matching patterns with extension are parsed + --parse-include *.rst 20 + --parse-include ${DATADIR}/parsing/**/*.rst 20 + --parse-include ${DATADIR}/parsing/data_formats/rest 1 + +*** Keywords *** +Expected number of tests should be run + [Arguments] ${options} ${expected} + Run Tests ${options} --run-empty-suite ${DATADIR}/parsing/data_formats + Should Be Equal As Integers ${SUITE.test_count} ${expected} diff --git a/atest/robot/cli/runner/invalid_usage.robot b/atest/robot/cli/runner/invalid_usage.robot index b23b44cfa2a..739b6ea9be9 100644 --- a/atest/robot/cli/runner/invalid_usage.robot +++ b/atest/robot/cli/runner/invalid_usage.robot @@ -3,25 +3,30 @@ Test Setup Create Output Directory Resource cli_resource.robot Test Template Run Should Fail +*** Variables *** +${VALID} ${DATA DIR}/${TEST FILE} + *** Test Cases *** No Input - ${EMPTY} Expected at least 1 argument, got 0\\. + ${EMPTY} Expected at least 1 argument, got 0. Argument File Option Without Value As Last Argument --argumentfile option --argumentfile requires argument Non-Existing Input - nonexisting.robot Parsing 'nonexisting\\.robot' failed: File or directory to execute does not exist\\. + nonexisting.robot Parsing '${EXECDIR}${/}nonexisting.robot' failed: File or directory to execute does not exist. Non-Existing Input With Non-Ascii Characters - eitäällä.robot Parsing 'eitäällä\\.robot' failed: File or directory to execute does not exist\\. + nö.röböt ${VALID} bäd + ... Parsing '${EXECDIR}${/}nö.röböt' and '${EXECDIR}${/}bäd' failed: File or directory to execute does not exist. Invalid Output Directory [Setup] Create File %{TEMPDIR}/not-dir - -d %{TEMPDIR}/not-dir/dir ${DATADIR}/${TEST FILE} - ... Creating output file directory '.*not-dir.dir' failed: .* - -d %{TEMPDIR}/not-dir/dir -o %{TEMPDIR}/out.xml ${DATADIR}/${TEST FILE} - ... Creating report file directory '.*not-dir.dir' failed: .* + -d %{TEMPDIR}/not-dir/dir ${VALID} + ... Creating output file directory '.*not-dir.dir' failed: .* regexp=True + -d %{TEMPDIR}/not-dir/dir -o %{TEMPDIR}/out.xml ${VALID} + ... Creating report file directory '.*not-dir.dir' failed: .* regexp=True + [Teardown] Remove File %{TEMPDIR}/not-dir Invalid Options --invalid option option --invalid not recognized @@ -37,12 +42,12 @@ Invalid --TagStatLink Invalid --RemoveKeywords --removekeywords wuks --removek name:xxx --RemoveKeywords Invalid tests.robot - ... Invalid value for option '--removekeywords'. Expected 'ALL', 'PASSED', 'NAME:', 'TAG:', 'FOR' or 'WUKS', got 'Invalid'. + ... Invalid value for option '--removekeywords': Expected 'ALL', 'PASSED', 'NAME:', 'TAG:', 'FOR' or 'WUKS', got 'Invalid'. Invalid --loglevel --loglevel bad tests.robot - ... Invalid value for option '--loglevel': Invalid level 'BAD'. + ... Invalid value for option '--loglevel': Invalid log level 'BAD'. --loglevel INFO:INV tests.robot - ... Invalid value for option '--loglevel': Invalid level 'INV'. + ... Invalid value for option '--loglevel': Invalid log level 'INV'. -L INFO:DEBUG tests.robot ... Invalid value for option '--loglevel': Level in log 'DEBUG' is lower than execution level 'INFO'. diff --git a/atest/robot/cli/runner/log_level.robot b/atest/robot/cli/runner/log_level.robot index 8f11cb8a8a7..76531894932 100644 --- a/atest/robot/cli/runner/log_level.robot +++ b/atest/robot/cli/runner/log_level.robot @@ -1,71 +1,73 @@ *** Settings *** -Documentation Tests for setting log level from command line with --loglevel option. Setting log level while executing tests (BuiltIn.Set Log Level) is tested with BuiltIn library keywords. -Resource atest_resource.robot +Documentation Tests for setting log level from command line with --loglevel option. +... Setting log level while executing tests (BuiltIn.Set Log Level) is +... tested with BuiltIn library keywords. +Resource atest_resource.robot *** Variables *** -${TESTDATA} misc/pass_and_fail.robot -${LOG NAME} logfile.html +${TESTDATA} misc/pass_and_fail.robot +${LOG NAME} logfile.html *** Test Cases *** No Log Level Given - [Documentation] Default level of INFO should be used - Run Tests ${EMPTY} ${TESTDATA} - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[0]} Hello says "Pass"! INFO - Should Be Equal As Integers ${SUITE.tests[0].kws[0].kws[1].message_count} 0 - Check Log Message ${SUITE.tests[1].kws[1].msgs[0]} Expected failure FAIL + [Documentation] Default level of INFO should be used + Run Tests ${EMPTY} ${TESTDATA} + Check Log Message ${SUITE.tests[0][0, 0, 0]} Hello says "Pass"! INFO + Should Be Empty ${SUITE.tests[0][0, 1].messages} + Check Log Message ${SUITE.tests[1][1, 0]} Expected failure FAIL Trace Level - Run Tests --loglevel TRACE ${TESTDATA} + Run Tests --loglevel TRACE ${TESTDATA} Should Log On Trace Level Debug Level - Run Tests --loglevel debug --log ${LOG NAME} ${TESTDATA} + Run Tests --loglevel debug --log ${LOG NAME} ${TESTDATA} Should Log On Debug Level Min level should be 'DEBUG' and default 'DEBUG' Debug Level With Default Info - Run Tests --loglevel dEBug:iNfo --log ${LOG NAME} ${TESTDATA} + Run Tests --loglevel dEBug:iNfo --log ${LOG NAME} ${TESTDATA} Should Log On Debug Level Min level should be 'DEBUG' and default 'INFO' Trace Level With Default Debug - Run Tests --loglevel trace:Debug --log ${LOG NAME} ${TESTDATA} + Run Tests --loglevel trace:Debug --log ${LOG NAME} ${TESTDATA} Should Log On Trace Level Min level should be 'TRACE' and default 'DEBUG' Info Level - Run Tests -L InFo ${TESTDATA} - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[0]} Hello says "Pass"! INFO - Should Be Equal As Integers ${SUITE.tests[0].kws[0].kws[1].message_count} 0 - Check Log Message ${SUITE.tests[1].kws[1].msgs[0]} Expected failure FAIL + Run Tests -L InFo ${TESTDATA} + Check Log Message ${SUITE.tests[0][0, 0, 0]} Hello says "Pass"! INFO + Should Be Empty ${SUITE.tests[0][0, 1].messages} + Check Log Message ${SUITE.tests[1][1, 0]} Expected failure FAIL Warn Level - Run Tests --loglevel WARN --variable LEVEL1:WARN --variable LEVEL2:INFO ${TESTDATA} - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[0]} Hello says "Pass"! WARN - Should Be Equal As Integers ${SUITE.tests[0].kws[0].kws[1].message_count} 0 - Check Log Message ${SUITE.tests[1].kws[1].msgs[0]} Expected failure FAIL + Run Tests --loglevel WARN --variable LEVEL1:WARN --variable LEVEL2:INFO ${TESTDATA} + Check Log Message ${SUITE.tests[0][0, 0, 0]} Hello says "Pass"! WARN + Should Be Empty ${SUITE.tests[0][0, 1].messages} + Check Log Message ${SUITE.tests[1][1, 0]} Expected failure FAIL Warnings Should Be Written To Syslog - Should Be Equal ${PREV TEST NAME} Warn Level - Check Log Message ${ERRORS.msgs[0]} Hello says "Suite Setup"! WARN - Check Log Message ${ERRORS.msgs[1]} Hello says "Pass"! WARN - Check Log Message ${ERRORS.msgs[2]} Hello says "Fail"! WARN - Should Be True ${ERRORS.msg_count} == 3 - Syslog Should Contain | WARN \ | Hello says "Suite Setup"! - Syslog Should Contain | WARN \ | Hello says "Pass"! - Syslog Should Contain | WARN \ | Hello says "Fail"! + Should Be Equal ${PREV TEST NAME} Warn Level + Check Log Message ${ERRORS[0]} Hello says "Suite Setup"! WARN + Check Log Message ${ERRORS[1]} Hello says "Pass"! WARN + Check Log Message ${ERRORS[2]} Hello says "Fail"! WARN + Length Should Be ${ERRORS.messages} 3 + Syslog Should Contain | WARN \ | Hello says "Suite Setup"! + Syslog Should Contain | WARN \ | Hello says "Pass"! + Syslog Should Contain | WARN \ | Hello says "Fail"! Error Level - Run Tests --loglevel ERROR --variable LEVEL1:ERROR --variable LEVEL2:WARN ${TESTDATA} - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[0]} Hello says "Pass"! ERROR - Should Be Equal As Integers ${SUITE.tests[0].kws[0].kws[1].message_count} 0 - Check Log Message ${SUITE.tests[1].kws[1].msgs[0]} Expected failure FAIL + Run Tests --loglevel ERROR --variable LEVEL1:ERROR --variable LEVEL2:WARN ${TESTDATA} + Check Log Message ${SUITE.tests[0][0, 0, 0]} Hello says "Pass"! ERROR + Should Be Empty ${SUITE.tests[0][0, 1].messages} + Check Log Message ${SUITE.tests[1][1, 0]} Expected failure FAIL None Level - Run Tests --loglevel NONE --log ${LOG NAME} --variable LEVEL1:ERROR --variable LEVEL2:WARN ${TESTDATA} - Should Be Equal As Integers ${SUITE.tests[0].kws[0].kws[0].message_count} 0 - Should Be Equal As Integers ${SUITE.tests[0].kws[0].kws[1].message_count} 0 - Should Be Equal As Integers ${SUITE.tests[1].kws[1].message_count} 0 + Run Tests --loglevel NONE --log ${LOG NAME} --variable LEVEL1:ERROR --variable LEVEL2:WARN ${TESTDATA} + Should Be Empty ${SUITE.tests[0][0, 0].message} + Should Be Empty ${SUITE.tests[0][0, 1].messages} + Should Be Empty ${SUITE.tests[1][1].messages} Min level should be 'NONE' and default 'NONE' *** Keywords *** @@ -75,14 +77,14 @@ Min level should be '${min}' and default '${default}' Should contain ${log} "defaultLevel":"${default}" Should Log On Debug Level - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[0]} Hello says "Pass"! INFO - Check Log Message ${SUITE.tests[0].kws[0].kws[1].msgs[0]} Debug message DEBUG - Check Log Message ${SUITE.tests[1].kws[1].msgs[0]} Expected failure FAIL + Check Log Message ${SUITE.tests[0][0, 0, 0]} Hello says "Pass"! INFO + Check Log Message ${SUITE.tests[0][0, 1, 0]} Debug message DEBUG + Check Log Message ${SUITE.tests[1][1, 0]} Expected failure FAIL Should Log On Trace Level - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[0]} Arguments: [ 'Hello says "Pass"!' | 'INFO' ] TRACE - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[1]} Hello says "Pass"! INFO - Check Log Message ${SUITE.tests[0].kws[0].kws[0].msgs[2]} Return: None TRACE - Check Log Message ${SUITE.tests[0].kws[0].kws[1].msgs[1]} Debug message DEBUG - Check Log Message ${SUITE.tests[1].kws[1].msgs[0]} Arguments: [ 'Expected failure' ] TRACE - Check Log Message ${SUITE.tests[1].kws[1].msgs[1]} Expected failure FAIL + Check Log Message ${SUITE.tests[0][0, 1, 0]} Arguments: [ 'Hello says "Pass"!' | 'INFO' ] TRACE + Check Log Message ${SUITE.tests[0][0, 1, 1]} Hello says "Pass"! INFO + Check Log Message ${SUITE.tests[0][0, 1, 2]} Return: None TRACE + Check Log Message ${SUITE.tests[0][0, 2, 1]} Debug message DEBUG + Check Log Message ${SUITE.tests[1][1, 0]} Arguments: [ 'Expected failure' ] TRACE + Check Log Message ${SUITE.tests[1][1, 1]} Expected failure FAIL diff --git a/atest/robot/cli/runner/multisource.robot b/atest/robot/cli/runner/multisource.robot index 2f06a21617a..6781c3b9a3e 100644 --- a/atest/robot/cli/runner/multisource.robot +++ b/atest/robot/cli/runner/multisource.robot @@ -45,6 +45,24 @@ Wildcards Should Contain Tests ${SUITE.suites[2]} Suite3 First Check Names ${SUITE.suites[2].tests[0]} Suite3 First Tsuite1 & Tsuite2 & Tsuite3.Tsuite3. +With Init File Included + Run Tests ${EMPTY} misc/suites/tsuite1.robot misc/suites/tsuite2.robot misc/suites/__init__.robot + Check Names ${SUITE} Tsuite1 & Tsuite2 + Should Contain Suites ${SUITE} Tsuite1 Tsuite2 + Check Keyword Data ${SUITE.teardown} BuiltIn.Log args=\${SUITE_TEARDOWN_ARG} type=TEARDOWN + Check Names ${SUITE.suites[0]} Tsuite1 Tsuite1 & Tsuite2. + Should Contain Tests ${SUITE.suites[0]} Suite1 First Suite1 Second Third In Suite1 + Check Names ${SUITE.suites[0].tests[0]} Suite1 First Tsuite1 & Tsuite2.Tsuite1. + Check Names ${SUITE.suites[0].tests[1]} Suite1 Second Tsuite1 & Tsuite2.Tsuite1. + Check Names ${SUITE.suites[0].tests[2]} Third In Suite1 Tsuite1 & Tsuite2.Tsuite1. + Check Names ${SUITE.suites[1]} Tsuite2 Tsuite1 & Tsuite2. + Should Contain Tests ${SUITE.suites[1]} Suite2 First + Check Names ${SUITE.suites[1].tests[0]} Suite2 First Tsuite1 & Tsuite2.Tsuite2. + +Multiple Init Files Not Allowed + Run Tests Without Processing Output ${EMPTY} misc/suites/tsuite1.robot misc/suites/__init__.robot misc/suites/__init__.robot + Stderr Should Contain [ ERROR ] Multiple init files not allowed. + Failure When Parsing Any Data Source Fails Run Tests Without Processing Output ${EMPTY} nönex misc/pass_and_fail.robot ${nönex} = Normalize Path ${DATADIR}/nönex @@ -54,4 +72,4 @@ Failure When Parsing Any Data Source Fails Warnings And Error When Parsing All Data Sources Fail Run Tests Without Processing Output ${EMPTY} nönex1 nönex2 ${nönex} = Normalize Path ${DATADIR}/nönex - Stderr Should Contain [ ERROR ] Parsing '${nönex}1' failed: File or directory to execute does not exist. + Stderr Should Contain [ ERROR ] Parsing '${nönex}1' and '${nönex}2' failed: File or directory to execute does not exist. diff --git a/atest/robot/cli/runner/output_files.robot b/atest/robot/cli/runner/output_files.robot index 76ab7bb8baf..00006f221ad 100644 --- a/atest/robot/cli/runner/output_files.robot +++ b/atest/robot/cli/runner/output_files.robot @@ -15,13 +15,17 @@ Output And Log Run Tests Without Processing Output --outputdir ${CLI OUTDIR} --output myoutput.xml --report none --log mylog.html ${TESTFILE} Output Directory Should Contain mylog.html myoutput.xml -Disabling output XML only disables log with a warning +Disabling only output file disables log with a warning Run Tests Without Processing Output --outputdir ${CLI OUTDIR} -o nOnE -r report.html -l mylog.html ${TESTFILE} + Stdout Should Contain Output: \ NONE\nReport: + Stderr Should Match Regexp \\[ ERROR \\] Log file cannot be created if output.xml is disabled. Output Directory Should Contain report.html - Stderr Should Match Regexp \\[ ERROR \\] Log file cannot be created if output.xml is disabled. All output files disabled - Run Tests Without Processing Output --outputdir ${CLI OUTDIR} -o nOnE -r NONE -l none ${TESTFILE} + [Documentation] Turning colors on turns also hyperlinks on console and `NONE` cannot be linked. + Run Tests Without Processing Output --outputdir ${CLI OUTDIR} -o nOnE -r NONE -l none --console-colors ON ${TESTFILE} + Stdout Should Contain Output: \ NONE\n + Stderr Should Be Empty Output Directory Should Be Empty Debug, Xunit And Report File Can Be Created When Output Is NONE @@ -49,6 +53,9 @@ Outputs Into Different Dirs Split Log Run Tests Without Processing Output --outputdir ${CLI OUTDIR} --output o.xml --report r.html --log l.html --splitlog ${TESTFILE} Directory Should Contain ${CLI OUTDIR} l-1.js l-2.js l.html o.xml r.html + FOR ${name} IN l-1.js l-2.js + File Should Contain ${CLI OUTDIR}/${name} window.fileLoading.notify("${name}"); + END Non-writable Output File Create Directory ${CLI OUTDIR}/diréctöry.xml diff --git a/atest/robot/cli/runner/remove_keywords.robot b/atest/robot/cli/runner/remove_keywords.robot index 1576131a8d7..05d1dca3f6a 100644 --- a/atest/robot/cli/runner/remove_keywords.robot +++ b/atest/robot/cli/runner/remove_keywords.robot @@ -3,65 +3,67 @@ Suite Setup Run Tests And Remove Keywords Resource atest_resource.robot *** Variables *** -${PASS MESSAGE} -PASSED -ALL -${FAIL MESSAGE} -ALL +PASSED -${REMOVED FOR MESSAGE} -FOR -ALL -${KEPT FOR MESSAGE} +FOR -ALL -${REMOVED WHILE MESSAGE} -WHILE -ALL -${KEPT WHILE MESSAGE} +WHILE -ALL -${REMOVED WUKS MESSAGE} -WUKS -ALL -${KEPT WUKS MESSAGE} +WUKS -ALL -${REMOVED BY NAME MESSAGE} -BYNAME -ALL -${KEPT BY NAME MESSAGE} +BYNAME -ALL +${PASS MESSAGE} -PASSED -ALL +${FAIL MESSAGE} -ALL +PASSED +${REMOVED FOR MESSAGE} -FOR -ALL +${KEPT FOR MESSAGE} +FOR -ALL +${REMOVED WHILE MESSAGE} -WHILE -ALL +${KEPT WHILE MESSAGE} +WHILE -ALL +${REMOVED WUKS MESSAGE} -WUKS -ALL +${KEPT WUKS MESSAGE} +WUKS -ALL +${REMOVED BY NAME MESSAGE} -BYNAME -ALL +${KEPT BY NAME MESSAGE} +BYNAME -ALL ${REMOVED BY PATTERN MESSAGE} -BYPATTERN -ALL -${KEPT BY PATTERN MESSAGE} +BYPATTERN -ALL +${KEPT BY PATTERN MESSAGE} +BYPATTERN -ALL *** Test Cases *** PASSED option when test passes Log should not contain ${PASS MESSAGE} Output should contain pass message + Messages from body are removed Passing PASSED option when test fails - Log should contain ${FAIL MESSAGE} + Log should contain ${FAIL MESSAGE} Output should contain fail message + Messages from body are not removed Failing FOR option Log should not contain ${REMOVED FOR MESSAGE} - Log should contain ${KEPT FOR MESSAGE} + Log should contain ${KEPT FOR MESSAGE} Output should contain for messages WHILE option Log should not contain ${REMOVED WHILE MESSAGE} - Log should contain ${KEPT WHILE MESSAGE} + Log should contain ${KEPT WHILE MESSAGE} Output should contain while messages WUKS option Log should not contain ${REMOVED WUKS MESSAGE} - Log should contain ${KEPT WUKS MESSAGE} + Log should contain ${KEPT WUKS MESSAGE} Output should contain WUKS messages NAME option Log should not contain ${REMOVED BY NAME MESSAGE} - Log should contain ${KEPT BY NAME MESSAGE} + Log should contain ${KEPT BY NAME MESSAGE} Output should contain NAME messages NAME option with pattern Log should not contain ${REMOVED BY PATTERN MESSAGE} - Log should contain ${KEPT BY PATTERN MESSAGE} + Log should contain ${KEPT BY PATTERN MESSAGE} Output should contain NAME messages with patterns TAGged keywords - Log should contain This is not removed by TAG + Log should contain This is not removed by TAG Log should not contain This is removed by TAG Warnings and errors are preserved + Log should contain Keywords with warnings are not removed + Log should contain Keywords with errors are not removed Output should contain warning and error - Log should contain Keywords with warnings are not removed - Log should contain Keywords with errors are not removed *** Keywords *** Run tests and remove keywords - ${opts} = Catenate + VAR ${opts} ... --removekeywords passed ... --RemoveKeywords FoR ... --RemoveKeywords whiLE @@ -70,10 +72,11 @@ Run tests and remove keywords ... --removekeywords name:Thisshouldbe* ... --removekeywords name:Remove??? ... --removekeywords tag:removeANDkitty + ... --listener AddMessagesToTestBody ... --log log.html Run tests ${opts} cli/remove_keywords/all_combinations.robot - ${LOG} = Get file ${OUTDIR}/log.html - Set suite variable $LOG + ${log} = Get file ${OUTDIR}/log.html + VAR ${LOG} ${log} scope=SUITE Log should not contain [Arguments] ${msg} @@ -83,13 +86,23 @@ Log should contain [Arguments] ${msg} Should contain ${LOG} ${msg} +Messages from body are removed + [Arguments] ${name} + Log should not contain Hello '${name}', says listener! + Log should not contain Bye '${name}', says listener! + +Messages from body are not removed + [Arguments] ${name} + Log should contain Hello '${name}', says listener! + Log should contain Bye '${name}', says listener! + Output should contain pass message ${tc} = Check test case Passing - Check Log Message ${tc.kws[0].msgs[0]} ${PASS MESSAGE} + Check Log Message ${tc[1, 0]} ${PASS MESSAGE} Output should contain fail message ${tc} = Check test case Failing - Check Log Message ${tc.kws[0].msgs[0]} ${FAIL MESSAGE} + Check Log Message ${tc[1, 0]} ${FAIL MESSAGE} Output should contain for messages Test should contain for messages FOR when test passes @@ -98,11 +111,10 @@ Output should contain for messages Test should contain for messages [Arguments] ${name} ${tc} = Check test case ${name} - ${for} = Set Variable ${tc.kws[0].kws[0]} - Check log message ${for.body[0].body[0].body[1].body[0].body[0]} ${REMOVED FOR MESSAGE} one - Check log message ${for.body[1].body[0].body[1].body[0].body[0]} ${REMOVED FOR MESSAGE} two - Check log message ${for.body[2].body[0].body[1].body[0].body[0]} ${REMOVED FOR MESSAGE} three - Check log message ${for.body[3].body[0].body[0].body[0].body[0]} ${KEPT FOR MESSAGE} LAST + Check log message ${tc[1, 0, 0, 0, 1, 0, 0]} ${REMOVED FOR MESSAGE} one + Check log message ${tc[1, 0, 1, 0, 1, 0, 0]} ${REMOVED FOR MESSAGE} two + Check log message ${tc[1, 0, 2, 0, 1, 0, 0]} ${REMOVED FOR MESSAGE} three + Check log message ${tc[1, 0, 3, 0, 0, 0, 0]} ${KEPT FOR MESSAGE} LAST Output should contain while messages Test should contain while messages WHILE when test passes @@ -111,11 +123,10 @@ Output should contain while messages Test should contain while messages [Arguments] ${name} ${tc} = Check test case ${name} - ${while} = Set Variable ${tc.kws[0].kws[1]} - Check log message ${while.body[0].body[0].body[1].body[0].body[0]} ${REMOVED WHILE MESSAGE} 1 - Check log message ${while.body[1].body[0].body[1].body[0].body[0]} ${REMOVED WHILE MESSAGE} 2 - Check log message ${while.body[2].body[0].body[1].body[0].body[0]} ${REMOVED WHILE MESSAGE} 3 - Check log message ${while.body[3].body[0].body[0].body[0].body[0]} ${KEPT WHILE MESSAGE} 4 + Check log message ${tc[1, 1, 0, 0, 1, 0, 0]} ${REMOVED WHILE MESSAGE} 1 + Check log message ${tc[1, 1, 1, 0, 1, 0, 0]} ${REMOVED WHILE MESSAGE} 2 + Check log message ${tc[1, 1, 2, 0, 1, 0, 0]} ${REMOVED WHILE MESSAGE} 3 + Check log message ${tc[1, 1, 3, 0, 0, 0, 0]} ${KEPT WHILE MESSAGE} 4 Output should contain WUKS messages Test should contain WUKS messages WUKS when test passes @@ -124,9 +135,9 @@ Output should contain WUKS messages Test should contain WUKS messages [Arguments] ${name} ${tc} = Check test case ${name} - Check log message ${tc.kws[0].kws[0].kws[1].kws[0].msgs[0]} ${REMOVED WUKS MESSAGE} FAIL - Check log message ${tc.kws[0].kws[8].kws[1].kws[0].msgs[0]} ${REMOVED WUKS MESSAGE} FAIL - Check log message ${tc.kws[0].kws[9].kws[2].kws[0].msgs[0]} ${KEPT WUKS MESSAGE} FAIL + Check log message ${tc[1, 0, 1, 0, 0]} ${REMOVED WUKS MESSAGE} FAIL + Check log message ${tc[1, 8, 1, 0, 0]} ${REMOVED WUKS MESSAGE} FAIL + Check log message ${tc[1, 9, 2, 0, 0]} ${KEPT WUKS MESSAGE} FAIL Output should contain NAME messages Test should contain NAME messages NAME when test passes @@ -135,10 +146,10 @@ Output should contain NAME messages Test should contain NAME messages [Arguments] ${name} ${tc}= Check test case ${name} - Check log message ${tc.kws[0].kws[0].msgs[0]} ${REMOVED BY NAME MESSAGE} - Check log message ${tc.kws[1].kws[0].msgs[0]} ${REMOVED BY NAME MESSAGE} - Check log message ${tc.kws[2].kws[0].kws[0].msgs[0]} ${REMOVED BY NAME MESSAGE} - Check log message ${tc.kws[2].kws[1].msgs[0]} ${KEPT BY NAME MESSAGE} + Check log message ${tc[1, 0, 0]} ${REMOVED BY NAME MESSAGE} + Check log message ${tc[2, 0, 0]} ${REMOVED BY NAME MESSAGE} + Check log message ${tc[3, 0, 0, 0]} ${REMOVED BY NAME MESSAGE} + Check log message ${tc[3, 1, 0]} ${KEPT BY NAME MESSAGE} Output should contain NAME messages with patterns Test should contain NAME messages with * pattern NAME with * pattern when test passes @@ -149,20 +160,20 @@ Output should contain NAME messages with patterns Test should contain NAME messages with * pattern [Arguments] ${name} ${tc}= Check test case ${name} - Check log message ${tc.kws[0].kws[0].msgs[0]} ${REMOVED BY PATTERN MESSAGE} - Check log message ${tc.kws[1].kws[0].msgs[0]} ${REMOVED BY PATTERN MESSAGE} - Check log message ${tc.kws[2].kws[0].msgs[0]} ${REMOVED BY PATTERN MESSAGE} - Check log message ${tc.kws[3].kws[0].kws[0].msgs[0]} ${REMOVED BY PATTERN MESSAGE} - Check log message ${tc.kws[3].kws[1].msgs[0]} ${KEPT BY PATTERN MESSAGE} + Check log message ${tc[1, 0, 0]} ${REMOVED BY PATTERN MESSAGE} + Check log message ${tc[2, 0, 0]} ${REMOVED BY PATTERN MESSAGE} + Check log message ${tc[3, 0, 0]} ${REMOVED BY PATTERN MESSAGE} + Check log message ${tc[4, 0, 0, 0]} ${REMOVED BY PATTERN MESSAGE} + Check log message ${tc[4, 1, 0]} ${KEPT BY PATTERN MESSAGE} Test should contain NAME messages with ? pattern [Arguments] ${name} ${tc}= Check test case ${name} - Check log message ${tc.kws[0].kws[0].msgs[0]} ${REMOVED BY PATTERN MESSAGE} - Check log message ${tc.kws[1].kws[0].kws[0].msgs[0]} ${REMOVED BY PATTERN MESSAGE} - Check log message ${tc.kws[1].kws[1].msgs[0]} ${KEPT BY PATTERN MESSAGE} + Check log message ${tc[1, 0, 0]} ${REMOVED BY PATTERN MESSAGE} + Check log message ${tc[2, 0, 0, 0]} ${REMOVED BY PATTERN MESSAGE} + Check log message ${tc[2, 1, 0]} ${KEPT BY PATTERN MESSAGE} Output should contain warning and error ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Keywords with warnings are not removed WARN - Check Log Message ${tc.kws[1].kws[0].msgs[0]} Keywords with errors are not removed ERROR + Check Log Message ${tc[1, 0, 0, 0]} Keywords with warnings are not removed WARN + Check Log Message ${tc[2, 0, 0]} Keywords with errors are not removed ERROR diff --git a/atest/robot/cli/runner/rerunfailed.robot b/atest/robot/cli/runner/rerunfailed.robot index adacf4a0d7b..68d263d8d34 100644 --- a/atest/robot/cli/runner/rerunfailed.robot +++ b/atest/robot/cli/runner/rerunfailed.robot @@ -49,7 +49,7 @@ Suite initialization Run Tests ${EMPTY} ${SUITE DIR} Copy File ${OUTFILE} ${RUN FAILED FROM} Copy File ${ORIG DIR}/runfailed2.robot ${SUITE DIR}/runfailed.robot - Run Tests --rerunfailed ${RUN FAILED FROM} --test Selected --exclude excluded_tag ${SUITE DIR} + Run Tests --rerunfailed ${RUN FAILED FROM} --test Selected --include common --exclude excluded_tag ${SUITE DIR} Test Should Have Been Executed [Arguments] ${name} diff --git a/atest/robot/cli/runner/rerunfailedsuites_corners.robot b/atest/robot/cli/runner/rerunfailedsuites_corners.robot index 45008eba073..930827c4305 100644 --- a/atest/robot/cli/runner/rerunfailedsuites_corners.robot +++ b/atest/robot/cli/runner/rerunfailedsuites_corners.robot @@ -7,7 +7,7 @@ ${RUN FAILED FROM} %{TEMPDIR}${/}run-failed-output.xml *** Test Cases *** Runs everything when output is set to NONE - Run Tests --ReRunFailedSuites NoNe cli/runfailed/onlypassing + Run Tests --Re-Run-Failed-Suites NoNe cli/runfailed/onlypassing File Should Exist ${OUTFILE} Check Test Case Passing diff --git a/atest/robot/cli/runner/run_empty_suite.robot b/atest/robot/cli/runner/run_empty_suite.robot index 90d326fb0a6..a7be72c65df 100644 --- a/atest/robot/cli/runner/run_empty_suite.robot +++ b/atest/robot/cli/runner/run_empty_suite.robot @@ -17,7 +17,7 @@ No tests in directory [Teardown] Remove directory ${NO TESTS DIR} Empty suite after filtering by tags - Run empty suite --RunEmptySuite --include nonex ${TEST FILE} + Run empty suite --Run-Empty-Suite --include nonex ${TEST FILE} Empty suite after filtering by names Run empty suite --RunEmptySuite --test nonex ${TEST FILE} diff --git a/atest/robot/cli/runner/suite_name_doc_and_metadata.robot b/atest/robot/cli/runner/suite_name_doc_and_metadata.robot index c1377bb3935..4a300f7248a 100644 --- a/atest/robot/cli/runner/suite_name_doc_and_metadata.robot +++ b/atest/robot/cli/runner/suite_name_doc_and_metadata.robot @@ -35,14 +35,20 @@ Documentation and metadata from external file Check All Names ${SUITE} Normal Should Be Equal ${SUITE.doc} ${value.rstrip()} Should Be Equal ${SUITE.metadata['name']} ${value.rstrip()} - Run Tests --doc " ${path}" --metadata "name: ${path}" ${TEST FILE} + Run Tests --doc " ${path}" --metadata "name: ${path}" -M dir:%{TEMPDIR} ${TEST FILE} Check All Names ${SUITE} Normal Should Be Equal ${SUITE.doc} ${path} Should Be Equal ${SUITE.metadata['name']} ${path} + Should Be Equal ${SUITE.metadata['dir']} %{TEMPDIR} Invalid external file - Run Tests Without Processing Output --doc . ${TEST FILE} - Stderr Should Match [[] ERROR []] Invalid value for option '--doc': Reading documentation from '.' failed: *${USAGE TIP}\n + [Tags] no-windows + ${path} = Normalize Path %{TEMPDIR}/file.txt + Create File ${path} + Evaluate os.chmod('${path}', 0) + Run Tests Without Processing Output --doc ${path} ${TEST FILE} + Stderr Should Match [[] ERROR []] Invalid value for option '--doc': Reading documentation from '${path}' failed: *${USAGE TIP}\n + [Teardown] Remove File ${path} *** Keywords *** Check All Names diff --git a/atest/robot/core/binary_data.robot b/atest/robot/core/binary_data.robot index e3372e88519..f6c70ccc3bb 100644 --- a/atest/robot/core/binary_data.robot +++ b/atest/robot/core/binary_data.robot @@ -28,13 +28,13 @@ Print Bytes ... 116 t ... 123 { ... 127 \x7f - Check Log Message ${tc.kws[0].msgs[${index}]} Byte ${index}: '${exp}' + Check Log Message ${tc[0, ${index}]} Byte ${index}: '${exp}' END # Check that all bytes were really written without errors. FOR ${index} IN RANGE 256 - Should Start With ${tc.kws[0].msgs[${index}].message} Byte ${index}: + Should Start With ${tc[0, ${index}].message} Byte ${index}: END - Check Log Message ${tc.kws[0].msgs[-1]} All bytes printed successfully + Check Log Message ${tc[0, -1]} All bytes printed successfully Byte Error [Documentation] Check an exception containing control chars is handled ok @@ -46,7 +46,7 @@ Byte Error In Setup And Teardown Binary Data [Documentation] Make sure even totally binary data doesn't break anything ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[1]} Binary data printed successfully + Check Log Message ${tc[0, 1]} Binary data printed successfully *** Keywords *** My Run Tests diff --git a/atest/robot/core/empty_tc_and_uk.robot b/atest/robot/core/empty_tc_and_uk.robot index 3c8c4cb22f3..bacff42b7db 100644 --- a/atest/robot/core/empty_tc_and_uk.robot +++ b/atest/robot/core/empty_tc_and_uk.robot @@ -1,32 +1,35 @@ *** Settings *** -Documentation Empty test cases and user keywords -Suite Setup Run Tests ${EMPTY} core/empty_testcase_and_uk.robot +Suite Setup Run Tests ${EMPTY} core/empty_testcase_and_uk.robot Resource atest_resource.robot *** Test Cases *** Test Case Without Name - Check Test Case ${EMPTY} + Check Test Case ${EMPTY} Empty Test Case - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Empty Test Case With Setup And Teardown - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} + +User Keyword Without Name + Error In File 0 core/empty_testcase_and_uk.robot 42 + ... Creating keyword '' failed: User keyword name cannot be empty. Empty User Keyword - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} User Keyword With Only Non-Empty [Return] Works - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} User Keyword With Empty [Return] Does Not Work - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Empty User Keyword With Other Settings Than [Return] - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Non-Empty And Empty User Keyword - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Non-Empty UK Using Empty UK - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} diff --git a/atest/robot/core/filter_by_names.robot b/atest/robot/core/filter_by_names.robot index b252ecbe4ba..221f274127c 100644 --- a/atest/robot/core/filter_by_names.robot +++ b/atest/robot/core/filter_by_names.robot @@ -20,7 +20,7 @@ ${SUITE DIR} misc/suites --test not matching Run Failing Test ... Suite 'Many Tests' contains no tests matching name 'notexists'. - ... --test notexists ${SUITE FILE} + ... --test notexists --test not matching with multiple inputs Run Failing Test @@ -30,6 +30,18 @@ ${SUITE DIR} misc/suites ... Suite 'My Name' contains no tests matching name 'notexists'. ... --name "My Name" --test notexists ${SUITE FILE} ${SUITE DIR} +--test and --include must both match + Run And Check Tests --test first --include t1 -i f1 First + Run Failing Test + ... Suite 'Many Tests' contains no tests matching name 'fifth' and matching tag 't1'. + ... --test fifth --include t1 + +--exclude wins over --test + Run And Check Tests --test fi* --exclude t1 Fifth + Run Failing Test + ... Suite 'Many Tests' contains no tests matching name 'first' and not matching tag 'f1'. + ... --test first --exclude f1 + --suite once Run Suites --suite tsuite1 Should Contain Suites ${SUITE} TSuite1 @@ -37,7 +49,7 @@ ${SUITE DIR} misc/suites --suite with . in name Run Suites --suite sub.suite.4 - Should Contain Suites ${SUITE} Subsuites2 + Should Contain Suites ${SUITE} Custom name for 📂 'subsuites2' Should Contain Tests ${SUITE} Test From Sub Suite 4 Should Not Contain Tests ${SUITE} SubSuite3 First SubSuite3 Second @@ -54,50 +66,13 @@ ${SUITE DIR} misc/suites Parent suite init files are processed Previous Test Should Have Passed --suite with patterns Should Be True ${SUITE.teardown} - Check log message ${SUITE.teardown.msgs[0]} Default suite teardown - -Unnecessary files are not parsed when --suite matches files - [Documentation] Test that only files matching --suite are processed. - ... Additionally __init__ files should never be ignored. - Previous Test Should Have Passed Parent suite init files are processed - ${root} = Normalize Path ${DATA DIR}/${SUITE DIR} - Syslog Should Contain Parsing directory '${root}'. - Syslog Should Contain Parsing file '${root}${/}tsuite1.robot'. - Syslog Should Contain Ignoring file or directory '${root}${/}tsuite2.robot'. - Syslog Should Contain Parsing file '${root}${/}tsuite3.robot'. - Syslog Should Contain Parsing file '${root}${/}fourth.robot'. - Syslog Should Contain Parsing directory '${root}${/}subsuites'. - Syslog Should Contain Ignoring file or directory '${root}${/}subsuites${/}sub1.robot'. - Syslog Should Contain Ignoring file or directory '${root}${/}subsuites${/}sub2.robot'. - Syslog Should Contain Parsing directory '${root}${/}subsuites2'. - Syslog Should Contain Ignoring file or directory '${root}${/}subsuites2${/}subsuite3.robot'. - Syslog Should Contain Ignoring file or directory '${root}${/}subsuites2${/}sub.suite.4.robot'. - Syslog Should Not Contain Regexp Ignoring file or directory '.*__init__.robot'. + Check log message ${SUITE.teardown[0]} Default suite teardown --suite matching directory Run Suites --suite sub?uit[efg]s Should Contain Suites ${SUITE.suites[0]} Sub1 Sub2 Should Contain Tests ${SUITE} SubSuite1 First SubSuite2 First -Unnecessary files are not parsed when --suite matches directory - [Documentation] Testing that only files matching to --suite are processed. - ... This time --suite matches directory so all suites under it - ... should be parsed regardless their names. - Previous Test Should Have Passed --suite matching directory - ${root} = Normalize Path ${DATA DIR}/${SUITE DIR} - Syslog Should Contain Parsing directory '${root}'. - Syslog Should Contain Ignoring file or directory '${root}${/}tsuite1.robot'. - Syslog Should Contain Ignoring file or directory '${root}${/}tsuite2.robot'. - Syslog Should Contain Ignoring file or directory '${root}${/}tsuite3.robot'. - Syslog Should Contain Ignoring file or directory '${root}${/}fourth.robot'. - Syslog Should Contain Parsing directory '${root}${/}subsuites'. - Syslog Should Contain Parsing file '${root}${/}subsuites${/}sub1.robot'. - Syslog Should Contain Parsing file '${root}${/}subsuites${/}sub2.robot'. - Syslog Should Contain Parsing directory '${root}${/}subsuites2'. - Syslog Should Contain Ignoring file or directory '${root}${/}subsuites2${/}subsuite3.robot'. - Syslog Should Contain Ignoring file or directory '${root}${/}subsuites2${/}sub.suite.4.robot'. - Syslog Should Not Contain Regexp Ignoring file or directory '.*__init__.robot'. - --suite with long name matching file Run Suites --suite suites.fourth --suite suites.*.SUB? Should Contain Suites ${SUITE} Fourth Subsuites @@ -110,18 +85,19 @@ Unnecessary files are not parsed when --suite matches directory Should Contain Tests ${SUITE} SubSuite1 First SubSuite2 First --suite with long name with . in name - Run Suites --suite suites.subsuites2.sub.suite.4 - Should Contain Suites ${SUITE} Subsuites2 + Run Suites --suite "suites.Custom name for 📂 'subsuites2'.sub.suite.4" + Should Contain Suites ${SUITE} Custom name for 📂 'subsuites2' Should Contain Tests ${SUITE} Test From Sub Suite 4 Should Not Contain Tests ${SUITE} SubSuite3 First SubSuite3 Second ---suite with end of long name - Run Suites --suite Subsuites.Sub? - Should Contain Suites ${SUITE} Subsuites - Should Contain Tests ${SUITE} SubSuite1 First SubSuite2 First +--suite matching end of long name is not enough anymore + [Documentation] This was supported until RF 7.0. + Run Failing Test + ... Suite 'Suites' contains no tests in suite 'Subsuites.Sub?'. + ... --suite Subsuites.Sub? ${SUITE DIR} --suite with long name when executing multiple suites - Run Suites -s "Subsuites & Subsuites2.Subsuites.Sub1" misc/suites/subsuites misc/suites/subsuites2 + Run Suites -s "Suite With Prefix & Subsuites.Subsuites.Sub1" misc/suites/01__suite_with_prefix misc/suites/subsuites Should Contain Suites ${SUITE} Subsuites Should Contain Suites ${SUITE.suites[0]} Sub1 Should Contain Tests ${SUITE} SubSuite1 First @@ -145,10 +121,10 @@ Unnecessary files are not parsed when --suite matches directory ... --suite xxx -N Custom ${SUITE DIR} ${SUITE FILE} --suite and --test together - [Documentation] Testing that only tests matching --test which are under suite matching --suite are run. - Run Suites --suite subsuites --suite tsuite3 --test SubSuite1First - Should Contain Suites ${SUITE} Subsuites - Should Contain Tests ${SUITE} SubSuite1 First + [Documentation] Validate that only tests matching --test under suites matching --suite are selected. + Run Suites --suite suites.subsuites.sub2 --suite tsuite3 --test *First + Should Contain Suites ${SUITE} Subsuites Tsuite3 + Should Contain Tests ${SUITE} SubSuite2 First Suite3 First --suite and --test together not matching Run Failing Test @@ -156,17 +132,17 @@ Unnecessary files are not parsed when --suite matches directory ... --suite subsuites -s nomatch --test Suite1* -t nomatch ${SUITE DIR} --suite with --include/--exclude - Run Suites --suite tsuite? --include t? --exclude t2 - Should Contain Suites ${SUITE} Tsuite1 Tsuite2 Tsuite3 - Should Contain Tests ${SUITE} Suite1 First Suite2 First Suite3 First + Run Suites --suite tsuite[13] --include t? --exclude t2 + Should Contain Suites ${SUITE} Tsuite1 Tsuite3 + Should Contain Tests ${SUITE} Suite1 First Suite3 First ---suite, --test, --inculde and --exclude - Run Suites --suite sub* --test *first -s nosuite -t notest --include t1 --exclude sub3 - Should Contain Suites ${SUITE} Subsuites - Should Contain Tests ${SUITE} SubSuite1 First +--suite, --test, --include and --exclude + Run Suites --suite sub* --suite "custom name *" --test "subsuite3 second" -t *first -s nomatch -t nomatch --include f1 --exclude t1 + Should Contain Suites ${SUITE} Custom name for 📂 'subsuites2' Subsuites + Should Contain Tests ${SUITE} SubSuite2 First SubSuite3 Second --suite with long name and other filters - Run Suites --suite suites.fourth --suite tsuite1 -s Subsuites.Sub1 --test *first* --exclude none + Run Suites --suite suites.fourth --suite tsuite1 -s *.Subsuites.Sub1 --test *first* --exclude none Should Contain Suites ${SUITE} Fourth Subsuites Tsuite1 Should Contain Tests ${SUITE} Suite4 First Suite1 First SubSuite1 First @@ -175,10 +151,14 @@ Unnecessary files are not parsed when --suite matches directory Should Contain Suites ${SUITE} Sub.Suite.1 Suite5 Suite6 Should Contain Suites ${SUITE.suites[0]} .Sui.te.2. Suite4 +Suite containing tasks is ok if only tests are selected + Run And Check Tests --test test Test sources=rpa/tasks rpa/tests.robot + Run And Check Tests --suite tests Test sources=rpa/tasks rpa/tests.robot + *** Keywords *** Run And Check Tests - [Arguments] ${params} @{tests} - Run Tests ${params} ${SUITE FILE} + [Arguments] ${params} @{tests} ${sources}=${SUITE FILE} + Run Tests ${params} ${sources} Stderr Should Be Empty Should Contain Tests ${suite} @{tests} @@ -188,6 +168,6 @@ Run Suites Stderr Should Be Empty Run Failing Test - [Arguments] ${error} ${options} ${sources} + [Arguments] ${error} ${options} ${sources}=${SUITE FILE} Run Tests Without Processing Output ${options} ${sources} Stderr Should Be Equal To [ ERROR ] ${error}${USAGE TIP}\n diff --git a/atest/robot/core/keyword_setup.robot b/atest/robot/core/keyword_setup.robot new file mode 100644 index 00000000000..1f8f91963f4 --- /dev/null +++ b/atest/robot/core/keyword_setup.robot @@ -0,0 +1,46 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} core/keyword_setup.robot +Resource atest_resource.robot + +*** Test Cases *** +Passing setup + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0].setup[0]} Hello, setup! + +Failing setup + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0].setup[0]} Hello, setup! FAIL + Should Be Equal ${tc[0, 0].status} NOT RUN + +Failing setup and passing teardown + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc.setup.setup[0]} Hello, setup! FAIL + Should Be Equal ${tc.setup[0].status} NOT RUN + Check Log Message ${tc.setup.teardown[0]} Hello, teardown! INFO + +Failing setup and teardown + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0].setup[0]} Hello, setup! FAIL + Should Be Equal ${tc[0, 0].status} NOT RUN + Check Log Message ${tc[0].teardown[0]} Hello, teardown! FAIL + +Continue-on-failure mode is not enabled in setup + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc.setup.setup[0, 0]} Hello, setup! INFO + Check Log Message ${tc.setup.setup[1, 0]} Hello again, setup! FAIL + Should Be Equal ${tc.setup.setup[2].status} NOT RUN + +NONE is same as no setup + ${tc} = Check Test Case ${TESTNAME} + Should Be Equal ${tc[0].setup.name} ${None} + +Empty [Setup] is same as no setup + ${tc} = Check Test Case ${TESTNAME} + Should Be Equal ${tc[0].setup.name} ${None} + +Using variable + ${tc} = Check Test Case ${TESTNAME} + Should Be Equal ${tc[0].setup.name} Log + Should Be Equal ${tc[1].setup.name} ${None} + Should Be Equal ${tc[2].setup.name} ${None} + Should Be Equal ${tc[3].setup.name} Fail diff --git a/atest/robot/core/keyword_teardown.robot b/atest/robot/core/keyword_teardown.robot index 4c0506c3ef1..d15cfe8bb28 100644 --- a/atest/robot/core/keyword_teardown.robot +++ b/atest/robot/core/keyword_teardown.robot @@ -1,67 +1,67 @@ *** Settings *** -Resource atest_resource.robot -Suite Setup Run Tests ${EMPTY} core/keyword_teardown.robot +Resource atest_resource.robot +Suite Setup Run Tests ${EMPTY} core/keyword_teardown.robot *** Test Cases *** Passing Keyword with Teardown - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} In UK - Check Log Message ${tc.kws[0].teardown.msgs[0]} In UK Teardown + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0]} In UK + Check Log Message ${tc[0].teardown[0]} In UK Teardown Failing Keyword with Teardown - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Expected Failure! FAIL - Check Log Message ${tc.kws[0].teardown.msgs[0]} In Failing UK Teardown + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0]} Expected Failure! FAIL + Check Log Message ${tc[0].teardown[0]} In Failing UK Teardown Teardown in keyword with embedded arguments - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} In UK with Embedded Arguments - Check Log Message ${tc.kws[0].teardown.msgs[0]} In Teardown of UK with Embedded Arguments - Check Log Message ${tc.kws[1].kws[0].msgs[0]} Expected Failure in UK with Embedded Arguments FAIL - Check Log Message ${tc.kws[1].teardown.msgs[0]} In Teardown of Failing UK with Embedded Arguments + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0]} In UK with Embedded Arguments + Check Log Message ${tc[0].teardown[0]} In Teardown of UK with Embedded Arguments + Check Log Message ${tc[1, 0, 0]} Expected Failure in UK with Embedded Arguments FAIL + Check Log Message ${tc[1].teardown[0]} In Teardown of Failing UK with Embedded Arguments Failure in Keyword Teardown - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} In UK - Check Log Message ${tc.kws[0].teardown.msgs[0]} Failing in UK Teardown FAIL + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0]} In UK + Check Log Message ${tc[0].teardown[0]} Failing in UK Teardown FAIL Failures in Keyword and Teardown - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Expected Failure! FAIL - Check Log Message ${tc.kws[0].teardown.msgs[0]} Failing in UK Teardown FAIL + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0]} Expected Failure! FAIL + Check Log Message ${tc[0].teardown[0]} Failing in UK Teardown FAIL Multiple Failures in Keyword Teardown - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].teardown.kws[0].msgs[0]} Failure in Teardown FAIL - Check Log Message ${tc.kws[0].teardown.kws[1].kws[0].msgs[0]} Expected Failure! FAIL - Check Log Message ${tc.kws[0].teardown.kws[1].kws[1].msgs[0]} Executed if in nested Teardown - Check Log Message ${tc.kws[0].teardown.kws[2].msgs[0]} Third failure in Teardown FAIL + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0].teardown[0, 0]} Failure in Teardown FAIL + Check Log Message ${tc[0].teardown[1, 0, 0]} Expected Failure! FAIL + Check Log Message ${tc[0].teardown[1, 1, 0]} Executed if in nested Teardown + Check Log Message ${tc[0].teardown[2, 0]} Third failure in Teardown FAIL Nested Keyword Teardowns - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} In UK - Check Log Message ${tc.kws[0].kws[0].teardown.msgs[0]} In UK Teardown - Check Log Message ${tc.kws[0].teardown.kws[0].msgs[0]} In UK - Check Log Message ${tc.kws[0].teardown.teardown.msgs[0]} In UK Teardown + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0, 0]} In UK + Check Log Message ${tc[0, 0].teardown[0]} In UK Teardown + Check Log Message ${tc[0].teardown[0, 0]} In UK + Check Log Message ${tc[0].teardown.teardown[0]} In UK Teardown Nested Keyword Teardown Failures - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].teardown.msgs[0]} Failing in UK Teardown FAIL - Check Log Message ${tc.kws[0].teardown.msgs[0]} Failing in outer UK Teardown FAIL + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0].teardown[0]} Failing in UK Teardown FAIL + Check Log Message ${tc[0].teardown[0]} Failing in outer UK Teardown FAIL Continuable Failure in Keyword - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Please continue FAIL - Check Log Message ${tc.kws[0].kws[1].msgs[0]} After continuable failure - Check Log Message ${tc.kws[0].teardown.msgs[0]} In UK Teardown + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0, 0]} Please continue FAIL + Check Log Message ${tc[0, 1, 0]} After continuable failure + Check Log Message ${tc[0].teardown[0]} In UK Teardown Non-ASCII Failure in Keyword Teardown - ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} åäö - Check Log Message ${tc.kws[0].teardown.msgs[0]} Hyvää äitienpäivää! FAIL + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0]} åäö + Check Log Message ${tc[0].teardown[0]} Hyvää äitienpäivää! FAIL Keyword cannot have only teardown - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} Replacing Variables in Keyword Teardown Fails - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} diff --git a/atest/robot/core/non_ascii.robot b/atest/robot/core/non_ascii.robot index 0d59f975c0b..732acc79e9b 100644 --- a/atest/robot/core/non_ascii.robot +++ b/atest/robot/core/non_ascii.robot @@ -6,41 +6,41 @@ Variables unicode_vars.py *** Test Cases *** Non-ASCII Log Messages ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} ${MESSAGE1} - Check Log Message ${tc.kws[0].msgs[1]} ${MESSAGE2} - Check Log Message ${tc.kws[0].msgs[2]} ${MESSAGE3} + Check Log Message ${tc[0, 0]} ${MESSAGE1} + Check Log Message ${tc[0, 1]} ${MESSAGE2} + Check Log Message ${tc[0, 2]} ${MESSAGE3} Non-ASCII Return Value ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[2].msgs[0]} Français + Check Log Message ${tc[2, 0]} Français Non-ASCII In Return Value Attributes ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} ${MESSAGES} - Check Log Message ${tc.kws[0].msgs[1]} \${obj} = ${MESSAGES} - Check Log Message ${tc.kws[1].msgs[0]} ${MESSAGES} + Check Log Message ${tc[0, 0]} ${MESSAGES} + Check Log Message ${tc[0, 1]} \${obj} = ${MESSAGES} + Check Log Message ${tc[1, 0]} ${MESSAGES} Non-ASCII Failure ${tc} = Check Test Case ${TESTNAME} FAIL ${MESSAGES} - Check Log Message ${tc.kws[0].msgs[0]} ${MESSAGES} FAIL + Check Log Message ${tc[0, 0]} ${MESSAGES} FAIL Non-ASCII Failure In Setup ${tc} = Check Test Case ${TESTNAME} FAIL Setup failed:\n${MESSAGES} - Check Log Message ${tc.setup.msgs[0]} ${MESSAGES} FAIL + Check Log Message ${tc.setup[0]} ${MESSAGES} FAIL Non-ASCII Failure In Teardown ${tc} = Check Test Case ${TESTNAME} FAIL Teardown failed:\n${MESSAGES} - Check Log Message ${tc.teardown.msgs[0]} ${MESSAGES} FAIL + Check Log Message ${tc.teardown[0]} ${MESSAGES} FAIL Non-ASCII Failure In Teardown After Normal Failure Check Test Case ${TESTNAME} FAIL Just ASCII here\n\nAlso teardown failed:\n${MESSAGES} Ñöñ-ÄŚÇÏÏ Tëśt äņd Këywörd Nämës, Спасибо ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} Ñöñ-ÄŚÇÏÏ Këywörd Nämë - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Hyvää päivää + Should Be Equal ${tc[0].name} Ñöñ-ÄŚÇÏÏ Këywörd Nämë + Check Log Message ${tc[0, 0, 0]} Hyvää päivää Non-ASCII Failure In Suite Setup and Teardown Check Test Case ${TESTNAME} - Check Log Message ${SUITE.suites[1].setup.msgs[0]} ${MESSAGES} FAIL - Check Log Message ${SUITE.suites[1].teardown.msgs[0]} ${MESSAGES} FAIL + Check Log Message ${SUITE.suites[1].setup[0]} ${MESSAGES} FAIL + Check Log Message ${SUITE.suites[1].teardown[0]} ${MESSAGES} FAIL diff --git a/atest/robot/core/overriding_default_settings_with_none.robot b/atest/robot/core/overriding_default_settings_with_none.robot index be042e3c300..627d11d77b0 100644 --- a/atest/robot/core/overriding_default_settings_with_none.robot +++ b/atest/robot/core/overriding_default_settings_with_none.robot @@ -22,15 +22,15 @@ Overriding Test Teardown from Command Line Overriding Test Template ${tc}= Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].name} BuiltIn.No Operation + Should Be Equal ${tc[0].full_name} BuiltIn.No Operation Overriding Test Timeout ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.body[0].msgs[0]} Slept 300 milliseconds + Check Log Message ${tc[0, 0]} Slept 123 milliseconds. Overriding Test Timeout from Command Line ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.body[0].msgs[0]} Slept 300 milliseconds + Check Log Message ${tc[0, 0]} Slept 123 milliseconds. Overriding Default Tags ${tc}= Check Test Case ${TESTNAME} @@ -44,5 +44,5 @@ Overriding Is Case Insensitive ${tc}= Check Test Case ${TESTNAME} Setup Should Not Be Defined ${tc} Teardown Should Not Be Defined ${tc} - Should Be Equal ${tc.body[0].name} BuiltIn.No Operation + Should Be Equal ${tc[0].full_name} BuiltIn.No Operation Should Be Empty ${tc.tags} diff --git a/atest/robot/core/resource_and_variable_imports.robot b/atest/robot/core/resource_and_variable_imports.robot index fa1157ff8bc..b089fb86f92 100644 --- a/atest/robot/core/resource_and_variable_imports.robot +++ b/atest/robot/core/resource_and_variable_imports.robot @@ -37,34 +37,50 @@ Invalid List Variable [Documentation] List variable not containing a list value causes an error Check Test Case ${TEST NAME} ${path} = Normalize Path ${RESDIR}/invalid_list_variable.py - Error in file 14 ${DATAFILE} 43 + Error in file 17 ${DATAFILE} 48 ... Processing variable file '${path}' failed: - ... Invalid variable '\@{invalid_list}': Expected list-like value, got string. + ... Invalid variable 'LIST__invalid_list': Expected a list-like value, got string. Dynamic Variable File - Check Test Case ${TEST NAME} With No Args - Check Test Case ${TEST NAME} With One Arg + Check Test Case ${TEST NAME} Dynamic Variable File With Variables And Backslashes In Args Check Test Case ${TEST NAME} +Static variable file does not accept arguments + ${path} = Normalize Path ${DATADIR}/core/resources_and_variables/variables.py + Error in file 6 ${DATAFILE} 18 + ... Processing variable file '${path}' with arguments ['static', 'does', 'not', 'accept', 'args'] failed: Static variable files do not accept arguments. + ... pattern=False + +Too few arguments to dynamic variable file + ${path} = Normalize Path ${DATADIR}/core/resources_and_variables/dynamic_variables.py + Error in file 7 ${DATAFILE} 19 + ... Processing variable file '${path}' failed: Variable file expected 1 to 4 arguments, got 0. + +Too many arguments to dynamic variable file + ${path} = Normalize Path ${DATADIR}/core/resources_and_variables/dynamic_variables.py + Error in file 8 ${DATAFILE} 20 + ... Processing variable file '${path}' with arguments ['More', 'than', 'four', 'arguments', 'fails'] failed: Variable file expected 1 to 4 arguments, got 5. + ... pattern=False + Invalid return value from dynamic variable file ${path} = Normalize Path ${RESDIR}/dynamic_variables.py Error in file 4 ${DATAFILE} 10 - ... Processing variable file '${path}' with arguments [ Two args | returns invalid ] failed: - ... Expected 'get_variables' to return dict-like value, got None. + ... Processing variable file '${path}' with arguments ['Three args', 'returns None', 'which is invalid'] failed: + ... Expected 'get_variables' to return a dictionary-like value, got None. ... pattern=False Dynamic variable file raises exception ${path} = Normalize Path ${RESDIR}/dynamic_variables.py Error in file 5 ${DATAFILE} 12 - ... Processing variable file '${path}' with arguments [ More | args | raises | exception ] failed: - ... Invalid arguments for get_variables + ... Processing variable file '${path}' with arguments ['Four', 'args', 'raises', 'exception'] failed: + ... Ooops! ... pattern=False Non-Existing Variable In Arguments To Dynamic Variable File ${path} = Normalize Path ${RESDIR}/dynamicVariables.py - Error in file 13 ${DATAFILE} 42 + Error in file 16 ${DATAFILE} 47 ... Replacing variables from setting 'Variables' failed: ... Variable '\${non_existing_var_as_arg}' not found. @@ -91,28 +107,28 @@ Re-Import Variable File Variable dynamic_variables.py ${SPACE}with arguments [ One arg works ] Non-Existing Resource File - Error in file 6 ${DATAFILE} 34 + Error in file 9 ${DATAFILE} 39 ... Resource file 'non_existing.robot' does not exist. Non-Existing Variable File - Error in file 7 ${DATAFILE} 35 + Error in file 10 ${DATAFILE} 40 ... Variable file 'non_existing.py' does not exist. Empty Resource File ${path} = Normalize Path ${RESDIR}/empty_resource.robot - Check log message ${ERRORS}[8] + Check log message ${ERRORS}[11] ... Imported resource file '${path}' is empty. WARN Invalid Resource Import Parameters - Error in file 0 ${DATAFILE} 37 + Error in file 0 ${DATAFILE} 42 ... Setting 'Resource' accepts only one value, got 2. Initialization file cannot be used as a resource file ${path} = Normalize Path ${DATADIR}/core/test_suite_dir_with_init_file/__init__.robot - Error in file 9 ${DATAFILE} 38 + Error in file 12 ${DATAFILE} 43 ... Initialization file '${path}' cannot be imported as a resource file. ${path} = Normalize Path ${DATADIR}/core/test_suite_dir_with_init_file/sub_suite_with_init_file/__INIT__.robot - Error in file 10 ${DATAFILE} 39 + Error in file 13 ${DATAFILE} 44 ... Initialization file '${path}' cannot be imported as a resource file. Invalid Setting In Resource File @@ -129,18 +145,18 @@ Resource cannot contain tests Invalid Variable File ${path} = Normalize Path ${RESDIR}/invalid_variable_file.py - Error in file 12 ${DATAFILE} 41 + Error in file 15 ${DATAFILE} 46 ... Processing variable file '${path}' failed: ... Importing variable file '${path}' failed: ... This is an invalid variable file ... traceback=* Resource Import Without Path - Error in file 11 ${DATAFILE} 40 + Error in file 14 ${DATAFILE} 45 ... Resource setting requires value. Variable Import Without Path - Error in file 15 ${DATAFILE} 44 + Error in file 18 ${DATAFILE} 49 ... Variables setting requires value. Resource File In PYTHONPATH diff --git a/atest/robot/core/suite_setup_and_teardown.robot b/atest/robot/core/suite_setup_and_teardown.robot index d5f08a8a5bf..5db730961b7 100644 --- a/atest/robot/core/suite_setup_and_teardown.robot +++ b/atest/robot/core/suite_setup_and_teardown.robot @@ -1,35 +1,32 @@ *** Settings *** -Resource atest_resource.robot +Resource atest_resource.robot *** Variables *** -${1 PASS MSG} 1 test, 1 passed, 0 failed -${1 FAIL MSG} 1 test, 0 passed, 1 failed -${2 FAIL MSG} 2 tests, 0 passed, 2 failed -${4 FAIL MSG} 4 tests, 0 passed, 4 failed -${5 FAIL MSG} 5 tests, 0 passed, 5 failed -${12 FAIL MSG} 12 tests, 0 passed, 12 failed -${ALSO} \n\nAlso teardown of the parent suite failed. +${1 PASS MSG} 1 test, 1 passed, 0 failed +${1 FAIL MSG} 1 test, 0 passed, 1 failed +${2 FAIL MSG} 2 tests, 0 passed, 2 failed +${4 FAIL MSG} 4 tests, 0 passed, 4 failed +${5 FAIL MSG} 5 tests, 0 passed, 5 failed +${12 FAIL MSG} 12 tests, 0 passed, 12 failed +${ALSO} \n\nAlso teardown of the parent suite failed. ${EXECUTED FILE} %{TEMPDIR}/robot-suite-teardown-executed.txt *** Test Cases *** Passing Suite Setup Run Tests ${EMPTY} core/passing_suite_setup.robot - Check Suite Status ${SUITE} PASS ${1 PASS MSG} - ... Verify Suite Setup + Check Suite Status ${SUITE} PASS ${1 PASS MSG} Verify Suite Setup Passing Suite Teardown [Setup] Remove File ${EXECUTED FILE} Run Tests ${EMPTY} core/passing_suite_teardown.robot - Check Suite Status ${SUITE} PASS ${1 PASS MSG} - ... Test + Check Suite Status ${SUITE} PASS ${1 PASS MSG} Test File Should Exist ${EXECUTED FILE} [Teardown] Remove File ${EXECUTED FILE} Passing Suite Setup And Teardown [Setup] Remove File ${EXECUTED FILE} Run Tests ${EMPTY} core/passing_suite_setup_and_teardown.robot - Check Suite Status ${SUITE} PASS ${1 PASS MSG} - ... Verify Suite Setup + Check Suite Status ${SUITE} PASS ${1 PASS MSG} Verify Suite Setup File Should Exist ${EXECUTED FILE} [Teardown] Remove File ${EXECUTED FILE} @@ -38,11 +35,10 @@ Failing Suite Setup Check Suite Status ${SUITE} FAIL ... Suite setup failed:\nExpected failure\n\n${2 FAIL MSG} ... Test 1 Test 2 - Should Be Equal ${SUITE.setup.status} FAIL - Should Be Equal ${SUITE.teardown.status} PASS - Length Should Be ${SUITE.teardown.msgs} 1 + Should Be Equal ${SUITE.setup.status} FAIL + Should Be Equal ${SUITE.teardown.status} PASS + Length Should Be ${SUITE.teardown.body} 1 Check Log Message ${SUITE.teardown.messages[0]} Suite teardown executed - Should Be Empty ${SUITE.teardown.kws} Erroring Suite Setup Run Tests ${EMPTY} core/erroring_suite_setup.robot @@ -50,15 +46,15 @@ Erroring Suite Setup ... Suite setup failed:\nNo keyword with name 'Non-Existing Keyword' found.\n\n${2 FAIL MSG} ... Test 1 Test 2 Should Be Equal ${SUITE.setup.status} FAIL - ${td} = Set Variable ${SUITE.teardown} - Should Be Equal ${td.name} My TD - Should Be Equal ${td.status} PASS - Should Be Empty ${td.msgs} - Length Should Be ${td.kws} 2 - Length Should Be ${td.kws[0].msgs} 1 - Check Log Message ${td.kws[0].msgs[0]} Hello from suite teardown! - Should Be Empty ${td.kws[0].kws} - Should Be Equal ${td.kws[1].name} BuiltIn.No Operation + VAR ${td} ${SUITE.teardown} + Should Be Equal ${td.name} My TD + Should Be Equal ${td.status} PASS + Length Should Be ${td.body} 2 + Length Should Be ${td.messages} 0 + Length Should Be ${td[0].body} 1 + Length Should Be ${td[0].messages} 1 + Check Log Message ${td[0, 0]} Hello from suite teardown! + Should Be Equal ${td[1].full_name} BuiltIn.No Operation Failing Higher Level Suite Setup Run Tests ${EMPTY} core/failing_higher_level_suite_setup @@ -104,7 +100,7 @@ Failing Suite Setup And Teardown ... in two lines Check Suite Status ${SUITE} FAIL ${error}\n\n${2 FAIL MSG} ... Test 1 Test 2 - Should Be Equal ${SUITE.setup.status} FAIL + Should Be Equal ${SUITE.setup.status} FAIL Should Be Equal ${SUITE.teardown.status} FAIL Output should contain teardown error Teardown failure\nin two lines @@ -161,10 +157,14 @@ Long Error Messages *** Keywords *** Check Suite Status [Arguments] ${suite or name} ${status} ${message} @{tests} - ${is string} = Run Keyword And Return Status Should Be String ${suite or name} - ${suite} = Run Keyword If ${is string} Get Test Suite ${suite or name} - ... ELSE Set Variable ${suite or name} - Should Be Equal ${suite.status} ${status} Wrong suite status + TRY + Should Be String ${suite or name} + EXCEPT + VAR ${suite} ${suite or name} + ELSE + ${suite} = Get Test Suite ${suite or name} + END + Should Be Equal ${suite.status} ${status} Wrong suite status Should Be Equal ${suite.full_message} ${message} Wrong suite message Should Contain Tests ${suite} @{tests} diff --git a/atest/robot/core/test_suite_init_file.robot b/atest/robot/core/test_suite_init_file.robot index 59d27cef032..fa952fba835 100644 --- a/atest/robot/core/test_suite_init_file.robot +++ b/atest/robot/core/test_suite_init_file.robot @@ -21,14 +21,14 @@ Suite Documentation Suite Setup [Documentation] Setting and not setting setup using suite file - Check Log Message ${suite.setup.kws[0].msgs[0]} Setup of test suite directory + Check Log Message ${suite.setup[0, 0]} Setup of test suite directory Setup Should Not Be Defined ${subsuite_with_init} Setup Should Not Be Defined ${subsuite_without_init} Suite Teardown [Documentation] Setting and not setting teardown using suite file - Check Log Message ${suite.teardown.kws[1].msgs[0]} Teardown of test suite directory - Check Log Message ${subsuite_with_init.teardown.kws[1].msgs[0]} Teardown of sub test suite directory + Check Log Message ${suite.teardown[1, 0]} Teardown of test suite directory + Check Log Message ${subsuite_with_init.teardown[1, 0]} Teardown of sub test suite directory Teardown Should Not Be Defined ${subsuite_without_init} Invalid Suite Setting diff --git a/atest/robot/keywords/async_keywords.robot b/atest/robot/keywords/async_keywords.robot new file mode 100644 index 00000000000..034ade1cb7e --- /dev/null +++ b/atest/robot/keywords/async_keywords.robot @@ -0,0 +1,27 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/async_keywords.robot +Resource atest_resource.robot + +*** Test Cases *** +Works With Asyncio Run + [Tags] require-py3.7 + Check Test Case ${TESTNAME} + +Basic Async Works + Check Test Case ${TESTNAME} + +Works Using Gather + Check Test Case ${TESTNAME} + +Long Async Tasks Run In Background + [Tags] require-py3.7 + Check Test Case ${TESTNAME} + +Builtin Call From Library Works + Check Test Case ${TESTNAME} + +Create Task With Loop Reference + Check Test Case ${TESTNAME} + +Generators Do Not Use Event Loop + Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/dots_in_keyword_name.robot b/atest/robot/keywords/dots_in_keyword_name.robot index ac30e4bf2c8..1ea6962e9a1 100644 --- a/atest/robot/keywords/dots_in_keyword_name.robot +++ b/atest/robot/keywords/dots_in_keyword_name.robot @@ -44,5 +44,5 @@ Dots in library name and keyword name with full name Conflicting names with dots ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} Running keyword 'Conflict'. - Check log message ${tc.kws[1].msgs[0]} Executing keyword 'In.name.conflict'. + Check log message ${tc[0, 0]} Running keyword 'Conflict'. + Check log message ${tc[1, 0]} Executing keyword 'In.name.conflict'. diff --git a/atest/robot/keywords/duplicate_dynamic_keywords.robot b/atest/robot/keywords/duplicate_dynamic_keywords.robot index eb587323ca7..15e1a07854b 100644 --- a/atest/robot/keywords/duplicate_dynamic_keywords.robot +++ b/atest/robot/keywords/duplicate_dynamic_keywords.robot @@ -5,14 +5,14 @@ Resource atest_resource.robot *** Test Cases *** Using keyword defined multiple times fails ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} DupeDynamicKeywords.DEFINED TWICE + Should Be Equal ${tc[0].full_name} DupeDynamicKeywords.Defined Twice Error in library DupeDynamicKeywords ... Adding keyword 'DEFINED TWICE' failed: ... Keyword with same name defined multiple times. Keyword with embedded arguments defined multiple times fails at run-time ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} Embedded twice + Should Be Equal ${tc[0].full_name} Embedded twice Length Should Be ${ERRORS} 1 Exact duplicate is accepted diff --git a/atest/robot/keywords/duplicate_hybrid_keywords.robot b/atest/robot/keywords/duplicate_hybrid_keywords.robot index 992fadcc07a..3269b524a3c 100644 --- a/atest/robot/keywords/duplicate_hybrid_keywords.robot +++ b/atest/robot/keywords/duplicate_hybrid_keywords.robot @@ -5,14 +5,14 @@ Resource atest_resource.robot *** Test Cases *** Using keyword defined multiple times fails ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} DupeHybridKeywords.DEFINED TWICE + Should Be Equal ${tc[0].full_name} DupeHybridKeywords.Defined Twice Error in library DupeHybridKeywords ... Adding keyword 'DEFINED TWICE' failed: ... Keyword with same name defined multiple times. Keyword with embedded arguments defined multiple times fails at run-time ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} Embedded twice + Should Be Equal ${tc[0].full_name} Embedded twice Length Should Be ${ERRORS} 1 Exact duplicate is accepted diff --git a/atest/robot/keywords/duplicate_static_keywords.robot b/atest/robot/keywords/duplicate_static_keywords.robot index 37e30927004..c2d9ce15ff7 100644 --- a/atest/robot/keywords/duplicate_static_keywords.robot +++ b/atest/robot/keywords/duplicate_static_keywords.robot @@ -5,20 +5,20 @@ Resource atest_resource.robot *** Test Cases *** Using keyword defined twice fails ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} DupeKeywords.Defined twice + Should Be Equal ${tc[0].full_name} DupeKeywords.Defined Twice Creating keyword should have failed 2 Defined twice Using keyword defined thrice fails as well ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} DupeKeywords.Defined Thrice + Should Be Equal ${tc[0].full_name} DupeKeywords.Defined Thrice Creating keyword should have failed 0 Defined Thrice Creating keyword should have failed 1 Defined Thrice Keyword with embedded arguments defined twice fails at run-time ${tc} = Check Test Case ${TESTNAME}: Called with embedded args - Should Be Equal ${tc.kws[0].name} Embedded arguments twice + Should Be Equal ${tc[0].full_name} Embedded arguments twice ${tc} = Check Test Case ${TESTNAME}: Called with exact name - Should Be Equal ${tc.kws[0].name} Embedded \${arguments match} twice + Should Be Equal ${tc[0].full_name} Embedded \${arguments match} twice Length Should Be ${ERRORS} 3 *** Keywords *** diff --git a/atest/robot/keywords/dynamic_positional_only_args.robot b/atest/robot/keywords/dynamic_positional_only_args.robot new file mode 100644 index 00000000000..98ead1c7c55 --- /dev/null +++ b/atest/robot/keywords/dynamic_positional_only_args.robot @@ -0,0 +1,53 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/dynamic_positional_only_args.robot +Resource atest_resource.robot + +*** Test Cases *** +One Argument + Check Test Case ${TESTNAME} + +Three arguments + Check Test Case ${TESTNAME} + +Pos and named + Check Test Case ${TESTNAME} + +Pos and names too few arguments + Check Test Case ${TESTNAME} + +Three arguments too many arguments + Check Test Case ${TESTNAME} + +Pos with default + Check Test Case ${TESTNAME} + +All args + Check Test Case ${TESTNAME} + +Too many markers + Validate invalid arg spec error 0 + ... Too many markers + ... Too many positional-only separators. + +After varargs + Validate invalid arg spec error 1 + ... After varargs + ... Positional-only separator must be before named-only arguments. + +After named-only marker + Validate invalid arg spec error 2 + ... After named-only marker + ... Positional-only separator must be before named-only arguments. + +After kwargs + Validate invalid arg spec error 3 + ... After kwargs + ... Only last argument can be kwargs. + +*** Keywords *** +Validate invalid arg spec error + [Arguments] ${index} ${name} ${error} + Error in library + ... DynamicPositionalOnly + ... Adding keyword '${name}' failed: Invalid argument specification: ${error} + ... index=${index} diff --git a/atest/robot/keywords/embedded_arguments.robot b/atest/robot/keywords/embedded_arguments.robot index 93b8103f887..b17b2ccfccc 100644 --- a/atest/robot/keywords/embedded_arguments.robot +++ b/atest/robot/keywords/embedded_arguments.robot @@ -5,62 +5,60 @@ Resource atest_resource.robot *** Test Cases *** Embedded Arguments In User Keyword Name ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} This is always executed - Check Keyword Data ${tc.kws[0]} User Peke Selects Advanced Python From Webshop \${name}, \${book} - Check Log Message ${tc.kws[2].kws[0].msgs[0]} This is always executed - Check Keyword Data ${tc.kws[2]} User Juha Selects Playboy From Webshop \${name}, \${book} - File Should Contain ${OUTFILE} - ... name="User Peke Selects Advanced Python From Webshop" - File Should Contain ${OUTFILE} - ... sourcename="User \${user} Selects \${item} From Webshop" - File Should Not Contain ${OUTFILE} sourcename="Log" + Check Log Message ${tc[0, 0, 0]} This is always executed + Check Keyword Data ${tc[0]} User Peke Selects Advanced Python From Webshop \${name}, \${book} + Check Log Message ${tc[2, 0, 0]} This is always executed + Check Keyword Data ${tc[2]} User Juha Selects Playboy From Webshop \${name}, \${book} + File Should Contain ${OUTFILE} name="User Peke Selects Advanced Python From Webshop" + File Should Contain ${OUTFILE} source_name="User \${user} Selects \${item} From Webshop" + File Should Not Contain ${OUTFILE} source_name="Log" Complex Embedded Arguments ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} feature-works - Check Log Message ${tc.kws[1].kws[0].msgs[0]} test case-is *executed* - Check Log Message ${tc.kws[2].kws[0].msgs[0]} issue-is about to be done! - File Should Contain ${OUTFILE} sourcename="\${prefix:Given|When|Then} this - File Should Not Contain ${OUTFILE} sourcename="Log" + Check Log Message ${tc[0, 0, 0]} feature-works + Check Log Message ${tc[1, 0, 0]} test case-is *executed* + Check Log Message ${tc[2, 0, 0]} issue-is about to be done! + File Should Contain ${OUTFILE} source_name="\${prefix:Given|When|Then} this + File Should Not Contain ${OUTFILE} source_name="Log" Embedded Arguments with BDD Prefixes ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} Given user x selects y from webshop - Check Keyword Data ${tc.kws[1]} When user x selects y from webshop - Check Keyword Data ${tc.kws[2]} Then user x selects y from webshop \${x}, \${y} - File Should Contain ${OUTFILE} - ... name="Given user x selects y from webshop" - File Should Contain ${OUTFILE} - ... sourcename="User \${user} Selects \${item} From Webshop" - File Should Not Contain ${OUTFILE} sourcename="Log" + Check Keyword Data ${tc[0]} Given user x selects y from webshop + Check Keyword Data ${tc[1]} When user x selects y from webshop + Check Keyword Data ${tc[2]} Then user x selects y from webshop \${x}, \${y} + File Should Contain ${OUTFILE} name="Given user x selects y from webshop" + File Should Contain ${OUTFILE} source_name="User \${user} Selects \${item} From Webshop" + File Should Not Contain ${OUTFILE} source_name="Log" Argument Namespaces with Embedded Arguments Check Test Case ${TEST NAME} - File Should Contain ${OUTFILE} name="My embedded warrior" - File Should Contain ${OUTFILE} sourcename="My embedded \${var}" - File Should Not Contain ${OUTFILE} sourcename="Log" + File Should Contain ${OUTFILE} name="My embedded warrior" + File Should Contain ${OUTFILE} source_name="My embedded \${var}" + File Should Not Contain ${OUTFILE} source_name="Log" Embedded Arguments as Variables ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} User \${42} Selects \${EMPTY} From Webshop \${name}, \${item} - Check Keyword Data ${tc.kws[2]} User \${name} Selects \${SPACE * 10} From Webshop \${name}, \${item} - File Should Contain ${OUTFILE} - ... name="User \${42} Selects \${EMPTY} From Webshop" - File Should Contain ${OUTFILE} - ... sourcename="User \${user} Selects \${item} From Webshop" - File Should Contain ${OUTFILE} - ... name="User \${name} Selects \${SPACE * 10} From Webshop" - File Should Contain ${OUTFILE} - ... sourcename="User \${user} Selects \${item} From Webshop" - File Should Not Contain ${OUTFILE} sourcename="Log"> + Check Keyword Data ${tc[0]} User \${42} Selects \${EMPTY} From Webshop \${name}, \${item} + Check Keyword Data ${tc[2]} User \${name} Selects \${SPACE * 100}[:10] From Webshop \${name}, \${item} + File Should Contain ${OUTFILE} name="User \${42} Selects \${EMPTY} From Webshop" + File Should Contain ${OUTFILE} name="User \${name} Selects \${SPACE * 100}[:10] From Webshop" + File Should Contain ${OUTFILE} source_name="User \${user} Selects \${item} From Webshop" + File Should Not Contain ${OUTFILE} source_name="Log"> + +Embedded arguments as variables and other content + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} User \${foo}\${EMPTY}\${bar} Selects \${foo}, \${bar} and \${zap} From Webshop \${name}, \${item} + +Embedded arguments as variables containing characters in keyword name + Check Test Case ${TEST NAME} Embedded Arguments as List And Dict Variables ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[1]} User \@{i1} Selects \&{i2} From Webshop \${o1}, \${o2} + Check Keyword Data ${tc[1]} User \@{i1} Selects \&{i2} From Webshop \${o1}, \${o2} Non-Existing Variable in Embedded Arguments ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} User \${non existing} Selects \${variables} From Webshop status=FAIL + Check Keyword Data ${tc[0]} User \${non existing} Selects \${variables} From Webshop status=FAIL Invalid List Variable as Embedded Argument Check Test Case ${TEST NAME} @@ -89,32 +87,44 @@ Grouping Custom Regexp Custom Regexp Matching Variables Check Test Case ${TEST NAME} -Custom Regexp Matching Variables When Regexp Does No Match Them +Custom regexp with inline Python evaluation Check Test Case ${TEST NAME} -Regexp Extensions Are Not Supported +Non Matching Variable Is Accepted With Custom Regexp (But Not For Long) + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} + ... Embedded argument 'x' got value 'foo' that does not match custom pattern 'bar'. The argument is still accepted, but this behavior will change in Robot Framework 8.0. WARN + +Partially Matching Variable Is Accepted With Custom Regexp (But Not For Long) + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} + ... Embedded argument 'x' got value 'ba' that does not match custom pattern 'bar'. The argument is still accepted, but this behavior will change in Robot Framework 8.0. WARN + Check Log Message ${tc[0, 1]} + ... Embedded argument 'y' got value 'zapzap' that does not match custom pattern '...'. The argument is still accepted, but this behavior will change in Robot Framework 8.0. WARN + +Non String Variable Is Accepted With Custom Regexp + Check Test Case ${TEST NAME} + +Custom regexp with inline flag Check Test Case ${TEST NAME} - Creating Keyword Failed 1 277 - ... Regexp extensions like \${x:(?x)re} are not supported - ... Regexp extensions are not allowed in embedded arguments. Invalid Custom Regexp Check Test Case ${TEST NAME} - Creating Keyword Failed 2 280 + Creating Keyword Failed 0 334 ... Invalid \${x:(} Regexp ... Compiling embedded arguments regexp failed: * Escaping Values Given As Embedded Arguments ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} User \\\${nonex} Selects \\\\ From Webshop \${name}, \${item} - Check Keyword Data ${tc.kws[2]} User \\ Selects \\ \\ From Webshop \${name}, \${item} + Check Keyword Data ${tc[0]} User \\\${nonex} Selects \\\\ From Webshop \${name}, \${item} + Check Keyword Data ${tc[2]} User \\ Selects \\ \\ From Webshop \${name}, \${item} Embedded Arguments Syntax Is Case Insensitive ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} x Gets y From The z - Check Keyword Data ${tc.kws[1]} x gets y from the z - Check Keyword Data ${tc.kws[2]} x GETS y from the z - Check Keyword Data ${tc.kws[3]} x gets y FROM THE z + Check Keyword Data ${tc[0]} x Gets y From The z + Check Keyword Data ${tc[1]} x gets y from the z + Check Keyword Data ${tc[2]} x GETS y from the z + Check Keyword Data ${tc[3]} x gets y FROM THE z Embedded Arguments Syntax is Space Sensitive Check Test Case ${TEST NAME} @@ -124,48 +134,51 @@ Embedded Arguments Syntax is Underscore Sensitive Embedded Arguments In Resource File ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} embedded_args_in_uk_1.Juha Uses Resource File \${ret} + Check Keyword Data ${tc[0]} embedded_args_in_uk_1.Juha Uses Resource File \${ret} Embedded Arguments In Resource File Used Explicitly ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} embedded_args_in_uk_1.peke uses resource file \${ret} + Check Keyword Data ${tc[0]} embedded_args_in_uk_1.peke uses resource file \${ret} -Embedded And Positional Arguments Do Not Work Together +Keyword with only embedded arguments doesn't accept normal arguments Check Test Case ${TEST NAME} Keyword with embedded args cannot be used as "normal" keyword Check Test Case ${TEST NAME} -Creating keyword with both normal and embedded arguments fails - Creating Keyword Failed 0 223 - ... Keyword with \${embedded} and normal args is invalid - ... Keyword cannot have both normal and embedded arguments. +Keyword with both embedded and normal arguments + ${tc} = Check Test Case ${TEST NAME} + Check Log message ${tc[0, 0, 0]} 2 horses are walking + Check Log message ${tc[1, 0, 0]} 2 horses are swimming + Check Log message ${tc[2, 0, 0]} 3 dogs are walking + +Keyword with both embedded and normal arguments with too few arguments Check Test Case ${TEST NAME} Keyword matching multiple keywords in test case file ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} foo+tc+bar - Check Log Message ${tc.kws[1].kws[0].msgs[0]} foo-tc-bar - Check Log Message ${tc.kws[2].kws[0].msgs[0]} foo+tc+bar+tc+zap + Check Log Message ${tc[0, 0, 0]} foo+tc+bar + Check Log Message ${tc[1, 0, 0]} foo-tc-bar + Check Log Message ${tc[2, 0, 0]} foo+tc+bar+tc+zap Keyword matching multiple keywords in one resource file ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} foo+r1+bar - Check Log Message ${tc.kws[1].kws[0].msgs[0]} foo-r1-bar + Check Log Message ${tc[0, 0, 0]} foo+r1+bar + Check Log Message ${tc[1, 0, 0]} foo-r1-bar Keyword matching multiple keywords in different resource files ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} foo-r1-bar - Check Log Message ${tc.kws[1].kws[0].msgs[0]} foo-r2-bar + Check Log Message ${tc[0, 0, 0]} foo-r1-bar + Check Log Message ${tc[1, 0, 0]} foo-r2-bar Keyword matching multiple keywords in one and different resource files Check Test Case ${TEST NAME} Same name with different regexp works ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} a car - Check Log Message ${tc.kws[1].kws[0].msgs[0]} a dog - Check Log Message ${tc.kws[2].kws[0].msgs[0]} a cow + Check Log Message ${tc[0, 0, 0]} a car + Check Log Message ${tc[1, 0, 0]} a dog + Check Log Message ${tc[2, 0, 0]} a cow Same name with different regexp matching multiple fails Check Test Case ${TEST NAME} diff --git a/atest/robot/keywords/embedded_arguments_conflicts.robot b/atest/robot/keywords/embedded_arguments_conflicts.robot new file mode 100644 index 00000000000..68779178bf0 --- /dev/null +++ b/atest/robot/keywords/embedded_arguments_conflicts.robot @@ -0,0 +1,86 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/embedded_arguments_conflicts.robot +Resource atest_resource.robot + +*** Test Cases *** +Unique match in suite file + Check Test Case ${TESTNAME} + +Best match wins in suite file + Check Test Case ${TESTNAME} + +Conflict in suite file + Check Test Case ${TESTNAME} 1 + Check Test Case ${TESTNAME} 2 + +Unique match in resource + Check Test Case ${TESTNAME} + +Best match wins in resource + Check Test Case ${TESTNAME} + +Conflict in resource + Check Test Case ${TESTNAME} + +Unique match in resource with explicit usage + Check Test Case ${TESTNAME} + +Best match wins in resource with explicit usage + Check Test Case ${TESTNAME} + +Conflict in resource with explicit usage + Check Test Case ${TESTNAME} + +Unique match in library + Check Test Case ${TESTNAME} + +Best match wins in library + Check Test Case ${TESTNAME} + +Conflict in library + Check Test Case ${TESTNAME} + +Unique match in library with explicit usage + Check Test Case ${TESTNAME} + +Best match wins in library with explicit usage + Check Test Case ${TESTNAME} + +Conflict in library with explicit usage + Check Test Case ${TESTNAME} + +Search order resolves conflict with resources + Check Test Case ${TESTNAME} + +Search order wins over best match in resource + Check Test Case ${TESTNAME} + +Search order resolves conflict with libraries + Check Test Case ${TESTNAME} + +Search order wins over best match in libraries + Check Test Case ${TESTNAME} + +Search order cannot resolve conflict within resource + Check Test Case ${TESTNAME} + +Search order causes conflict within resource + Check Test Case ${TESTNAME} + +Search order cannot resolve conflict within library + Check Test Case ${TESTNAME} + +Search order causes conflict within library + Check Test Case ${TESTNAME} + +Public match wins over better private match in different resource + Check Test Case ${TESTNAME} + +Match in same resource wins over better match elsewhere + Check Test Case ${TESTNAME} + +Keyword without embedded arguments wins over keyword with them in same file + Check Test Case ${TESTNAME} + +Keyword without embedded arguments wins over keyword with them in different file + Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/embedded_arguments_library_keywords.robot b/atest/robot/keywords/embedded_arguments_library_keywords.robot index 2720592bfd1..85893658173 100755 --- a/atest/robot/keywords/embedded_arguments_library_keywords.robot +++ b/atest/robot/keywords/embedded_arguments_library_keywords.robot @@ -5,66 +5,69 @@ Resource atest_resource.robot *** Test Cases *** Embedded Arguments In Library Keyword Name ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} This is always executed - Check Keyword Data ${tc.kws[0]} embedded_args_in_lk_1.User Peke Selects Advanced Python From Webshop \${name}, \${book} - Check Log Message ${tc.kws[2].msgs[0]} This is always executed - Check Keyword Data ${tc.kws[2]} embedded_args_in_lk_1.User Juha selects Playboy from webshop \${name}, \${book} - File Should Contain ${OUTFILE} - ... name="User Peke Selects Advanced Python From Webshop" - File Should Contain ${OUTFILE} - ... library="embedded_args_in_lk_1" - File Should Contain ${OUTFILE} - ... sourcename="User \${user} Selects \${item} From Webshop" - File Should Not Contain ${OUTFILE} sourcename="Log" + Check Log Message ${tc[0, 0]} This is always executed + Check Keyword Data ${tc[0]} embedded_args_in_lk_1.User Peke Selects Advanced Python From Webshop \${name}, \${book} + Check Log Message ${tc[2, 0]} This is always executed + Check Keyword Data ${tc[2]} embedded_args_in_lk_1.User Juha selects Playboy from webshop \${name}, \${book} + File Should Contain ${OUTFILE} name="User Peke Selects Advanced Python From Webshop" + File Should Contain ${OUTFILE} owner="embedded_args_in_lk_1" + File Should Contain ${OUTFILE} source_name="User \${user} Selects \${item} From Webshop" + File Should Not Contain ${OUTFILE} source_name="Log" Complex Embedded Arguments ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} feature-works - Check Log Message ${tc.kws[1].msgs[0]} test case-is *executed* - Check Log Message ${tc.kws[2].msgs[0]} issue-is about to be done! - File Should Contain ${OUTFILE} sourcename="\${prefix:Given|When|Then} this - File Should Not Contain ${OUTFILE} sourcename="Log" + Check Log Message ${tc[0, 0]} feature-works + Check Log Message ${tc[1, 0]} test case-is *executed* + Check Log Message ${tc[2, 0]} issue-is about to be done! + File Should Contain ${OUTFILE} source_name="\${prefix:Given|When|Then} this + File Should Not Contain ${OUTFILE} source_name="Log" Embedded Arguments with BDD Prefixes ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} embedded_args_in_lk_1.Given user x selects y from webshop - Check Keyword Data ${tc.kws[1]} embedded_args_in_lk_1.When user x selects y from webshop - Check Keyword Data ${tc.kws[2]} embedded_args_in_lk_1.Then user x selects y from webshop \${x}, \${y} - File Should Contain ${OUTFILE} name="Given user x selects y from webshop" - File Should Contain ${OUTFILE} library="embedded_args_in_lk_1" - File Should Contain ${OUTFILE} sourcename="User \${user} Selects \${item} From Webshop" - File Should Not Contain ${OUTFILE} sourcename="Log" + Check Keyword Data ${tc[0]} embedded_args_in_lk_1.Given user x selects y from webshop + Check Keyword Data ${tc[1]} embedded_args_in_lk_1.When user x selects y from webshop + Check Keyword Data ${tc[2]} embedded_args_in_lk_1.Then user x selects y from webshop \${x}, \${y} + File Should Contain ${OUTFILE} name="Given user x selects y from webshop" + File Should Contain ${OUTFILE} owner="embedded_args_in_lk_1" + File Should Contain ${OUTFILE} source_name="User \${user} Selects \${item} From Webshop" + File Should Not Contain ${OUTFILE} source_name="Log" Argument Namespaces with Embedded Arguments Check Test Case ${TEST NAME} - File Should Contain ${OUTFILE} name="My embedded warrior" - File Should Contain ${OUTFILE} library="embedded_args_in_lk_1" - File Should Contain ${OUTFILE} sourcename="My embedded \${var}" - File Should Not Contain ${OUTFILE} sourcename="Log" + File Should Contain ${OUTFILE} name="My embedded warrior" + File Should Contain ${OUTFILE} owner="embedded_args_in_lk_1" + File Should Contain ${OUTFILE} source_name="My embedded \${var}" + File Should Not Contain ${OUTFILE} source_name="Log" Embedded Arguments as Variables ${tc} = Check Test Case ${TEST NAME} - File Should Contain ${OUTFILE} - ... name="User \${42} Selects \${EMPTY} From Webshop" - File Should Contain ${OUTFILE} - ... library="embedded_args_in_lk_1" - File Should Contain ${OUTFILE} - ... sourcename="User \${user} Selects \${item} From Webshop" - File Should Contain ${OUTFILE} - ... name="User \${name} Selects \${SPACE * 10} From Webshop" - File Should Not Contain ${OUTFILE} sourcename="Log" + File Should Contain ${OUTFILE} name="User \${42} Selects \${EMPTY} From Webshop" + File Should Contain ${OUTFILE} owner="embedded_args_in_lk_1" + File Should Contain ${OUTFILE} source_name="User \${user} Selects \${item} From Webshop" + File Should Contain ${OUTFILE} name="User \${name} Selects \${SPACE * 100}[:10] From Webshop" + File Should Not Contain ${OUTFILE} source_name="Log" + +Embedded arguments as variables and other content + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} embedded_args_in_lk_1.User \${foo}\${EMPTY}\${bar} Selects \${foo}, \${bar} and \${zap} From Webshop \${name}, \${item} + +Embedded arguments as variables containing characters in keyword name + Check Test Case ${TEST NAME} Embedded Arguments as List And Dict Variables ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[1]} embedded_args_in_lk_1.User \@{i1} Selects \&{i2} From Webshop \${o1}, \${o2} + Check Keyword Data ${tc[1]} embedded_args_in_lk_1.User \@{inp1} Selects \&{inp2} From Webshop \${out1}, \${out2} Non-Existing Variable in Embedded Arguments ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} embedded_args_in_lk_1.User \${non existing} Selects \${variables} From Webshop status=FAIL + Check Keyword Data ${tc[0]} embedded_args_in_lk_1.User \${non existing} Selects \${variables} From Webshop status=FAIL Custom Embedded Argument Regexp Check Test Case ${TEST NAME} +Custom regexp with inline flags + Check Test Case ${TEST NAME} + Custom Regexp With Curly Braces Check Test Case ${TEST NAME} @@ -77,7 +80,22 @@ Grouping Custom Regexp Custom Regexp Matching Variables Check Test Case ${TEST NAME} -Custom Regexp Matching Variables When Regexp Does No Match Them +Custom regexp with inline Python evaluation + Check Test Case ${TEST NAME} + +Non Matching Variable Is Accepted With Custom Regexp (But Not For Long) + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} + ... Embedded argument 'x' got value 'foo' that does not match custom pattern 'bar'. The argument is still accepted, but this behavior will change in Robot Framework 8.0. WARN + +Partially Matching Variable Is Accepted With Custom Regexp (But Not For Long) + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} + ... Embedded argument 'x' got value 'ba' that does not match custom pattern 'bar'. The argument is still accepted, but this behavior will change in Robot Framework 8.0. WARN + Check Log Message ${tc[0, 1]} + ... Embedded argument 'y' got value 'zapzap' that does not match custom pattern '...'. The argument is still accepted, but this behavior will change in Robot Framework 8.0. WARN + +Non String Variable Is Accepted With Custom Regexp Check Test Case ${TEST NAME} Embedded Arguments Syntax is Space Sensitive @@ -88,36 +106,51 @@ Embedded Arguments Syntax is Underscore Sensitive Keyword matching multiple keywords in library file ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} foo+lib+bar - Check Log Message ${tc.kws[1].msgs[0]} foo-lib-bar - Check Log Message ${tc.kws[2].msgs[0]} foo+lib+bar+lib+zap + Check Log Message ${tc[0, 0]} foo+lib+bar + Check Log Message ${tc[1, 0]} foo-lib-bar + Check Log Message ${tc[2, 0]} foo+lib+bar+lib+zap Keyword matching multiple keywords in different library files Check Test Case ${TEST NAME} -Embedded And Positional Arguments Do Not Work Together +Keyword with only embedded arguments doesn't accept normal arguments Check Test Case ${TEST NAME} Keyword with embedded args cannot be used as "normal" keyword Check Test Case ${TEST NAME} -Embedded argument count must match accepted arguments +Keyword with both embedded and normal arguments + ${tc} = Check Test Case ${TEST NAME} + Check Log message ${tc[0, 0]} 2 horses are walking + Check Log message ${tc[1, 0]} 2 horses are swimming + Check Log message ${tc[2, 0]} 3 dogs are walking + +Conversion with embedded and normal arguments + Check Test Case ${TEST NAME} + +Keyword with both embedded and normal arguments with too few arguments + Check Test Case ${TEST NAME} + +Must accept at least as many positional arguments as there are embedded arguments Check Test Case ${TESTNAME} Error in library embedded_args_in_lk_1 ... Adding keyword 'Wrong \${number} of embedded \${args}' failed: - ... Embedded argument count does not match number of accepted arguments. + ... Keyword must accept at least as many positional arguments as it has embedded arguments. Optional Non-Embedded Args Are Okay Check Test Case ${TESTNAME} -Star Args With Embedded Args Are Okay +Varargs With Embedded Args Are Okay + Check Test Case ${TESTNAME} + +Lists are not expanded when keyword accepts varargs Check Test Case ${TESTNAME} Same name with different regexp works ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} a car - Check Log Message ${tc.kws[1].msgs[0]} a dog - Check Log Message ${tc.kws[2].msgs[0]} a cow + Check Log Message ${tc[0, 0]} a car + Check Log Message ${tc[1, 0]} a dog + Check Log Message ${tc[2, 0]} a cow Same name with different regexp matching multiple fails Check Test Case ${TEST NAME} diff --git a/atest/robot/keywords/keyword_documentation.robot b/atest/robot/keywords/keyword_documentation.robot index 8cc336b170e..2ae9f37eeba 100644 --- a/atest/robot/keywords/keyword_documentation.robot +++ b/atest/robot/keywords/keyword_documentation.robot @@ -26,4 +26,4 @@ Multiline documentation with split short doc Verify Documentation [Arguments] ${doc} ${test}=${TEST NAME} ${tc} = Check Test Case ${test} - Should Be Equal ${tc.kws[0].doc} ${doc} + Should Be Equal ${tc[0].doc} ${doc} diff --git a/atest/robot/keywords/keyword_names.robot b/atest/robot/keywords/keyword_names.robot index 4fc7cc7b117..dccf6c6afa7 100644 --- a/atest/robot/keywords/keyword_names.robot +++ b/atest/robot/keywords/keyword_names.robot @@ -20,38 +20,38 @@ Base Keyword Names In Test Case Test Case File User Keyword Names In Test Case File User Keyword ${test} = Check Test Case Test Case File User Keyword Names In Test Case File User Keyword - Check Name and Three Keyword Names ${test.body[0]} Using Test Case File User Keywords Keyword Only In Test Case File - Should Be Equal ${test.body[1].name} Using Test Case File User Keywords Nested - Check Name and Three Keyword Names ${test.body[1].body[0]} Using Test Case File User Keywords Keyword Only In Test Case File - Check Name and Three Keyword Names ${test.body[1].body[1]} Using Test Case File User Keywords Keyword Only In Test Case File + Check Name and Three Keyword Names ${test[0]} Using Test Case File User Keywords Keyword Only In Test Case File + Should Be Equal ${test[1].full_name} Using Test Case File User Keywords Nested + Check Name and Three Keyword Names ${test[1, 0]} Using Test Case File User Keywords Keyword Only In Test Case File + Check Name and Three Keyword Names ${test[1, 1]} Using Test Case File User Keywords Keyword Only In Test Case File Resource File User Keyword Names In Test Case File User Keyword ${test} = Check Test Case Resource File User Keyword Names In Test Case File User Keyword - Check Name and Three Keyword Names ${test.body[0]} Using Resource File User Keywords my_resource_1.Keyword Only In Resource 1 - Should Be Equal ${test.body[1].name} Using Resource File User Keywords Nested - Check Name and Three Keyword Names ${test.body[1].body[0]} Using Resource File User Keywords my_resource_1.Keyword Only In Resource 1 - Check Name and Three Keyword Names ${test.body[1].body[1]} Using Resource File User Keywords my_resource_1.Keyword Only In Resource 1 + Check Name and Three Keyword Names ${test[0]} Using Resource File User Keywords my_resource_1.Keyword Only In Resource 1 + Should Be Equal ${test[1].full_name} Using Resource File User Keywords Nested + Check Name and Three Keyword Names ${test[1, 0]} Using Resource File User Keywords my_resource_1.Keyword Only In Resource 1 + Check Name and Three Keyword Names ${test[1, 1]} Using Resource File User Keywords my_resource_1.Keyword Only In Resource 1 Base Keyword Names In Test Case File User Keyword ${test} = Check Test Case Base Keyword Names In Test Case File User Keyword - Check Name and Three Keyword Names ${test.body[0]} Using Base Keywords MyLibrary1.Keyword Only In Library 1 - Should Be Equal ${test.body[1].name} Using Base Keywords Nested - Check Name and Three Keyword Names ${test.body[1].body[0]} Using Base Keywords MyLibrary1.Keyword Only In Library 1 - Check Name and Three Keyword Names ${test.body[1].body[1]} Using Base Keywords MyLibrary1.Keyword Only In Library 1 + Check Name and Three Keyword Names ${test[0]} Using Base Keywords MyLibrary1.Keyword Only In Library 1 + Should Be Equal ${test[1].full_name} Using Base Keywords Nested + Check Name and Three Keyword Names ${test[1, 0]} Using Base Keywords MyLibrary1.Keyword Only In Library 1 + Check Name and Three Keyword Names ${test[1, 1]} Using Base Keywords MyLibrary1.Keyword Only In Library 1 Test Case File User Keyword Names In Resource File User Keyword ${test} = Check Test Case Test Case File User Keyword Names In Resource File User Keyword - Should Be Equal ${test.body[0].name} my_resource_1.Using Test Case File User Keywords In Resource - Check Name and Three Keyword Names ${test.body[0].body[0]} Using Test Case File User Keywords Keyword Only In Test Case File + Should Be Equal ${test[0].full_name} my_resource_1.Using Test Case File User Keywords In Resource + Check Name and Three Keyword Names ${test[0, 0]} Using Test Case File User Keywords Keyword Only In Test Case File Resource File User Keyword Names In Resource File User Keyword ${test} = Check Test Case Resource File User Keyword Names In Resource File User Keyword - Check Name and Three Keyword Names ${test.body[0]} my_resource_1.Using Resource File User Keywords In Resource 1 my_resource_1.Keyword Only In Resource 1 - Check Name and Three Keyword Names ${test.body[1]} my_resource_1.Using Resource File User Keywords In Resource 2 my_resource_2.Keyword Only In Resource 2 + Check Name and Three Keyword Names ${test[0]} my_resource_1.Using Resource File User Keywords In Resource 1 my_resource_1.Keyword Only In Resource 1 + Check Name and Three Keyword Names ${test[1]} my_resource_1.Using Resource File User Keywords In Resource 2 my_resource_2.Keyword Only In Resource 2 Base Keyword Names In Resource File User Keyword ${test} = Check Test Case Base Keyword Names In Resource File User Keyword - Check Name and Three Keyword Names ${test.body[0]} my_resource_1.Using Base Keywords In Resource MyLibrary1.Keyword Only In Library 1 + Check Name and Three Keyword Names ${test[0]} my_resource_1.Using Base Keywords In Resource MyLibrary1.Keyword Only In Library 1 User Keyword Name Containing Dots Check Test And Three Keyword Names User Keyword Name Containing Dots User Keyword.Name @@ -61,47 +61,47 @@ User Keyword Name Ending With Dot Name Set Using 'robot_name' Attribute ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} MyLibrary1.Name set using 'robot_name' attribute - Check Log Message ${tc.kws[0].msgs[0]} My name was set using 'robot_name' attribute! + Should Be Equal ${tc[0].full_name} MyLibrary1.Name set using 'robot_name' attribute + Check Log Message ${tc[0, 0]} My name was set using 'robot_name' attribute! Name Set Using 'robot.api.deco.keyword' Decorator ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} MyLibrary1.Name set using 'robot.api.deco.keyword' decorator - Check Log Message ${tc.kws[0].msgs[0]} My name was set using 'robot.api.deco.keyword' decorator! + Should Be Equal ${tc[0].full_name} MyLibrary1.Name set using 'robot.api.deco.keyword' decorator + Check Log Message ${tc[0, 0]} My name was set using 'robot.api.deco.keyword' decorator! Custom non-ASCII name ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} MyLibrary1.Custom nön-ÄSCII name + Should Be Equal ${tc[0].full_name} MyLibrary1.Custom nön-ÄSCII name Old Name Doesn't Work If Name Set Using 'robot_name' Check Test Case ${TESTNAME} Keyword can just be marked without changing its name ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} MyLibrary1.No Custom Name Given 1 - Should Be Equal ${tc.kws[1].name} MyLibrary1.No Custom Name Given 2 + Should Be Equal ${tc[0].full_name} MyLibrary1.No Custom Name Given 1 + Should Be Equal ${tc[1].full_name} MyLibrary1.No Custom Name Given 2 Functions decorated with @keyword can start with underscrore ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].name} MyLibrary1.I Start With An Underscore And I Am Ok - Check Log Message ${tc.kws[0].msgs[0]} I'm marked with @keyword - Should Be Equal ${tc.kws[1].name} MyLibrary1.Function name can be whatever - Check Log Message ${tc.kws[1].msgs[0]} Real name set by @keyword + Should Be Equal ${tc[0].full_name} MyLibrary1.I Start With An Underscore And I Am Ok + Check Log Message ${tc[0, 0]} I'm marked with @keyword + Should Be Equal ${tc[1].full_name} MyLibrary1.Function name can be whatever + Check Log Message ${tc[1, 0]} Real name set by @keyword Assignment is not part of name ${tc} = Check Test Case ${TESTNAME} - Keyword name and assign should be ${tc.kws[0]} BuiltIn.Log - Keyword name and assign should be ${tc.kws[1]} BuiltIn.Set Variable \${var} - Keyword name and assign should be ${tc.kws[2]} BuiltIn.Set Variable \${v1} \${v2} - Keyword name and assign should be ${tc.kws[3]} BuiltIn.Evaluate \${first} \@{rest} + Check Keyword Data ${tc[0]} BuiltIn.Log args=No assignment + Check Keyword Data ${tc[1]} BuiltIn.Set Variable assign=\${var} args=value + Check Keyword Data ${tc[2]} BuiltIn.Set Variable assign=\${v1}, \${v2} args=1, 2 + Check Keyword Data ${tc[3]} BuiltIn.Evaluate assign=\${first}, \@{rest} args=range(10) Library name and keyword name are separate ${tc} = Check Test Case ${TESTNAME} - Keyword and library names should be ${tc.kws[0]} Keyword Only In Test Case File - Keyword and library names should be ${tc.kws[1]} Keyword Only In Resource 1 my_resource_1 - Keyword and library names should be ${tc.kws[2]} Keyword Only In Resource 1 my_resource_1 - Keyword and library names should be ${tc.kws[3]} Log BuiltIn - Keyword and library names should be ${tc.kws[4]} Log BuiltIn + Keyword and library names should be ${tc[0]} Keyword Only In Test Case File + Keyword and library names should be ${tc[1]} Keyword Only In Resource 1 my_resource_1 + Keyword and library names should be ${tc[2]} Keyword Only In Resource 1 my_resource_1 + Keyword and library names should be ${tc[3]} Log BuiltIn + Keyword and library names should be ${tc[4]} Log BuiltIn Empty keyword name is not allowed Error in library MyLibrary1 @@ -116,26 +116,21 @@ Check Test And Three Keyword Names Check Name And Three Keyword Names [Arguments] ${item} ${exp_name} ${exp_kw_name} - Should Be Equal ${item.name} ${exp_name} + Should Be Equal ${item.full_name} ${exp_name} Check Three Keyword Names ${item} ${exp_kw_name} Check Three Keyword Names [Arguments] ${item} ${exp_kw_name} - Should Be Equal ${item.body[0].name} ${exp_kw_name} - Should Be Equal ${item.body[1].name} ${exp_kw_name} - Should Be Equal ${item.body[2].name} ${exp_kw_name} - -Keyword name and assign should be - [Arguments] ${kw} ${name} @{assign} - Should Be Equal ${kw.name} ${name} - Lists Should Be Equal ${kw.assign} ${assign} + Should Be Equal ${item[0].full_name} ${exp_kw_name} + Should Be Equal ${item[1].full_name} ${exp_kw_name} + Should Be Equal ${item[2].full_name} ${exp_kw_name} Keyword and library names should be [Arguments] ${kw} ${kwname} ${libname}=${None} - Should Be Equal ${kw.kwname} ${kwname} - Should Be Equal ${kw.libname} ${libname} + Should Be Equal ${kw.name} ${kwname} + Should Be Equal ${kw.owner} ${libname} IF $libname is None - Should Be Equal ${kw.name} ${kwname} + Should Be Equal ${kw.full_name} ${kwname} ELSE - Should Be Equal ${kw.name} ${libname}.${kwname} + Should Be Equal ${kw.full_name} ${libname}.${kwname} END diff --git a/atest/robot/keywords/keyword_namespaces.robot b/atest/robot/keywords/keyword_namespaces.robot index 032890ad28f..b18f7f4fd36 100644 --- a/atest/robot/keywords/keyword_namespaces.robot +++ b/atest/robot/keywords/keyword_namespaces.robot @@ -25,14 +25,45 @@ Keyword From Test Case File Overrides Keywords From Resources And Libraries Keyword From Resource Overrides Keywords From Libraries Check Test Case ${TEST NAME} +Keyword From Test Case File Overriding Local Keyword In Resource File Is Deprecated + ${tc} = Check Test Case ${TEST NAME} + ${message} = Catenate + ... Keyword 'my_resource_1.Use test case file keyword even when local keyword with same name exists' called keyword + ... 'Keyword Everywhere' that exists both in the same resource file as the caller and in the suite file using that + ... resource. The keyword in the suite file is used now, but this will change in Robot Framework 8.0. + Check Log Message ${tc[0, 0, 0]} ${message} WARN + Check Log Message ${ERRORS}[1] ${message} WARN + +Local keyword in resource file has precedence over keywords in other resource files + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0, 0, 0]} Keyword in resource 1 + Check Log Message ${tc[1, 0, 0, 0]} Keyword in resource 2 + +Search order has precedence over local keyword in resource file + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0, 0, 0]} Keyword in resource 1 + Check Log Message ${tc[1, 0, 0, 0]} Keyword in resource 1 + Keyword From Custom Library Overrides Keywords From Standard Library ${tc} = Check Test Case ${TEST NAME} - Verify Override Message ${ERRORS[1]} ${tc.kws[0].msgs[0]} Comment BuiltIn - Verify Override Message ${ERRORS[2]} ${tc.kws[1].msgs[0]} Copy Directory OperatingSystem + Verify Override Message ${ERRORS}[2] ${tc[0]} Comment BuiltIn + Verify Override Message ${ERRORS}[3] ${tc[1]} Copy Directory OperatingSystem + +Search order can give presedence to standard library keyword over custom keyword + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[1]} BuiltIn.Comment args=Used from BuiltIn + Verify Override Message ${ERRORS}[4] ${tc[2]} Copy Directory OperatingSystem + +Search order can give presedence to custom keyword over standard library keyword + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[1]} MyLibrary1.Comment + Check Log Message ${tc[1, 0]} Overrides keyword from BuiltIn library + Check Keyword Data ${tc[2]} MyLibrary1.Copy Directory + Check Log Message ${tc[2, 0]} Overrides keyword from OperatingSystem library Keyword From Custom Library Overrides Keywords From Standard Library Even When Std Lib Imported With Different Name ${tc} = Check Test Case ${TEST NAME} - Verify Override Message ${ERRORS[3]} ${tc.kws[0].msgs[0]} Replace String + Verify Override Message ${ERRORS}[5] ${tc[0]} Replace String ... String MyLibrary2 Std With Name My With Name No Warning When Custom Library Keyword Is Registered As RunKeyword Variant And It Has Same Name As Std Keyword @@ -45,23 +76,24 @@ Keyword In More Than One Custom Library And Standard Library Keywords are first searched from test case file even if they contain dot ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.kws[0].kws[0].msgs[0]} Keyword in test case file overriding keyword in my_resource_1 - Check log message ${tc.kws[0].kws[1].kws[0].msgs[0]} Keyword in resource 1 - Check log message ${tc.kws[1].kws[0].msgs[0]} Keyword in test case file overriding keyword in BuiltIn - Check log message ${tc.kws[1].kws[1].msgs[0]} Using keyword in test case file here! + Check log message ${tc[0, 0, 0]} Keyword in test case file overriding keyword in my_resource_1 + Check log message ${tc[0, 1, 0, 0]} Keyword in resource 1 + Check log message ${tc[1, 0, 0]} Keyword in test case file overriding keyword in BuiltIn + Check log message ${tc[1, 1, 0]} Using keyword in test case file here! *** Keywords *** Verify override message - [Arguments] ${error msg} ${kw msg} ${kw} ${standard} ${custom}=MyLibrary1 + [Arguments] ${error msg} ${kw} ${name} ${standard} ${custom}=MyLibrary1 ... ${std with name}= ${ctm with name}= ${std imported as} = Set Variable If "${std with name}" ${SPACE}imported as '${std with name}' ${EMPTY} ${ctm imported as} = Set Variable If "${ctm with name}" ${SPACE}imported as '${ctm with name}' ${EMPTY} ${std long} = Set Variable If "${std with name}" ${std with name} ${standard} ${ctm long} = Set Variable If "${ctm with name}" ${ctm with name} ${custom} ${expected} = Catenate - ... Keyword '${kw}' found both from a custom library '${custom}'${ctm imported as} + ... Keyword '${name}' found both from a custom library '${custom}'${ctm imported as} ... and a standard library '${standard}'${std imported as}. The custom keyword is used. - ... To select explicitly, and to get rid of this warning, use either '${ctm long}.${kw}' - ... or '${std long}.${kw}'. + ... To select explicitly, and to get rid of this warning, use either '${ctm long}.${name}' + ... or '${std long}.${name}'. Check Log Message ${error msg} ${expected} WARN - Check Log Message ${kw msg} ${expected} WARN + Check Log Message ${kw[0]} ${expected} WARN + Check Log Message ${kw[1]} Overrides keyword from ${standard} library diff --git a/atest/robot/keywords/keyword_recommendations.robot b/atest/robot/keywords/keyword_recommendations.robot index e5325fb851c..5de5e8ced00 100644 --- a/atest/robot/keywords/keyword_recommendations.robot +++ b/atest/robot/keywords/keyword_recommendations.robot @@ -78,9 +78,6 @@ Misspelled Keyword Spacing Misspelled Keyword No Whitespace Check Test Case ${TESTNAME} -Keyword With Period - Check Test Case ${TESTNAME} - Keyword With Periods Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/keyword_tags.robot b/atest/robot/keywords/keyword_tags.robot index aae6472c416..93d54b48f7a 100644 --- a/atest/robot/keywords/keyword_tags.robot +++ b/atest/robot/keywords/keyword_tags.robot @@ -1,5 +1,5 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} keywords/keyword_tags.robot +Suite Setup Run Tests ${EMPTY} keywords/keyword_tags Resource atest_resource.robot Test Template Keyword tags should be @@ -41,8 +41,25 @@ User keyword tags with duplicates Dynamic library keyword with tags bar foo +Keyword tags setting in resource file + in resource + in resource own index=1 + in doc in resource index=2 + +Keyword tags setting in test case file + first second + first own second index=1 + doc first in second index=2 + +Keyword tags setting in init file + in init kw=${SUITE.setup} + in init own kw=${SUITE.teardown} + *** Keywords *** Keyword tags should be - [Arguments] @{tags} - ${tc}= Check Test Case ${TESTNAME} - Lists should be equal ${tc.kws[0].tags} ${tags} + [Arguments] @{tags} ${index}=0 ${kw}= + IF not $kw + ${tc}= Check Test Case ${TESTNAME} + ${kw}= Set Variable ${tc.body}[${index}] + END + Lists should be equal ${kw.tags} ${tags} diff --git a/atest/robot/keywords/keywords_implemented_in_c.robot b/atest/robot/keywords/keywords_implemented_in_c.robot index 0f44b4e807e..99bd99a9164 100644 --- a/atest/robot/keywords/keywords_implemented_in_c.robot +++ b/atest/robot/keywords/keywords_implemented_in_c.robot @@ -5,7 +5,7 @@ Resource atest_resource.robot *** Test Cases *** Use with correct arguments ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[-1].msgs[0]} This is a bit weird ... + Check Log Message ${tc[-1, 0]} This is a bit weird ... Use with incorrect arguments ${error} = Set Variable If ${INTERPRETER.is_pypy} or ${INTERPRETER.version_info} >= (3, 7) diff --git a/atest/robot/keywords/named_only_args/dynamic.robot b/atest/robot/keywords/named_only_args/dynamic.robot index e358763d1b5..74e5de7db46 100644 --- a/atest/robot/keywords/named_only_args/dynamic.robot +++ b/atest/robot/keywords/named_only_args/dynamic.robot @@ -41,4 +41,4 @@ Using kw-only arguments is not possible if 'run_keyword' accepts no kwargs Check Test Case ${TESTNAME} Error In Library DynamicKwOnlyArgsWithoutKwargs ... Adding keyword 'No kwargs' failed: - ... Too few 'run_keyword' method parameters for keyword-only arguments support. + ... Too few 'run_keyword' method parameters to support named-only arguments. diff --git a/atest/robot/keywords/optional_given_when_then.robot b/atest/robot/keywords/optional_given_when_then.robot index 50a5ac48259..5af7f0f4e6e 100644 --- a/atest/robot/keywords/optional_given_when_then.robot +++ b/atest/robot/keywords/optional_given_when_then.robot @@ -1,48 +1,85 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} keywords/optional_given_when_then.robot +Suite Setup Run Tests --lang fi keywords/optional_given_when_then.robot Resource atest_resource.robot *** Test Cases *** In user keyword name with normal arguments - ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].name} Given we don't drink too many beers - Should Be Equal ${tc.kws[1].name} When we are in - Should Be Equal ${tc.kws[2].name} But we don't drink too many beers - Should Be Equal ${tc.kws[3].name} And time - Should Be Equal ${tc.kws[4].name} Then we get this feature ready today - Should Be Equal ${tc.kws[5].name} and we don't drink too many beers + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} Given we don't drink too many beers + Should Be Equal ${tc[1].full_name} When we are in + Should Be Equal ${tc[2].full_name} But we don't drink too many beers + Should Be Equal ${tc[3].full_name} And time + Should Be Equal ${tc[4].full_name} Then we get this feature ready today + Should Be Equal ${tc[5].full_name} and we don't drink too many beers In user keyword name with embedded arguments - ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].name} Given we are in Berlin city - Should Be Equal ${tc.kws[1].name} When it does not rain - Should Be Equal ${tc.kws[2].name} And we get this feature implemented - Should Be Equal ${tc.kws[3].name} Then we go to walking tour - Should Be Equal ${tc.kws[4].name} but it does not rain + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} Given we are in Berlin city + Should Be Equal ${tc[1].full_name} When it does not rain + Should Be Equal ${tc[2].full_name} And we get this feature implemented + Should Be Equal ${tc[3].full_name} Then we go to walking tour + Should Be Equal ${tc[4].full_name} but it does not rain In library keyword name - ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].name} BuiltIn.Given Should Be Equal - Should Be Equal ${tc.kws[1].name} BuiltIn.And Should Not Match - Should Be Equal ${tc.kws[2].name} BuiltIn.But Should Match - Should Be Equal ${tc.kws[3].name} BuiltIn.When set test variable - Should Be Equal ${tc.kws[4].name} BuiltIn.THEN should be equal + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} BuiltIn.Given Should Be Equal + Should Be Equal ${tc[1].full_name} BuiltIn.And Should Not Match + Should Be Equal ${tc[2].full_name} BuiltIn.But Should Match + Should Be Equal ${tc[3].full_name} BuiltIn.When set test variable + Should Be Equal ${tc[4].full_name} BuiltIn.THEN should be equal In user keyword in resource file - ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].name} optional_given_when_then.Given Keyword Is In Resource File - Should Be Equal ${tc.kws[1].name} optional_given_when_then.and another resource file + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} optional_given_when_then.Given Keyword Is In Resource File + Should Be Equal ${tc[1].full_name} optional_given_when_then.and another resource file Correct Name Shown in Keyword Not Found Error - Check Test Case ${TEST NAME} + Check Test Case ${TEST NAME} Keyword can be used with and without prefix - ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].name} GiveN we don't drink too many beers - Should Be Equal ${tc.kws[1].name} and we don't drink too many beers - Should Be Equal ${tc.kws[2].name} We don't drink too many beers - Should Be Equal ${tc.kws[3].name} When time - Should Be Equal ${tc.kws[4].name} Time - Should Be Equal ${tc.kws[5].name} Then we are in Berlin city - Should Be Equal ${tc.kws[6].name} we are in Berlin city + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} GiveN we don't drink too many beers + Should Be Equal ${tc[1].full_name} and we don't drink too many beers + Should Be Equal ${tc[2].full_name} We don't drink too many beers + Should Be Equal ${tc[3].full_name} When time + Should Be Equal ${tc[4].full_name} Time + Should Be Equal ${tc[5].full_name} Then we are in Berlin city + Should Be Equal ${tc[6].full_name} we are in Berlin city +Only single prefixes are a processed + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} Given we are in Berlin city + Should Be Equal ${tc[1].full_name} but then we are in Berlin city + +First word of a keyword can be a prefix + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} Given the prefix is part of the keyword + +First word in a keyword can be an argument + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} Given we don't drink too many beers + Should Be Equal ${tc[1].full_name} Then Pekka drinks lonkero instead + Should Be Equal ${tc[2].full_name} and Miikka drinks water instead + Should Be Equal ${tc[3].full_name} Étant donné Miikka drinks water instead + +Localized prefixes + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} Oletetaan we don't drink too many beers + Should Be Equal ${tc[1].full_name} Kun we are in + Should Be Equal ${tc[2].full_name} mutta we don't drink too many beers + Should Be Equal ${tc[3].full_name} Ja time + Should Be Equal ${tc[4].full_name} Niin we get this feature ready today + Should Be Equal ${tc[5].full_name} ja we don't drink too many beers + +Prefix consisting of multiple words + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].full_name} Étant donné multipart prefixes didn't work with RF 6.0 + Should Be Equal ${tc[1].full_name} Zakładając, że multipart prefixes didn't work with RF 6.0 + Should Be Equal ${tc[2].full_name} Diyelim ki multipart prefixes didn't work with RF 6.0 + Should Be Equal ${tc[3].full_name} Eğer ki multipart prefixes didn't work with RF 6.0 + Should Be Equal ${tc[4].full_name} O zaman multipart prefixes didn't work with RF 6.0 + Should Be Equal ${tc[5].full_name} В случай че multipart prefixes didn't work with RF 6.0 + Should Be Equal ${tc[6].full_name} Fie ca multipart prefixes didn't work with RF 6.0 + +Prefix must be followed by space + Check Test Case ${TEST NAME} diff --git a/atest/robot/keywords/positional_only_args.robot b/atest/robot/keywords/positional_only_args.robot index b6969a820ed..2644754cd9b 100644 --- a/atest/robot/keywords/positional_only_args.robot +++ b/atest/robot/keywords/positional_only_args.robot @@ -1,16 +1,18 @@ *** Settings *** Suite Setup Run Tests ${EMPTY} keywords/positional_only_args.robot -Force Tags require-py3.8 Resource atest_resource.robot *** Test Cases *** Normal usage Check Test Case ${TESTNAME} -Named syntax is not used +Default values Check Test Case ${TESTNAME} -Default values +Positional only value can contain '=' without it being considered named argument + Check Test Case ${TESTNAME} + +Name of positional only argument can be used with kwargs Check Test Case ${TESTNAME} Type conversion @@ -19,16 +21,9 @@ Type conversion Too few arguments Check Test Case ${TESTNAME} 1 Check Test Case ${TESTNAME} 2 + Check Test Case ${TESTNAME} 3 Too many arguments Check Test Case ${TESTNAME} 1 Check Test Case ${TESTNAME} 2 - -Named argument syntax doesn't work after valid named arguments - Check Test Case ${TESTNAME} - -Name can be used with kwargs - Check Test Case ${TESTNAME} - -Mandatory positional-only missing with kwargs - Check Test Case ${TESTNAME} + Check Test Case ${TESTNAME} 3 diff --git a/atest/robot/keywords/private.robot b/atest/robot/keywords/private.robot new file mode 100644 index 00000000000..f8a13aef81c --- /dev/null +++ b/atest/robot/keywords/private.robot @@ -0,0 +1,56 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/private.robot +Resource atest_resource.robot + +*** Test Cases *** +Valid Usage With Local Keyword + ${tc}= Check Test Case ${TESTNAME} + Length Should Be ${tc[0].body} 1 + +Invalid Usage With Local Keyword + ${tc}= Check Test Case ${TESTNAME} + Private Call Warning Should Be Private Keyword ${tc[0, 0]} ${ERRORS[0]} + Length Should Be ${tc[0].body} 2 + +Valid Usage With Resource Keyword + ${tc}= Check Test Case ${TESTNAME} + Length Should Be ${tc[0].body} 1 + +Invalid Usage With Resource Keyword + ${tc}= Check Test Case ${TESTNAME} + Private Call Warning Should Be private.Private Keyword In Resource ${tc[0, 0]} ${ERRORS[1]} + Length Should Be ${tc[0].body} 2 + +Invalid Usage in Resource File + ${tc}= Check Test Case ${TESTNAME} + Private Call Warning Should Be private2.Private Keyword In Resource 2 ${tc[0, 0, 0]} ${ERRORS[2]} + Length Should Be ${tc[0, 0].body} 2 + +Local Private Keyword In Resource File Has Precedence Over Keywords In Another Resource + ${tc}= Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0, 0]} private.resource + Check Log Message ${tc[0, 1, 0, 0]} private.resource + +Search Order Has Precedence Over Local Private Keyword In Resource File + ${tc}= Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0, 0]} private2.resource + +Imported Public Keyword Has Precedence Over Imported Private Keywords + ${tc}= Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0, 0]} private2.resource + Check Log Message ${tc[1, 0, 0, 0]} private2.resource + +If All Keywords Are Private Raise Multiple Keywords Found + Check Test Case ${TESTNAME} + +If More Than Two Keywords Are Public Raise Multiple Keywords Found + Check Test Case ${TESTNAME} + +*** Keywords *** +Private Call Warning Should Be + [Arguments] ${name} @{messages} + FOR ${message} IN @{messages} + Check Log Message ${message} + ... Keyword '${name}' is private and should only be called by keywords in the same file. + ... WARN + END diff --git a/atest/robot/keywords/trace_log_keyword_arguments.robot b/atest/robot/keywords/trace_log_keyword_arguments.robot index 1aaeb3adb48..23523614e19 100644 --- a/atest/robot/keywords/trace_log_keyword_arguments.robot +++ b/atest/robot/keywords/trace_log_keyword_arguments.robot @@ -37,6 +37,11 @@ Variable Number of Arguments ... \${mand}='mandatory' | \@{vargs}=[] ... 'mandatory' +Named only + Check Argument Value Trace + ... \${no1}='a' | \${no2}='b' + ... no1='a' | no2='b' + Kwargs Check Argument Value Trace ... \&{kwargs}={} @@ -46,8 +51,8 @@ Kwargs All args Check Argument Value Trace - ... \${positional}='1' | \@{varargs}=['2', '3'] | \&{kwargs}={'d': '4'} - ... '1' | '2' | '3' | d='4' + ... \${positional}='1' | \@{varargs}=['2', '3'] | \${named_only}='4' | \&{kwargs}={'free': '5'} + ... '1' | '2' | '3' | named_only='4' | free='5' Non String Object as Argument Check Argument Value Trace @@ -68,13 +73,19 @@ Object With Unicode Repr as Argument Arguments With Run Keyword ${tc}= Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[1].msgs[0]} Arguments: [ 'Catenate' | '\@{VALUES}' ] TRACE - Check Log Message ${tc.kws[1].kws[0].msgs[0]} Arguments: [ 'a' | 'b' | 'c' | 'd' ] TRACE + Check Log Message ${tc[1, 0]} Arguments: [ '\${keyword name}' | '\@{VALUES}' ] TRACE + Check Log Message ${tc[1, 1, 0]} Arguments: [ 'a' | 'b' | 'c' | 'd' ] TRACE Embedded Arguments ${tc}= Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Arguments: [ \${first}='foo' | \${second}=42 | \${what}='UK' ] TRACE - Check Log Message ${tc.kws[1].msgs[0]} Arguments: [ 'bar' | 'Embedded Arguments' ] TRACE + Check Log Message ${tc[0, 0]} Arguments: [ \${first}='foo' | \${second}=42 | \${what}='UK' ] TRACE + Check Log Message ${tc[1, 0]} Arguments: [ 'bar' | 'Embedded Arguments' ] TRACE + Check Log Message ${tc[2, 0]} Arguments: [ \${embedded}='embedded' | \${normal}='argument' ] TRACE + Check Log Message ${tc[3, 0]} Arguments: [ \${embedded}='embedded' | \${normal}='argument' ] TRACE + FOR ${kw} IN @{tc.body} + Check Log Message ${kw[-1]} Return: None TRACE + Length Should Be ${kw.messages} 2 + END *** Keywords *** Check Argument Value Trace @@ -82,7 +93,7 @@ Check Argument Value Trace ${tc} = Check Test Case ${TEST NAME} ${length} = Get Length ${expected} FOR ${index} IN RANGE 0 ${length} - Check Log Message ${tc.kws[${index}].msgs[0]} Arguments: [ ${expected}[${index}] ] TRACE + Check Log Message ${tc[${index}, 0]} Arguments: [ ${expected}[${index}] ] TRACE END Check UKW Default, LKW Default, UKW Varargs, and LKW Varargs diff --git a/atest/robot/keywords/trace_log_return_value.robot b/atest/robot/keywords/trace_log_return_value.robot index 3bced7ccaa4..acf1d128701 100644 --- a/atest/robot/keywords/trace_log_return_value.robot +++ b/atest/robot/keywords/trace_log_return_value.robot @@ -5,35 +5,35 @@ Resource atest_resource.robot *** Test Cases *** Return from user keyword ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[1]} Return: 'value' TRACE - Check Log Message ${test.kws[0].kws[0].msgs[1]} Return: 'value' TRACE + Check Log Message ${test[0, 3]} Return: 'value' TRACE + Check Log Message ${test[0, 1, 1]} Return: 'value' TRACE Return from library keyword ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[1]} Return: 'value' TRACE + Check Log Message ${test[0, 1]} Return: 'value' TRACE Return from Run Keyword ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[1]} Return: 'value' TRACE - Check Log Message ${test.kws[0].kws[0].msgs[1]} Return: 'value' TRACE + Check Log Message ${test[0, 2]} Return: 'value' TRACE + Check Log Message ${test[0, 1, 1]} Return: 'value' TRACE Return non-string value ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[2]} Return: 1 TRACE + Check Log Message ${test[0, 2]} Return: 1 TRACE Return None ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[1]} Return: None TRACE + Check Log Message ${test[0, 1]} Return: None TRACE Return non-ASCII string ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[1]} Return: "Hyvää 'Päivää'\\n" TRACE + Check Log Message ${test[0, 1]} Return: "Hyvää 'Päivää'\\n" TRACE Return object with non-ASCII repr ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[1]} Return: Hyvä TRACE + Check Log Message ${test[0, 1]} Return: Hyvä TRACE Return object with invalid repr ${test} = Check Test Case ${TESTNAME} - Check Log Message ${test.kws[0].msgs[1]} + Check Log Message ${test[0, 1]} ... Return: TRACE diff --git a/atest/robot/keywords/type_conversion/annotations.robot b/atest/robot/keywords/type_conversion/annotations.robot index 6b1fedbb593..ad426e03ecd 100644 --- a/atest/robot/keywords/type_conversion/annotations.robot +++ b/atest/robot/keywords/type_conversion/annotations.robot @@ -63,18 +63,15 @@ Bytes Invalid bytes Check Test Case ${TESTNAME} -Bytestring - Check Test Case ${TESTNAME} - -Invalid bytesstring - Check Test Case ${TESTNAME} - Bytearray Check Test Case ${TESTNAME} Invalid bytearray Check Test Case ${TESTNAME} +Bytestring replacement + Check Test Case ${TESTNAME} + Datetime Check Test Case ${TESTNAME} @@ -93,6 +90,12 @@ Timedelta Invalid timedelta Check Test Case ${TESTNAME} +Path + Check Test Case ${TESTNAME} + +Invalid Path + Check Test Case ${TESTNAME} + Enum Check Test Case ${TESTNAME} @@ -174,6 +177,9 @@ Invalid frozenset Unknown types are not converted Check Test Case ${TESTNAME} +Unknown types are not converted in union + Check Test Case ${TESTNAME} + Non-type values don't cause errors Check Test Case ${TESTNAME} @@ -204,12 +210,18 @@ Invalid kwonly Return value annotation causes no error Check Test Case ${TESTNAME} -None as default +None as default with known type + Check Test Case ${TESTNAME} + +None as default with unknown type Check Test Case ${TESTNAME} Forward references Check Test Case ${TESTNAME} +Unknown forward references + Check Test Case ${TESTNAME} + @keyword decorator overrides annotations Check Test Case ${TESTNAME} @@ -233,3 +245,8 @@ Default value is used if explicit type conversion fails Explicit conversion failure is used if both conversions fail Check Test Case ${TESTNAME} + +Deferred evaluation of annotations + [Documentation] https://peps.python.org/pep-0649 + [Tags] require-py3.14 + Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/type_conversion/annotations_with_typing.robot b/atest/robot/keywords/type_conversion/annotations_with_typing.robot index b1e03308e49..90da0f1516e 100644 --- a/atest/robot/keywords/type_conversion/annotations_with_typing.robot +++ b/atest/robot/keywords/type_conversion/annotations_with_typing.robot @@ -1,33 +1,57 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} keywords/type_conversion/annotations_with_typing.robot -Resource atest_resource.robot +Suite Setup Run Tests ${EMPTY} keywords/type_conversion/annotations_with_typing.robot +Resource atest_resource.robot *** Test Cases *** List Check Test Case ${TESTNAME} -List with params +List with types + Check Test Case ${TESTNAME} + +List with incompatible types Check Test Case ${TESTNAME} Invalid list Check Test Case ${TESTNAME} +Tuple + Check Test Case ${TESTNAME} + +Tuple with types + Check Test Case ${TESTNAME} + +Tuple with homogenous types + Check Test Case ${TESTNAME} + +Tuple with incompatible types + Check Test Case ${TESTNAME} + +Tuple with wrong number of values + Check Test Case ${TESTNAME} + +Invalid tuple + Check Test Case ${TESTNAME} + Sequence Check Test Case ${TESTNAME} -Sequence with params +Sequence with types + Check Test Case ${TESTNAME} + +Sequence with incompatible types Check Test Case ${TESTNAME} -Invalid Sequence +Invalid sequence Check Test Case ${TESTNAME} Dict Check Test Case ${TESTNAME} -Dict with params +Dict with types Check Test Case ${TESTNAME} -TypedDict +Dict with incompatible types Check Test Case ${TESTNAME} Invalid dictionary @@ -36,24 +60,57 @@ Invalid dictionary Mapping Check Test Case ${TESTNAME} -Mapping with params +Mapping with types + Check Test Case ${TESTNAME} + +Mapping with incompatible types Check Test Case ${TESTNAME} Invalid mapping Check Test Case ${TESTNAME} +TypedDict + Check Test Case ${TESTNAME} + +Stringified TypedDict types + Check Test Case ${TESTNAME} + +Optional TypedDict keys can be omitted (total=False) + Check Test Case ${TESTNAME} + +Not required TypedDict keys can be omitted (NotRequired/Required) + Check Test Case ${TESTNAME} + +Required TypedDict keys cannot be omitted + Check Test Case ${TESTNAME} + +Incompatible TypedDict + Check Test Case ${TESTNAME} + +Invalid TypedDict + Check Test Case ${TESTNAME} + Set Check Test Case ${TESTNAME} -Set with params +Set with types + Check Test Case ${TESTNAME} + +Set with incompatible types Check Test Case ${TESTNAME} Invalid Set Check Test Case ${TESTNAME} +Any + Check Test Case ${TESTNAME} + None as default Check Test Case ${TESTNAME} +None as default with Any + Check Test Case ${TESTNAME} + Forward references Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/type_conversion/custom_converters.robot b/atest/robot/keywords/type_conversion/custom_converters.robot index 3c55d0f498f..28a076e43c1 100644 --- a/atest/robot/keywords/type_conversion/custom_converters.robot +++ b/atest/robot/keywords/type_conversion/custom_converters.robot @@ -21,16 +21,40 @@ Custom in Union Accept subscripted generics Check Test Case ${TESTNAME} +With generics + Check Test Case ${TESTNAME} + +With TypedDict + Check Test Case ${TESTNAME} + Failing conversion Check Test Case ${TESTNAME} +`None` as strict converter + Check Test Case ${TESTNAME} + +Only vararg + Check Test Case ${TESTNAME} + +With library as argument to converter + Check Test Case ${TESTNAME} + +Test scope library instance is reset between test + Check Test Case ${TESTNAME} 1 + Check Test Case ${TESTNAME} 2 + +Global scope library instance is not reset between test + Check Test Case ${TESTNAME} 1 + Check Test Case ${TESTNAME} 2 + Invalid converters Check Test Case ${TESTNAME} Validate Errors ... Custom converters must be callable, converter for Invalid is integer. - ... Custom converters must accept exactly one positional argument, converter 'TooFewArgs' accepts 0. - ... Custom converters must accept exactly one positional argument, converter 'TooManyArgs' accepts 2. - ... Custom converter 'KwOnlyNotOk' accepts keyword-only arguments which is not supported. + ... Custom converters must accept one positional argument, 'TooFewArgs' accepts none. + ... Custom converters cannot have more than two mandatory arguments, 'TooManyArgs' has 'one', 'two' and 'three'. + ... Custom converters must accept one positional argument, 'NoPositionalArg' accepts none. + ... Custom converters cannot have mandatory keyword-only arguments, 'KwOnlyNotOk' has 'another' and 'kwo'. ... Custom converters must be specified using types, got string 'Bad'. Non-type annotation @@ -60,6 +84,6 @@ Invalid converter dictionary *** Keywords *** Validate Errors [Arguments] @{messages} - FOR ${err} ${msg} IN ZIP ${ERRORS} ${messages} + FOR ${err} ${msg} IN ZIP ${ERRORS} ${messages} mode=SHORTEST Check Log Message ${err} Error in library 'CustomConverters': ${msg} ERROR END diff --git a/atest/robot/keywords/type_conversion/default_values.robot b/atest/robot/keywords/type_conversion/default_values.robot index 6a199124326..bad1658932f 100644 --- a/atest/robot/keywords/type_conversion/default_values.robot +++ b/atest/robot/keywords/type_conversion/default_values.robot @@ -72,6 +72,12 @@ Timedelta Invalid timedelta Check Test Case ${TESTNAME} +Path + Check Test Case ${TESTNAME} + +Invalid Path + Check Test Case ${TESTNAME} + Enum Check Test Case ${TESTNAME} @@ -127,9 +133,6 @@ Unknown types are not converted Positional as named Check Test Case ${TESTNAME} -Invalid positional as named - Check Test Case ${TESTNAME} - Kwonly Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/type_conversion/internal_conversion_using_typeinfo.robot b/atest/robot/keywords/type_conversion/internal_conversion_using_typeinfo.robot new file mode 100644 index 00000000000..023acb09d63 --- /dev/null +++ b/atest/robot/keywords/type_conversion/internal_conversion_using_typeinfo.robot @@ -0,0 +1,16 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/type_conversion/internal_conversion_using_typeinfo.robot +Resource atest_resource.robot + +*** Test Cases *** +Internal conversion + Check Test Case ${TESTNAME} + +Custom converters + Check Test Case ${TESTNAME} + +Language configuration + Check Test Case ${TESTNAME} + +Default language configuration + Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/type_conversion/keyword_decorator.robot b/atest/robot/keywords/type_conversion/keyword_decorator.robot index 00ec4af6969..3766b587390 100644 --- a/atest/robot/keywords/type_conversion/keyword_decorator.robot +++ b/atest/robot/keywords/type_conversion/keyword_decorator.robot @@ -63,18 +63,15 @@ Bytes Invalid bytes Check Test Case ${TESTNAME} -Bytestring - Check Test Case ${TESTNAME} - -Invalid bytesstring - Check Test Case ${TESTNAME} - Bytearray Check Test Case ${TESTNAME} Invalid bytearray Check Test Case ${TESTNAME} +Bytestring replacement + Check Test Case ${TESTNAME} + Datetime Check Test Case ${TESTNAME} @@ -93,6 +90,12 @@ Timedelta Invalid timedelta Check Test Case ${TESTNAME} +Path + Check Test Case ${TESTNAME} + +Invalid Path + Check Test Case ${TESTNAME} + Enum Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/type_conversion/literal.robot b/atest/robot/keywords/type_conversion/literal.robot new file mode 100644 index 00000000000..9d4b968ba62 --- /dev/null +++ b/atest/robot/keywords/type_conversion/literal.robot @@ -0,0 +1,61 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/type_conversion/literal.robot +Resource atest_resource.robot + +*** Test Cases *** +Integers + Check Test Case ${TESTNAME} + +Invalid integers + Check Test Case ${TESTNAME} + +Strings + Check Test Case ${TESTNAME} + +Strings are case, space, etc. insensitive + Check Test Case ${TESTNAME} + +Invalid strings + Check Test Case ${TESTNAME} + +Bytes + Check Test Case ${TESTNAME} + +Invalid bytes + Check Test Case ${TESTNAME} + +Booleans + Check Test Case ${TESTNAME} + +Booleans are localized + Check Test Case ${TESTNAME} + +Invalid booleans + Check Test Case ${TESTNAME} + +None + Check Test Case ${TESTNAME} + +Invalid None + Check Test Case ${TESTNAME} + +Enums + Check Test Case ${TESTNAME} + +Invalid enums + Check Test Case ${TESTNAME} + +Int enums + Check Test Case ${TESTNAME} + +Invalid int enums + Check Test Case ${TESTNAME} + +Multiple matches with exact match + Check Test Case ${TESTNAME} + +Multiple matches with not exact match + Check Test Case ${TESTNAME} + +In parameters + Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/type_conversion/standard_generics.robot b/atest/robot/keywords/type_conversion/standard_generics.robot new file mode 100644 index 00000000000..85c304534ac --- /dev/null +++ b/atest/robot/keywords/type_conversion/standard_generics.robot @@ -0,0 +1,92 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/type_conversion/standard_generics.robot +Test Tags require-py3.9 +Resource atest_resource.robot + +*** Test Cases *** +List + Check Test Case ${TESTNAME} + +List with unknown + Check Test Case ${TESTNAME} + +List in union + Check Test Case ${TESTNAME} + +Incompatible list + Check Test Case ${TESTNAME} + +Tuple + Check Test Case ${TESTNAME} + +Tuple with unknown + Check Test Case ${TESTNAME} + +Tuple in union + Check Test Case ${TESTNAME} + +Homogenous tuple + Check Test Case ${TESTNAME} + +Homogenous tuple with unknown + Check Test Case ${TESTNAME} + +Homogenous tuple in union + Check Test Case ${TESTNAME} + +Incompatible tuple + Check Test Case ${TESTNAME} + +Dict + Check Test Case ${TESTNAME} + +Dict with unknown + Check Test Case ${TESTNAME} + +Dict in union + Check Test Case ${TESTNAME} + +Incompatible dict + Check Test Case ${TESTNAME} + +Set + Check Test Case ${TESTNAME} + +Set with unknown + Check Test Case ${TESTNAME} + +Set in union + Check Test Case ${TESTNAME} + +Incompatible set + Check Test Case ${TESTNAME} + +Nested generics + Check Test Case ${TESTNAME} + +Incompatible nested generics + Check Test Case ${TESTNAME} + +Invalid list + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS[1]} + ... Error in library 'StandardGenerics': Adding keyword 'invalid_list' failed: 'list[]' requires exactly 1 parameter, 'list[int, float]' has 2. + ... ERROR + +Invalid tuple + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS[3]} + ... Error in library 'StandardGenerics': Adding keyword 'invalid_tuple' failed: Homogenous tuple requires exactly 1 parameter, 'tuple[int, float, ...]' has 2. + ... ERROR + +Invalid dict + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS[0]} + ... Error in library 'StandardGenerics': Adding keyword 'invalid_dict' failed: 'dict[]' requires exactly 2 parameters, 'dict[int]' has 1. + ... ERROR + +Invalid set + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS[2]} + ... Error in library 'StandardGenerics': Adding keyword 'invalid_set' failed: 'set[]' requires exactly 1 parameter, 'set[int, float]' has 2. + ... ERROR diff --git a/atest/robot/keywords/type_conversion/stringly_types.robot b/atest/robot/keywords/type_conversion/stringly_types.robot new file mode 100644 index 00000000000..f9224d36b28 --- /dev/null +++ b/atest/robot/keywords/type_conversion/stringly_types.robot @@ -0,0 +1,46 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} keywords/type_conversion/stringly_types.robot +Resource atest_resource.robot + +*** Test Cases *** +Parameterized list + Check Test Case ${TESTNAME} + +Parameterized dict + Check Test Case ${TESTNAME} + +Parameterized set + Check Test Case ${TESTNAME} + +Parameterized tuple + Check Test Case ${TESTNAME} + +Homogenous tuple + Check Test Case ${TESTNAME} + +Literal + Check Test Case ${TESTNAME} + +Union + Check Test Case ${TESTNAME} + +Nested + Check Test Case ${TESTNAME} + +Aliases + Check Test Case ${TESTNAME} + +TypedDict items + Check Test Case ${TESTNAME} + +Invalid + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS[1]} + ... Error in library 'StringlyTypes': Adding keyword 'invalid' failed: Parsing type 'bad[info' failed: Error at end: Closing ']' missing. + ... ERROR + +Bad parameters + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS[0]} + ... Error in library 'StringlyTypes': Adding keyword 'bad_params' failed: 'list[]' requires exactly 1 parameter, 'list[int, str]' has 2. + ... ERROR diff --git a/atest/robot/keywords/type_conversion/translated_boolean_values.robot b/atest/robot/keywords/type_conversion/translated_boolean_values.robot new file mode 100644 index 00000000000..746fff37efd --- /dev/null +++ b/atest/robot/keywords/type_conversion/translated_boolean_values.robot @@ -0,0 +1,10 @@ +*** Settings *** +Suite Setup Run Tests --lang fi keywords/type_conversion/translated_boolean_values.robot +Resource atest_resource.robot + +*** Test Cases *** +Boolean + Check Test Case ${TESTNAME} + +Via Run Keyword + Check Test Case ${TESTNAME} diff --git a/atest/robot/keywords/type_conversion/unions.robot b/atest/robot/keywords/type_conversion/unions.robot index 62b32782e82..d8d9630fe8f 100644 --- a/atest/robot/keywords/type_conversion/unions.robot +++ b/atest/robot/keywords/type_conversion/unions.robot @@ -24,13 +24,19 @@ Union with subscripted generics and str Union with TypedDict Check Test Case ${TESTNAME} +Union with str and TypedDict + Check Test Case ${TESTNAME} + Union with item not liking isinstance Check Test Case ${TESTNAME} Argument not matching union Check Test Case ${TESTNAME} -Union with custom type +Union with unrecognized type + Check Test Case ${TESTNAME} + +Union with only unrecognized types Check Test Case ${TESTNAME} Multiple types using tuple @@ -57,8 +63,22 @@ Avoid unnecessary conversion Avoid unnecessary conversion with ABC Check Test Case ${TESTNAME} +Default value type + Check Test Case ${TESTNAME} + +Default value type with unrecognized type + Check Test Case ${TESTNAME} + Union with invalid types Check Test Case ${TESTNAME} Tuple with invalid types Check Test Case ${TESTNAME} + +Union without types + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS}[1] Error in library 'unions': Adding keyword 'union_without_types' failed: Union cannot be empty. ERROR + +Empty tuple + Check Test Case ${TESTNAME} + Check Log Message ${ERRORS}[0] Error in library 'unions': Adding keyword 'empty_tuple' failed: Union cannot be empty. ERROR diff --git a/atest/robot/keywords/type_conversion/unionsugar.robot b/atest/robot/keywords/type_conversion/unionsugar.robot index 97c098f0c97..f50493409b3 100644 --- a/atest/robot/keywords/type_conversion/unionsugar.robot +++ b/atest/robot/keywords/type_conversion/unionsugar.robot @@ -31,7 +31,10 @@ Union with item not liking isinstance Argument not matching union Check Test Case ${TESTNAME} -Union with custom type +Union with unrecognized type + Check Test Case ${TESTNAME} + +Union with only unrecognized types Check Test Case ${TESTNAME} Avoid unnecessary conversion diff --git a/atest/robot/keywords/user_keyword_arguments.robot b/atest/robot/keywords/user_keyword_arguments.robot index d154c4db875..f802c686713 100644 --- a/atest/robot/keywords/user_keyword_arguments.robot +++ b/atest/robot/keywords/user_keyword_arguments.robot @@ -85,12 +85,12 @@ Caller does not see modifications to varargs Invalid Arguments Spec [Template] Verify Invalid Argument Spec - 0 334 Invalid argument syntax Invalid argument syntax 'no deco'. - 1 338 Non-default after defaults Non-default argument after default arguments. - 2 342 Default with varargs Only normal arguments accept default values, list arguments like '\@{varargs}' do not. - 3 346 Default with kwargs Only normal arguments accept default values, dictionary arguments like '\&{kwargs}' do not. - 4 350 Kwargs not last Only last argument can be kwargs. - 5 354 Multiple errors Multiple errors: + 0 338 Invalid argument syntax Invalid argument syntax 'no deco'. + 1 342 Non-default after defaults Non-default argument after default arguments. + 2 346 Default with varargs Only normal arguments accept default values, list arguments like '\@{varargs}' do not. + 3 350 Default with kwargs Only normal arguments accept default values, dictionary arguments like '\&{kwargs}' do not. + 4 354 Kwargs not last Only last argument can be kwargs. + 5 358 Multiple errors Multiple errors: ... - Invalid argument syntax 'invalid'. ... - Non-default argument after default arguments. ... - Cannot have multiple varargs. diff --git a/atest/robot/keywords/user_keyword_kwargs.robot b/atest/robot/keywords/user_keyword_kwargs.robot index 96f3d119a80..69b8b5b7ebd 100644 --- a/atest/robot/keywords/user_keyword_kwargs.robot +++ b/atest/robot/keywords/user_keyword_kwargs.robot @@ -47,8 +47,8 @@ Caller does not see modifications to kwargs Invalid arguments spec [Template] Verify Invalid Argument Spec - 0 181 Positional after kwargs Only last argument can be kwargs. - 1 185 Varargs after kwargs Only last argument can be kwargs. + 0 182 Positional after kwargs Only last argument can be kwargs. + 1 186 Varargs after kwargs Only last argument can be kwargs. *** Keywords *** Verify Invalid Argument Spec diff --git a/atest/robot/libdoc/LibDocLib.py b/atest/robot/libdoc/LibDocLib.py index 7fbc07bcb81..66c8763f8b6 100644 --- a/atest/robot/libdoc/LibDocLib.py +++ b/atest/robot/libdoc/LibDocLib.py @@ -5,12 +5,15 @@ from pathlib import Path from subprocess import run, PIPE, STDOUT -from jsonschema import Draft202012Validator +try: + from jsonschema import Draft202012Validator as JSONValidator +except ImportError: + JSONValidator = None from xmlschema import XMLSchema from robot.api import logger -from robot.utils import SYSTEM_ENCODING -from robot.running.arguments import ArgInfo +from robot.utils import NOT_SET, SYSTEM_ENCODING +from robot.running.arguments import ArgInfo, TypeInfo ROOT = Path(__file__).absolute().parent.parent.parent.parent @@ -20,9 +23,14 @@ class LibDocLib: def __init__(self, interpreter=None): self.interpreter = interpreter - self.xml_schema = XMLSchema(ROOT/'doc/schema/libdoc.xsd') - with open(ROOT/'doc/schema/libdoc.json') as f: - self.json_schema = Draft202012Validator(json.load(f)) + self.xml_schema = XMLSchema(str(ROOT/'doc/schema/libdoc.xsd')) + self.json_schema = self._load_json_schema() + + def _load_json_schema(self): + if not JSONValidator: + return None + with open(ROOT/'doc/schema/libdoc.json', encoding='UTF-8') as f: + return JSONValidator(json.load(f)) @property def libdoc(self): @@ -60,25 +68,30 @@ def validate_xml_spec(self, path): self.xml_schema.validate(path) def validate_json_spec(self, path): - with open(path) as f: + if not self.json_schema: + raise RuntimeError('jsonschema module is not installed!') + with open(path, encoding='UTF-8') as f: self.json_schema.validate(json.load(f)) - def relative_source(self, path, start): - if not exists(path): - return path - try: - return relpath(path, start) - except ValueError: - return normpath(path) - def get_repr_from_arg_model(self, model): return str(ArgInfo(kind=model['kind'], name=model['name'], - types=tuple(model['type']), - default=model['default'] or ArgInfo.NOTSET)) + type=self._get_type_info(model['type']), + default=self._get_default(model['default']))) def get_repr_from_json_arg_model(self, model): return str(ArgInfo(kind=model['kind'], name=model['name'], - types=tuple(model['types']), - default=model['defaultValue'] or ArgInfo.NOTSET)) + type=self._get_type_info(model['type']), + default=self._get_default(model['defaultValue']))) + + def _get_type_info(self, data): + if not data: + return None + if isinstance(data, str): + return TypeInfo.from_string(data) + nested = [self._get_type_info(n) for n in data.get('nested', ())] + return TypeInfo(data['name'], None, nested=nested or None) + + def _get_default(self, data): + return data if data is not None else NOT_SET diff --git a/atest/robot/libdoc/backwards_compatibility.robot b/atest/robot/libdoc/backwards_compatibility.robot new file mode 100644 index 00000000000..587664238ce --- /dev/null +++ b/atest/robot/libdoc/backwards_compatibility.robot @@ -0,0 +1,87 @@ +*** Settings *** +Documentation Test that Libdoc can read old XML and JSON spec files. +Test Template Generate and validate +Resource libdoc_resource.robot + +*** Variables *** +${BASE} ${TESTDATADIR}/BackwardsCompatibility + +*** Test Cases *** +Latest + ${BASE}.py source=${BASE}.py + +RF 6.1 XML + ${BASE}-6.1.xml + +RF 6.1 JSON + ${BASE}-6.1.json + +RF 5.0 XML + ${BASE}-5.0.xml + +RF 5.0 JSON + ${BASE}-5.0.json + +RF 4.0 XML + ${BASE}-4.0.xml datatypes=True + +RF 4.0 JSON + ${BASE}-4.0.json datatypes=True + +*** Keywords *** +Generate and validate + [Arguments] ${path} ${source}=BackwardsCompatibility.py ${datatypes}=False + # JSON source files must be generated using RAW format as well. + Run Libdoc And Parse Output --specdocformat RAW ${path} + Validate ${source} ${datatypes} + +Validate + [Arguments] ${source} ${datatypes}=False + [Tags] robot:recursive-continue-on-failure + Validate library ${source} + Validate keyword 'Simple' + Validate keyword 'Arguments' + Validate keyword 'Types' + Validate keyword 'Special Types' + Validate keyword 'Union' + +Validate library + [Arguments] ${source} + Name Should Be BackwardsCompatibility + Version Should Be 1.0 + Doc Should Start With Library for testing backwards compatibility.\n + Type Should Be LIBRARY + Scope Should Be GLOBAL + Format Should Be ROBOT + Source Should Be ${source} + Lineno Should Be 1 + Generated Should Be Defined + Spec Version Should Be Correct + Should Have No Init + Keyword Count Should Be 5 + +Validate keyword 'Simple' + Keyword Name Should Be 1 Simple + Keyword Doc Should Be 1 Some doc. + Keyword Tags Should Be 1 example + Keyword Lineno Should Be 1 34 + Keyword Arguments Should Be 1 + +Validate keyword 'Arguments' + Keyword Name Should Be 0 Arguments + Keyword Doc Should Be 0 ${EMPTY} + Keyword Tags Should Be 0 + Keyword Lineno Should Be 0 42 + Keyword Arguments Should Be 0 a b=2 *c d=4 e **f + +Validate keyword 'Types' + Keyword Name Should Be 3 Types + Keyword Arguments Should Be 3 a: int b: bool = True + +Validate keyword 'Special Types' + Keyword Name Should Be 2 Special Types + Keyword Arguments Should Be 2 a: Color b: Size + +Validate keyword 'Union' + Keyword Name Should Be 4 Union + Keyword Arguments Should Be 4 a: int | float diff --git a/atest/robot/libdoc/cli.robot b/atest/robot/libdoc/cli.robot index b7927c81952..905e60c695d 100644 --- a/atest/robot/libdoc/cli.robot +++ b/atest/robot/libdoc/cli.robot @@ -21,6 +21,9 @@ Using --specdocformat to specify doc format in output --format XML --specdocformat RAW String ${OUTBASE}.libspec XML String path=${OUTBASE}.libspec --format XML --specdocformat HTML String ${OUTBASE}.libspec LIBSPEC String path=${OUTBASE}.libspec +Library arguments + ${TESTDATADIR}/LibraryArguments.py::required::true ${OUTHTML} HTML LibraryArguments + Library name matching spec extension --pythonpath ${DATADIR}/libdoc LIBPKG.JSON ${OUTXML} XML LIBPKG.JSON path=${OUTXML} [Teardown] Keyword Name Should Be 0 Keyword In Json @@ -29,6 +32,19 @@ Library name matching resource extension --pythonpath ${DATADIR}/libdoc LIBPKG.resource ${OUTXML} XML LIBPKG.resource path=${OUTXML} [Teardown] Keyword Name Should Be 0 Keyword In Resource +Library argument matching resource extension + ${TESTDATADIR}/LibraryArguments.py::required::true::foo.resource ${OUTHTML} HTML LibraryArguments + +Library argument matching resource extension when import fails + [Template] Run libdoc and verify output + NonExisting::foo.resource ${OUTHTML} + ... Importing library 'NonExisting' failed: ModuleNotFoundError: No module named 'NonExisting' + ... Traceback (most recent call last): + ... ${SPACE*2}None + ... PYTHONPATH: + ... * + ... ${USAGE TIP[1:]} + Override name and version --name MyName --version 42 String ${OUTHTML} HTML MyName 42 -n MyName -v 42 -f xml BuiltIn ${OUTHTML} XML MyName 42 @@ -40,6 +56,16 @@ Missing destination subdirectory is created Quiet --quiet String ${OUTHTML} HTML String quiet=True +Theme + --theme DARK String ${OUTHTML} HTML String theme=dark + --theme light String ${OUTHTML} HTML String theme=light + --theme NoNe String ${OUTHTML} HTML String theme= + +Language + --language EN String ${OUTHTML} HTML String lang=en + --language fI String ${OUTHTML} HTML String lang=fi + --language NoNe String ${OUTHTML} HTML String language= + Relative path with Python libraries [Template] NONE ${dir in libdoc exec dir}= Normalize Path ${ROBOTPATH}/../TempDirInExecDir @@ -56,7 +82,7 @@ Resource file in PYTHONPATH [Template] NONE Run Libdoc And Parse Output --pythonpath ${DATADIR}/libdoc resource.resource Name Should Be resource - Keyword Name Should Be 0 Yay, I got new extension! + Keyword Name Should Be -1 Yay, I got new extension! Non-existing resource [Template] NONE @@ -65,10 +91,17 @@ Non-existing resource *** Keywords *** Run Libdoc And Verify Created Output File - [Arguments] ${args} ${format} ${name} ${version}= ${path}=${OUTHTML} ${quiet}=False + [Arguments] ${args} ${format} ${name} ${version}= ${path}=${OUTHTML} ${theme}= ${lang}= ${quiet}=False ${stdout} = Run Libdoc ${args} Run Keyword ${format} Doc Should Have Been Created ${path} ${name} ${version} File Should Have Correct Line Separators ${path} + IF "${theme}" + File Should Contain ${path} "theme": "${theme}" + ELSE IF "${lang}" + File Should Contain ${path} "lang": "${lang}" + ELSE + File Should Not Contain ${path} "theme": + END IF not ${quiet} Path to output should be in stdout ${path} ${stdout.rstrip()} ELSE @@ -79,7 +112,7 @@ Run Libdoc And Verify Created Output File HTML Doc Should Have Been Created [Arguments] ${path} ${name} ${version} ${libdoc}= Get File ${path} - Should Start With ${libdoc} Class doc is used when converter method has no doc.

-Accepted types +Standard + DataType Standard Should Be 0 + ... Any + ...

Any value is accepted. No conversion is done.

+ DataType Standard Should Be 1 + ... boolean + ...

Strings TRUE, + DataType Standard Should Be 6 + ... Literal + ...

Only specified values are accepted. + +Standard with generics + DataType Standard Should Be 2 + ... dictionary + ...

Strings must be Python Strings must be Python Defines the geolocation.

- ...
    - ...
  • latitude Latitude between -90 and 90.
  • - ...
  • longitude Longitude between -180 and 180.
  • - ...
  • accuracy Optional Non-negative accuracy value. Defaults to 0.
  • - ...
- ...

Example usage: {'latitude': 59.95, 'longitude': 30.31667}

- ${MODEL}[typedocs][6][type] TypedDict - ${MODEL}[typedocs][6][name] GeoLocation - ${MODEL}[typedocs][6][doc]

Defines the geolocation.

+ ${MODEL}[typedocs][7][type] TypedDict + ${MODEL}[typedocs][7][name] GeoLocation + ${MODEL}[typedocs][7][doc]

Defines the geolocation.

...
    ...
  • latitude Latitude between -90 and 90.
  • ...
  • longitude Longitude between -180 and 180.
  • @@ -50,7 +40,7 @@ TypedDict TypedDict Items [Template] NONE - ${required} Set Variable ${Model}[dataTypes][typedDicts][0][items][0][required] + VAR ${required} ${Model}[typedocs][7][items][0][required] IF $required is None ${longitude}= Create Dictionary key=longitude type=float required=${None} ${latitude}= Create Dictionary key=latitude type=float required=${None} @@ -61,7 +51,7 @@ TypedDict Items ${accuracy}= Create Dictionary key=accuracy type=float required=${False} END FOR ${exp} IN ${longitude} ${latitude} ${accuracy} - FOR ${item} IN @{Model}[dataTypes][typedDicts][0][items] + FOR ${item} IN @{Model}[typedocs][7][items] IF $exp['key'] == $item['key'] Dictionaries Should Be Equal ${item} ${exp} BREAK @@ -70,72 +60,125 @@ TypedDict Items END Enum - ${MODEL}[dataTypes][enums][0][type] Enum - ${MODEL}[dataTypes][enums][0][name] AssertionOperator - ${MODEL}[dataTypes][enums][0][doc]

    This is some Doc

    - ...

    This has was defined by assigning to __doc__.

    - ${MODEL}[typedocs][0][type] Enum - ${MODEL}[typedocs][0][name] AssertionOperator - ${MODEL}[typedocs][0][doc]

    This is some Doc

    + ${MODEL}[typedocs][1][type] Enum + ${MODEL}[typedocs][1][name] AssertionOperator + ${MODEL}[typedocs][1][doc]

    This is some Doc

    ...

    This has was defined by assigning to __doc__.

    Enum Members [Template] NONE ${exp_list} Evaluate [{"name": "equal","value": "=="},{"name": "==","value": "=="},{"name": "<","value": "<"},{"name": ">","value": ">"},{"name": "<=","value": "<="},{"name": ">=","value": ">="}] - FOR ${cur} ${exp} IN ZIP ${MODEL}[dataTypes][enums][0][members] ${exp_list} - Dictionaries Should Be Equal ${cur} ${exp} - END - FOR ${cur} ${exp} IN ZIP ${MODEL}[typedocs][0][members] ${exp_list} + FOR ${cur} ${exp} IN ZIP ${MODEL}[typedocs][1][members] ${exp_list} Dictionaries Should Be Equal ${cur} ${exp} END Custom types - ${MODEL}[typedocs][2][type] Custom - ${MODEL}[typedocs][2][name] CustomType - ${MODEL}[typedocs][2][doc]

    Converter method doc is used when defined.

    ${MODEL}[typedocs][3][type] Custom - ${MODEL}[typedocs][3][name] CustomType2 - ${MODEL}[typedocs][3][doc]

    Class doc is used when converter method has no doc.

    + ${MODEL}[typedocs][3][name] CustomType + ${MODEL}[typedocs][3][doc]

    Converter method doc is used when defined.

    + ${MODEL}[typedocs][4][type] Custom + ${MODEL}[typedocs][4][name] CustomType2 + ${MODEL}[typedocs][4][doc]

    Class doc is used when converter method has no doc.

    Standard types - ${MODEL}[typedocs][1][type] Standard - ${MODEL}[typedocs][1][name] boolean - ${MODEL}[typedocs][1][doc]

    Strings TRUE, YES, start=True + ${MODEL}[typedocs][0][type] Standard + ${MODEL}[typedocs][0][name] Any + ${MODEL}[typedocs][0][doc]

    Any value is accepted. No conversion is done.

    + ${MODEL}[typedocs][2][type] Standard + ${MODEL}[typedocs][2][name] boolean + ${MODEL}[typedocs][2][doc]

    Strings TRUE, YES, start=True + ${MODEL}[typedocs][10][name] Literal + ${MODEL}[typedocs][10][doc]

    Only specified values are accepted. start=True + +Standard types with generics + ${MODEL}[typedocs][5][type] Standard + ${MODEL}[typedocs][5][name] dictionary + ${MODEL}[typedocs][5][doc]

    Strings must be Python Strings must be Python Defines the geolocation.

    - ...
      - ...
    • latitude Latitude between -90 and 90.
    • - ...
    • longitude Longitude between -180 and 180.
    • - ...
    • accuracy Optional Non-negative accuracy value. Defaults to 0.
    • - ...
    - ...

    Example usage: {'latitude': 59.95, 'longitude': 30.31667}

    - ${MODEL}[typedocs][6][type] TypedDict - ${MODEL}[typedocs][6][name] GeoLocation - ${MODEL}[typedocs][6][doc]

    Defines the geolocation.

    + ${MODEL}[typedocs][7][type] TypedDict + ${MODEL}[typedocs][7][name] GeoLocation + ${MODEL}[typedocs][7][doc]

    Defines the geolocation.

    ...
      ...
    • latitude Latitude between -90 and 90.
    • ...
    • longitude Longitude between -180 and 180.
    • @@ -51,7 +44,7 @@ TypedDict Items ${latitude}= Create Dictionary key=latitude type=float required=${True} ${accuracy}= Create Dictionary key=accuracy type=float required=${False} FOR ${exp} IN ${longitude} ${latitude} ${accuracy} - FOR ${item} IN @{Model}[dataTypes][typedDicts][0][items] + FOR ${item} IN @{Model}[typedocs][7][items] IF $exp['key'] == $item['key'] Dictionaries Should Be Equal ${item} ${exp} BREAK @@ -60,78 +53,130 @@ TypedDict Items END Enum - ${MODEL}[dataTypes][enums][0][type] Enum - ${MODEL}[dataTypes][enums][0][name] AssertionOperator - ${MODEL}[dataTypes][enums][0][doc]

      This is some Doc

      - ...

      This has was defined by assigning to __doc__.

      - ${MODEL}[typedocs][0][type] Enum - ${MODEL}[typedocs][0][name] AssertionOperator - ${MODEL}[typedocs][0][doc]

      This is some Doc

      + ${MODEL}[typedocs][1][type] Enum + ${MODEL}[typedocs][1][name] AssertionOperator + ${MODEL}[typedocs][1][doc]

      This is some Doc

      ...

      This has was defined by assigning to __doc__.

      Enum Members [Template] NONE ${exp_list} Evaluate [{"name": "equal","value": "=="},{"name": "==","value": "=="},{"name": "<","value": "<"},{"name": ">","value": ">"},{"name": "<=","value": "<="},{"name": ">=","value": ">="}] - FOR ${cur} ${exp} IN ZIP ${MODEL}[dataTypes][enums][0][members] ${exp_list} - Dictionaries Should Be Equal ${cur} ${exp} - END - FOR ${cur} ${exp} IN ZIP ${MODEL}[typedocs][0][members] ${exp_list} + FOR ${cur} ${exp} IN ZIP ${MODEL}[typedocs][1][members] ${exp_list} Dictionaries Should Be Equal ${cur} ${exp} END Custom types - ${MODEL}[typedocs][2][type] Custom - ${MODEL}[typedocs][2][name] CustomType - ${MODEL}[typedocs][2][doc]

      Converter method doc is used when defined.

      - ${MODEL}[typedocs][3][type] Custom - ${MODEL}[typedocs][3][name] CustomType2 - ${MODEL}[typedocs][3][doc]

      Class doc is used when converter method has no doc.

      + ${MODEL}[typedocs][3][type] Custom + ${MODEL}[typedocs][3][name] CustomType + ${MODEL}[typedocs][3][doc]

      Converter method doc is used when defined.

      + ${MODEL}[typedocs][4][type] Custom + ${MODEL}[typedocs][4][name] CustomType2 + ${MODEL}[typedocs][4][doc]

      Class doc is used when converter method has no doc.

      Standard types - ${MODEL}[typedocs][1][type] Standard - ${MODEL}[typedocs][1][name] boolean - ${MODEL}[typedocs][1][doc]

      Strings TRUE, YES, start=True + ${MODEL}[typedocs][0][type] Standard + ${MODEL}[typedocs][0][name] Any + ${MODEL}[typedocs][0][doc]

      Any value is accepted. No conversion is done.

      + ${MODEL}[typedocs][2][type] Standard + ${MODEL}[typedocs][2][name] boolean + ${MODEL}[typedocs][2][doc]

      Strings TRUE, YES, start=True + ${MODEL}[typedocs][10][name] Literal + ${MODEL}[typedocs][10][doc]

      Only specified values are accepted. start=True + +Standard types with generics + ${MODEL}[typedocs][5][type] Standard + ${MODEL}[typedocs][5][name] dictionary + ${MODEL}[typedocs][5][doc]

      Strings must be Python Strings must be Python ${HTML DOC}

      HTML --format jSoN --specdocformat hTML DocFormat.py

      ${HTML DOC}

      HTML --format jSoN DocFormat.py

      ${HTML DOC}

      HTML --docfor RoBoT -f JSON -s HTML DocFormatHtml.py @@ -68,6 +70,7 @@ Format from XML spec Format from JSON RAW spec [Template] NONE + [Tags] require-jsonschema Test Format In JSON ${RAW DOC} ROBOT -F Robot -s RAW lib=DocFormat.py Copy File ${OUTJSON} ${OUTBASE}-2.json Test Format In JSON

      ${HTML DOC}

      HTML lib=${OUTBASE}-2.json @@ -80,6 +83,7 @@ Format from LIBSPEC spec Format from JSON spec [Template] NONE + [Tags] require-jsonschema Test Format In JSON

      ${HTML DOC}

      HTML -F Robot lib=DocFormat.py Copy File ${OUTJSON} ${OUTBASE}-2.json Test Format In JSON

      ${HTML DOC}

      HTML lib=${OUTBASE}-2.json diff --git a/atest/robot/libdoc/dynamic_library.robot b/atest/robot/libdoc/dynamic_library.robot index 6539af01d7e..a3adf492b29 100644 --- a/atest/robot/libdoc/dynamic_library.robot +++ b/atest/robot/libdoc/dynamic_library.robot @@ -90,6 +90,9 @@ Keyword tags from documentation Keyword types Keyword Arguments Should Be 18 integer: int no type boolean: bool = True +Return type + Return Type Should Be 18 int + No keyword source info Keyword Name Should Be 0 0 Keyword Should Not Have Source 0 diff --git a/atest/robot/libdoc/html_output.robot b/atest/robot/libdoc/html_output.robot index f42a4b150b8..d259c49bc7d 100644 --- a/atest/robot/libdoc/html_output.robot +++ b/atest/robot/libdoc/html_output.robot @@ -15,7 +15,7 @@ Version Generated [Template] Should Match Regexp - ${MODEL}[generated] \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} + ${MODEL}[generated] \\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]\\d{2}:\\d{2} Scope ${MODEL}[scope] GLOBAL @@ -33,7 +33,7 @@ Keyword Arguments [Template] Verify Argument Models ${MODEL}[keywords][0][args] ${MODEL}[keywords][1][args] a1=d *a2 - ${MODEL}[keywords][6][args] arg=hyv\\xe4 + ${MODEL}[keywords][6][args] arg=hyvä ${MODEL}[keywords][9][args] arg=hyvä ${MODEL}[keywords][10][args] a=1 b=True c=(1, 2, None) ${MODEL}[keywords][11][args] arg=\\ robot \\ escapers\\n\\t\\r \\ \\ @@ -41,8 +41,18 @@ Keyword Arguments Embedded Arguments [Template] NONE - Should Be Equal ${MODEL}[keywords][13][name] Takes \${embedded} \${args} - Should Be Empty ${MODEL}[keywords][13][args] + Should Be Equal ${MODEL}[keywords][13][name] Takes \${embedded} \${args} + Should Be Empty ${MODEL}[keywords][13][args] + +Embedded and Normal Arguments + [Template] NONE + Should Be Equal ${MODEL}[keywords][14][name] Takes \${embedded} and normal args + Verify Argument Models ${MODEL}[keywords][14][args] mandatory optional=None + +Embedded and Positional-only Arguments + [Template] NONE + Should Be Equal ${MODEL}[keywords][15][name] Takes \${embedded} and positional-only args + Verify Argument Models ${MODEL}[keywords][15][args] mandatory / optional=None Keyword Documentation ${MODEL}[keywords][1][doc] @@ -105,6 +115,13 @@ User keyword documentation formatting ... ... +Private keyword should be excluded + [Setup] Run Libdoc And Parse Model From HTML ${TESTDATADIR}/resource.robot + [Template] None + FOR ${keyword} IN @{MODEL}[keywords] + Should Not Be Equal ${keyword}[name] Private + END + *** Keywords *** Verify Argument Models [Arguments] ${arg_models} @{expected_reprs} diff --git a/atest/robot/libdoc/invalid_library_keywords.robot b/atest/robot/libdoc/invalid_library_keywords.robot index 4f212480158..f923179c717 100644 --- a/atest/robot/libdoc/invalid_library_keywords.robot +++ b/atest/robot/libdoc/invalid_library_keywords.robot @@ -20,7 +20,7 @@ Invalid embedded arguments Keyword Count Should Be 3 Stdout should contain adding keyword error ... Invalid embedded \${args} - ... Embedded argument count does not match number of accepted arguments. + ... Keyword must accept at least as many positional arguments as it has embedded arguments. *** Keywords *** Stdout should contain adding keyword error diff --git a/atest/robot/libdoc/invalid_usage.robot b/atest/robot/libdoc/invalid_usage.robot index 24f1c0b4ec7..51b7daada69 100644 --- a/atest/robot/libdoc/invalid_usage.robot +++ b/atest/robot/libdoc/invalid_usage.robot @@ -2,7 +2,6 @@ Resource libdoc_resource.robot Test Setup Remove File ${OUT HTML} Test Template Run libdoc and verify error -Test Teardown Should Not Exist ${OUT HTML} *** Test Cases *** No arguments @@ -22,6 +21,7 @@ Invalid format --format XML:XXX BuiltIn ${OUT HTML} Format must be 'HTML', 'XML', 'JSON' or 'LIBSPEC', got 'XML:XXX'. --format XML:HTML BuiltIn ${OUT HTML} Format must be 'HTML', 'XML', 'JSON' or 'LIBSPEC', got 'XML:HTML'. BuiltIn out.ext Format must be 'HTML', 'XML', 'JSON' or 'LIBSPEC', got 'EXT'. + BuiltIn BuiltIn Format must be 'HTML', 'XML', 'JSON' or 'LIBSPEC', got ''. Invalid specdocformat -s XXX BuiltIn ${OUT HTML} Spec doc format must be 'RAW' or 'HTML', got 'XXX'. @@ -36,6 +36,10 @@ Invalid doc format Invalid doc format in library ${TESTDATADIR}/DocFormatInvalid.py ${OUT HTML} Invalid documentation format 'INVALID'. +Invalid theme + --theme bad String ${OUT XML} Theme must be 'DARK', 'LIGHT' or 'NONE', got 'BAD'. + --theme light --format xml String ${OUT XML} The --theme option is only applicable with HTML outputs. + Non-existing library NonExistingLib ${OUT HTML} Importing library 'NonExistingLib' failed: * @@ -53,11 +57,17 @@ Non-XML spec [Teardown] Remove File ${OUT XML} Invalid resource - ${CURDIR}/invalid_usage.robot ${OUT HTML} - ... ? ERROR ? Error in file '*' on line 3: Setting 'Test Setup' is not allowed in resource file. - ... ? ERROR ? Error in file '*' on line 4: Setting 'Test Template' is not allowed in resource file. - ... ? ERROR ? Error in file '*' on line 5: Setting 'Test Teardown' is not allowed in resource file. - ... Error in file '*[/\\]invalid_usage.robot' on line 7: Resource file with 'Test Cases' section is invalid. + ${TESTDATADIR}/invalid_resource.resource ${OUT HTML} + ... ? ERROR ? Error in file '*[/\\]invalid_resource.resource' on line 2: Setting 'Metadata' is not allowed in resource file. + ... ? ERROR ? Error in file '*[/\\]invalid_resource.resource' on line 3: Setting 'Test Setup' is not allowed in resource file. + ... Error in file '*[/\\]invalid_resource.resource' on line 5: Resource file with 'Test Cases' section is invalid. + +Invalid resource with '.robot' extension + ${TESTDATADIR}/invalid_resource.robot ${OUT HTML} + ... ? ERROR ? Error in file '*[/\\]invalid_resource.robot' on line 2: Setting 'Metadata' is not allowed in resource file. + ... ? ERROR ? Error in file '*[/\\]invalid_resource.robot' on line 3: Setting 'Test Setup' is not allowed in resource file. + ... ${OUT HTML} + ... fatal=False Invalid output file [Setup] Run Keywords @@ -70,10 +80,16 @@ Invalid output file ... Remove Directory ${OUT HTML} AND ... Remove Directory ${OUT XML} -invalid Spec File version - ${TESTDATADIR}/OldSpec.xml ${OUT XML} Invalid spec file version 'None'. Supported versions are 3 and 4. +Invalid Spec File version + ${TESTDATADIR}/OldSpec.xml ${OUT XML} Invalid spec file version 'None'. Supported versions are 3, 4, 5, and 6. *** Keywords *** Run libdoc and verify error - [Arguments] ${args} @{error} - Run libdoc and verify output ${args} @{error} ${USAGE TIP[1:]} + [Arguments] ${args} @{error} ${fatal}=True + IF ${fatal} + Run Libdoc And Verify Output ${args} @{error} ${USAGE TIP[1:]} + File Should Not Exist ${OUT HTML} + ELSE + Run Libdoc And Verify Output ${args} @{error} + File Should Exist ${OUT HTML} + END diff --git a/atest/robot/libdoc/invalid_user_keywords.robot b/atest/robot/libdoc/invalid_user_keywords.robot index 530cec1840c..9dcec3a8cf7 100644 --- a/atest/robot/libdoc/invalid_user_keywords.robot +++ b/atest/robot/libdoc/invalid_user_keywords.robot @@ -6,16 +6,16 @@ Resource libdoc_resource.robot Invalid arg spec Keyword Name Should Be 0 Invalid arg spec Keyword Doc Should Be 0 *Creating keyword failed:* Invalid argument specification: Only last argument can be kwargs. - Stdout should contain error Invalid arg spec 2 + Stdout should contain error Invalid arg spec 3 ... Invalid argument specification: Only last argument can be kwargs. -Dublicate name - Keyword Name Should Be 3 Same twice +Duplicate name + Keyword Name Should Be 3 Same Twice Keyword Doc Should Be 3 *Creating keyword failed:* Keyword with same name defined multiple times. - Stdout should contain error Same twice 8 + Stdout should contain error Same twice 10 ... Keyword with same name defined multiple times -Dublicate name with embedded arguments +Duplicate name with embedded arguments Keyword Name Should Be 1 same \${embedded match} Keyword Doc Should Be 1 ${EMPTY} Keyword Name Should Be 2 Same \${embedded} diff --git a/atest/robot/libdoc/json_output.robot b/atest/robot/libdoc/json_output.robot index 78305a45851..deec2eb1cf4 100644 --- a/atest/robot/libdoc/json_output.robot +++ b/atest/robot/libdoc/json_output.robot @@ -2,6 +2,7 @@ Resource libdoc_resource.robot Suite Setup Run Libdoc And Parse Model From JSON ${TESTDATADIR}/module.py Test Template Should Be Equal Multiline +Test Tags require-jsonschema *** Test Cases *** Name @@ -15,7 +16,7 @@ Version Generated [Template] Should Match Regexp - ${MODEL}[generated] \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} + ${MODEL}[generated] \\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[+-]\\d{2}:\\d{2} Scope ${MODEL}[scope] GLOBAL @@ -33,7 +34,7 @@ Keyword Arguments [Template] Verify Argument Models ${MODEL}[keywords][0][args] ${MODEL}[keywords][1][args] a1=d *a2 - ${MODEL}[keywords][6][args] arg=hyv\\xe4 + ${MODEL}[keywords][6][args] arg=hyvä ${MODEL}[keywords][9][args] arg=hyvä ${MODEL}[keywords][10][args] a=1 b=True c=(1, 2, None) ${MODEL}[keywords][11][args] arg=\\ robot \\ escapers\\n\\t\\r \\ \\ @@ -41,8 +42,18 @@ Keyword Arguments Embedded Arguments [Template] NONE - Should Be Equal ${MODEL}[keywords][13][name] Takes \${embedded} \${args} - Should Be Empty ${MODEL}[keywords][13][args] + Should Be Equal ${MODEL}[keywords][13][name] Takes \${embedded} \${args} + Should Be Empty ${MODEL}[keywords][13][args] + +Embedded and Normal Arguments + [Template] NONE + Should Be Equal ${MODEL}[keywords][14][name] Takes \${embedded} and normal args + Verify Argument Models ${MODEL}[keywords][14][args] mandatory optional=None + +Embedded and Positional-only Arguments + [Template] NONE + Should Be Equal ${MODEL}[keywords][15][name] Takes \${embedded} and positional-only args + Verify Argument Models ${MODEL}[keywords][15][args] mandatory / optional=None Keyword Documentation ${MODEL}[keywords][1][doc] @@ -105,6 +116,20 @@ User keyword documentation formatting ... ... +Private user keyword should be included + [Setup] Run Libdoc And Parse Model From JSON ${TESTDATADIR}/resource.robot + ${MODEL}[keywords][-1][name] Private + ${MODEL}[keywords][-1][tags] ['robot:private'] + ${MODEL}[keywords][-1][private] True + ${MODEL['keywords'][0].get('private')} None + +Deprecation + [Setup] Run Libdoc And Parse Model From JSON ${TESTDATADIR}/Deprecation.py + ${MODEL}[keywords][0][deprecated] True + ${MODEL}[keywords][1][deprecated] True + ${MODEL['keywords'][2].get('deprecated')} None + ${MODEL['keywords'][3].get('deprecated')} None + *** Keywords *** Verify Argument Models [Arguments] ${arg_models} @{expected_reprs} diff --git a/atest/robot/libdoc/libdoc_resource.robot b/atest/robot/libdoc/libdoc_resource.robot index 351b5e793d3..8f08ec03f6a 100644 --- a/atest/robot/libdoc/libdoc_resource.robot +++ b/atest/robot/libdoc/libdoc_resource.robot @@ -31,8 +31,8 @@ Run Libdoc And Parse Output Run Libdoc And Verify Output [Arguments] ${args} @{expected} + VAR ${expected} @{expected} separator=\n ${output}= Run Libdoc ${args} - ${expected}= Catenate SEPARATOR=\n @{expected} Should Match ${output} ${expected}\n Run Libdoc And Parse Model From HTML @@ -80,7 +80,7 @@ Type Should Be Element Attribute Should Be ${LIBDOC} type ${type} Scope Should Be - [Arguments] ${scope} ${old}=${{ {'GLOBAL': 'global', 'SUITE': 'test suite', 'TEST': 'test case'}[$scope] }} + [Arguments] ${scope} Element Attribute Should Be ${LIBDOC} scope ${scope} Source Should Be @@ -93,10 +93,16 @@ Lineno Should Be Element Attribute Should Be ${LIBDOC} lineno ${lineno} Generated Should Be Defined - Element Attribute Should Match ${LIBDOC} generated ????-??-??T??:??:??Z + # For example, '1970-01-01T00:00:01+00:00'. + Element Attribute Should Match ${LIBDOC} generated ????-??-??T??:??:?????:?? + +Generated Should Be + [Arguments] ${generated} + Generated Should Be Defined + Element Attribute Should Be ${LIBDOC} generated ${generated} Spec version should be correct - Element Attribute Should Be ${LIBDOC} specversion 4 + Element Attribute Should Be ${LIBDOC} specversion 6 Should Have No Init ${inits} = Get Elements ${LIBDOC} xpath=inits/init @@ -132,12 +138,22 @@ Verify Arguments Structure [Arguments] ${index} ${xpath} ${expected} ${kws}= Get Elements ${LIBDOC} xpath=${xpath} ${arg_elems}= Get Elements ${kws}[${index}] xpath=arguments/arg - FOR ${arg_elem} ${exp_repr} IN ZIP ${arg_elems} ${expected} + FOR ${arg_elem} ${exp_repr} IN ZIP ${arg_elems} ${expected} mode=STRICT + IF $INTERPRETER.version_info >= (3, 11) + ${exp_repr} = Replace String ${exp_repr} | None = None = None + END ${kind}= Get Element Attribute ${arg_elem} kind ${required}= Get Element Attribute ${arg_elem} required ${repr}= Get Element Attribute ${arg_elem} repr ${name}= Get Element Optional Text ${arg_elem} name - ${type}= Get Elements Texts ${arg_elem} type + ${types}= Get Elements ${arg_elem} type + IF not $types + ${type}= Set Variable ${None} + ELSE IF len($types) == 1 + ${type}= Get Type ${types}[0] + ELSE + Fail Cannot have more than one element + END ${default}= Get Element Optional Text ${arg_elem} default ${arg_model}= Create Dictionary ... kind=${kind} @@ -148,7 +164,37 @@ Verify Arguments Structure Verify Argument Model ${arg_model} ${exp_repr} Should Be Equal ${repr} ${exp_repr} END - Should Be Equal ${{len($arg_elems)}} ${{len($expected)}} + +Return Type Should Be + [Arguments] ${index} ${name} @{nested} + ${kws}= Get Elements ${LIBDOC} xpath=keywords/kw + VAR ${kw} ${kws}[${index}] + IF $name.upper() == 'NONE' + Element Should Not Exist ${kw} returntype + RETURN + END + Element Attribute Should Be ${kw} name ${name} xpath=returntype + ${type_elems} = Get Elements ${kw} returntype/type + FOR ${elem} ${expected} IN ZIP ${type_elems} ${nested} mode=STRICT + Element Attribute Should Be ${elem} name ${expected} + END + +Get Type + [Arguments] ${elem} + ${children} = Get Elements ${elem} type + ${nested} = Create List + FOR ${child} IN @{children} + ${type} = Get Type ${child} + Append To List ${nested} ${type} + END + ${type} = Get Element Attribute ${elem} name + IF $elem.get('union') == 'true' + ${type} = Catenate SEPARATOR=${SPACE}|${SPACE} @{nested} + ELSE IF $nested + ${args} = Catenate SEPARATOR=,${SPACE} @{nested} + ${type} = Set Variable ${type}\[${args}] + END + RETURN ${type} Get Element Optional Text [Arguments] ${source} ${xpath} @@ -193,7 +239,7 @@ Keyword Tags Should Be Specfile Tags Should Be [Arguments] @{expected} - ${tags} Get Elements Texts ${LIBDOC} xpath=tags/tag + ${tags}= Get Elements Texts ${LIBDOC} xpath=tags/tag Should Be Equal ${tags} ${expected} Keyword Source Should Be @@ -217,6 +263,16 @@ Keyword Should Not Have Lineno ${kws}= Get Elements ${LIBDOC} xpath=${xpath} Element Should Not Have Attribute ${kws}[${index}] lineno +Keyword Should Be Private + [Arguments] ${index} + ${kws}= Get Elements ${LIBDOC} xpath=keywords/kw + Element Attribute Should be ${kws}[${index}] private true + +Keyword Should Not Be Private + [Arguments] ${index} + ${kws}= Get Elements ${LIBDOC} xpath=keywords/kw + Element Should Not Have Attribute ${kws}[${index}] private + Keyword Should Be Deprecated [Arguments] ${index} ${kws}= Get Elements ${LIBDOC} xpath=keywords/kw @@ -252,52 +308,48 @@ List of Dict Should Be Equal DataType Enum Should Be [Arguments] ${index} ${name} ${doc} @{exp_members} - FOR ${xpath} IN datatypes/enums/enum typedocs/type[@type='Enum'] - ${enums}= Get Elements ${LIBDOC} xpath=${xpath} - Element Attribute Should Be ${enums}[${index}] name ${name} - Element Text Should Be ${enums}[${index}] ${doc} xpath=doc - ${members}= Get Elements ${enums}[${index}] xpath=members/member - FOR ${member} ${exp_member} IN ZIP ${members} ${exp_members} - ${attrs}= Get Element Attributes ${member} - Element Attribute Should Be ${member} name ${{${exp_member}}}[name] - Element Attribute Should Be ${member} value ${{${exp_member}}}[value] - END + ${enums}= Get Elements ${LIBDOC} xpath=typedocs/type[@type='Enum'] + Element Attribute Should Be ${enums}[${index}] name ${name} + Element Text Should Be ${enums}[${index}] ${doc} xpath=doc + ${members}= Get Elements ${enums}[${index}] xpath=members/member + FOR ${member} ${exp_member} IN ZIP ${members} ${exp_members} + ${attrs}= Get Element Attributes ${member} + Element Attribute Should Be ${member} name ${{${exp_member}}}[name] + Element Attribute Should Be ${member} value ${{${exp_member}}}[value] END DataType TypedDict Should Be [Arguments] ${index} ${name} ${doc} @{exp_items} - FOR ${xpath} IN datatypes/typeddicts/typeddict typedocs/type[@type='TypedDict'] - ${dicts}= Get Elements ${LIBDOC} xpath=${xpath} - Element Attribute Should Be ${dicts}[${index}] name ${name} - Element Text Should Be ${dicts}[${index}] ${doc} xpath=doc - ${items}= Get Elements ${dicts}[${index}] xpath=items/item - FOR ${exp_item} IN @{exp_items} - ${exp}= Evaluate json.loads($exp_item) - FOR ${item} IN @{items} - ${cur}= Get Element Attributes ${item} - IF $cur['key'] == $exp['key'] - Should Be Equal ${cur}[key] ${exp}[key] - Should Be Equal ${cur}[type] ${exp}[type] - IF 'required' in $exp - Should Be Equal ${cur}[required] ${exp}[required] - END - BREAK + ${dicts}= Get Elements ${LIBDOC} xpath=typedocs/type[@type='TypedDict'] + Element Attribute Should Be ${dicts}[${index}] name ${name} + Element Text Should Be ${dicts}[${index}] ${doc} xpath=doc + ${items}= Get Elements ${dicts}[${index}] xpath=items/item + FOR ${exp_item} IN @{exp_items} + ${exp}= Evaluate json.loads($exp_item) + FOR ${item} IN @{items} + ${cur}= Get Element Attributes ${item} + IF $cur['key'] == $exp['key'] + Should Be Equal ${cur}[key] ${exp}[key] + Should Be Equal ${cur}[type] ${exp}[type] + IF 'required' in $exp + Should Be Equal ${cur}[required] ${exp}[required] END + BREAK END END END DataType Custom Should Be [Arguments] ${index} ${name} ${doc} - ${customs}= Get Elements ${LIBDOC} xpath=typedocs/type[@type='Custom'] - Element Attribute Should Be ${customs}[${index}] name ${name} - Element Text Should Be ${customs}[${index}] ${doc} xpath=doc + ${types}= Get Elements ${LIBDOC} xpath=typedocs/type[@type='Custom'] + Element Attribute Should Be ${types}[${index}] name ${name} + Element Text Should Be ${types}[${index}] ${doc} xpath=doc DataType Standard Should Be [Arguments] ${index} ${name} ${doc} - ${customs}= Get Elements ${LIBDOC} xpath=typedocs/type[@type='Standard'] - Element Attribute Should Be ${customs}[${index}] name ${name} - Element Text Should Match ${customs}[${index}] ${doc}* xpath=doc + ${types}= Get Elements ${LIBDOC} xpath=typedocs/type[@type='Standard'] + Element Attribute Should Be ${types}[${index}] name ${name} + Element Text Should Match ${types}[${index}] ${doc}* xpath=doc Usages Should Be [Arguments] ${index} ${type} ${name} @{expected} @@ -322,15 +374,21 @@ Accepted Types Should Be END Typedoc links should be - [Arguments] ${kw} ${arg} @{typedocs} - ${types} = Get Elements ${LIBDOC} keywords/kw[${${kw} + 1}]/arguments/arg[${${arg} + 1}]/type - Length Should Be ${types} ${{len($typedocs)}} - FOR ${type} ${typedoc} IN ZIP ${types} ${typedocs} - IF ':' in $typedoc - ${typename} ${typedoc} = Split String ${typedoc} : - ELSE - ${typename} = Set Variable ${typedoc} - END - Element Text Should Be ${type} ${typename} - Element Attribute Should Be ${type} typedoc ${{$typedoc or None}} + [Arguments] ${kw} ${arg} ${typedoc} @{nested typedocs} + ${type} = Get Element ${LIBDOC} keywords/kw[${${kw} + 1}]/arguments/arg[${${arg} + 1}]/type + Typedoc link should be ${type} ${typedoc} + ${nested} = Get Elements ${type} type + Length Should Be ${nested} ${{len($nested_typedocs)}} + FOR ${type} ${typedoc} IN ZIP ${nested} ${nested typedocs} + Typedoc link should be ${type} ${typedoc} + END + +Typedoc link should be + [Arguments] ${type} ${typedoc} + IF ':' in $typedoc + ${typename} ${typedoc} = Split String ${typedoc} : + ELSE + ${typename} = Set Variable ${typedoc} END + Element Attribute Should Be ${type} name ${typename} + Element Attribute Should Be ${type} typedoc ${{$typedoc or None}} diff --git a/atest/robot/libdoc/module_library.robot b/atest/robot/libdoc/module_library.robot index 3744d8e82d4..4dbb7717ea2 100644 --- a/atest/robot/libdoc/module_library.robot +++ b/atest/robot/libdoc/module_library.robot @@ -44,7 +44,7 @@ Keyword Arguments Keyword Arguments Should Be 12 a b *args **kwargs Non-ASCII Bytes Defaults - Keyword Arguments Should Be 6 arg=hyv\\xe4 + Keyword Arguments Should Be 6 arg=hyvä Non-ASCII String Defaults Keyword Arguments Should Be 9 arg=hyvä @@ -53,6 +53,14 @@ Embedded Arguments Keyword Name Should Be 13 Takes \${embedded} \${args} Keyword Arguments Should Be 13 +Embedded and Normal Arguments + Keyword Name Should Be 14 Takes \${embedded} and normal args + Keyword Arguments Should Be 14 mandatory optional=None + +Embedded and Positional-only Arguments + Keyword Name Should Be 15 Takes \${embedded} and positional-only args + Keyword Arguments Should Be 15 mandatory / optional=None + Keyword Documentation Keyword Doc Should Be 1 A keyword.\n\nSee `get hello` for details. Keyword Shortdoc Should Be 1 A keyword. diff --git a/atest/robot/libdoc/python_library.robot b/atest/robot/libdoc/python_library.robot index c6266e6cbff..5ad43a8479e 100644 --- a/atest/robot/libdoc/python_library.robot +++ b/atest/robot/libdoc/python_library.robot @@ -13,7 +13,7 @@ Documentation ... ``Telnet`` is Robot Framework's standard library that makes it possible to Version - Version Should Match [345].* + Version Should Match [6789].* Type Type Should Be LIBRARY @@ -53,10 +53,10 @@ Keyword Names Keyword Arguments Keyword Arguments Should Be 0 - Keyword Arguments Should Be 1 loglevel=None + Keyword Arguments Should Be 1 loglevel=None Keyword Documentation - Keyword Doc Should Start With 0 Closes all open connections + Keyword Doc Should Start With 0 Closes all open connections Keyword Doc Should Start With 2 ... Executes the given ``command`` and reads, logs, and returns everything until the prompt. ... @@ -76,29 +76,28 @@ Keyword Source Info # This keyword is from the "main library". Keyword Name Should Be 0 Close All Connections Keyword Should Not Have Source 0 - Keyword Lineno Should Be 0 470 + Keyword Lineno Should Be 0 472 # This keyword is from an external library component. Keyword Name Should Be 7 Read Until Prompt Keyword Should Not Have Source 7 - Keyword Lineno Should Be 7 1009 + Keyword Lineno Should Be 7 1011 KwArgs and VarArgs - Run Libdoc And Parse Output Process - Keyword Name Should Be 7 Run Process - Keyword Arguments Should Be 7 command *arguments **configuration + Run Libdoc And Parse Output ${TESTDATADIR}/KwArgs.py + Keyword Arguments Should Be 2 *varargs **kwargs + Keyword Arguments Should Be 3 a / b c=d *e f g=h **i Keyword-only Arguments - Run Libdoc And Parse Output ${TESTDATADIR}/KeywordOnlyArgs.py + Run Libdoc And Parse Output ${TESTDATADIR}/KwArgs.py Keyword Arguments Should Be 0 * kwo Keyword Arguments Should Be 1 *varargs kwo another=default Positional-only Arguments - [Tags] require-py3.8 Run Libdoc And Parse Output ${DATADIR}/keywords/PositionalOnly.py - Keyword Arguments Should Be 2 arg / + Keyword Arguments Should Be 1 arg / Keyword Arguments Should Be 5 posonly / normal Keyword Arguments Should Be 0 required optional=default / - Keyword Arguments Should Be 4 first: int second: float / + Keyword Arguments Should Be 3 first: int second: float / Decorators Run Libdoc And Parse Output ${TESTDATADIR}/Decorators.py @@ -114,6 +113,11 @@ Documentation set in __init__ Run Libdoc And Parse Output ${TESTDATADIR}/DocSetInInit.py Doc Should Be Doc set in __init__!! +__init__ with only named-only arguments + Run Libdoc And Parse Output ${TESTDATADIR}/InitWithOnlyNamedOnlyArgs.py::b=2 + Init Arguments Should Be 0 * a=1 b + Init Doc Should Be 0 xxx + Deprecation Run Libdoc And Parse Output ${TESTDATADIR}/Deprecation.py Keyword Name Should Be 0 Deprecated @@ -130,3 +134,8 @@ Deprecation ... ... RF and Libdoc don't consider this being deprecated. Keyword Should Not Be Deprecated 3 + +NOT_SET as default value + Run Libdoc And Parse Output Collections + Keyword Name Should Be 17 Get From Dictionary + Keyword Arguments Should Be 17 dictionary key default= diff --git a/atest/robot/libdoc/resource_file.robot b/atest/robot/libdoc/resource_file.robot index 35e06f8def1..0e138bdec20 100644 --- a/atest/robot/libdoc/resource_file.robot +++ b/atest/robot/libdoc/resource_file.robot @@ -19,7 +19,7 @@ Documentation ... ... | *TABLE* | ... | \${NONEX} | $\{CURDIR} | \${TEMPDIR} | - ... | foo | bar | + ... | foo${SPACE*6}|${SPACE*4}bar${SPACE*4}| ... tabs \t\t\t here Version @@ -32,7 +32,7 @@ Generated Generated Should Be Defined Scope - Scope Should Be GLOBAL old=${EMPTY} + Scope Should Be GLOBAL Source Info Source Should Be ${TESTDATADIR}/resource.robot @@ -43,7 +43,7 @@ Spec version Resource Tags Specfile Tags Should Be \${3} ?!?!?? a b bar dar - ... foo Has kw4 tags + ... foo Has kw4 robot:private tags Resource Has No Inits Should Have No Init @@ -85,7 +85,7 @@ Keyword Documentation ... ------------- ... ... | = first = | = second = | - ... | foo | bar | + ... | foo${SPACE*7}|${SPACE*4}bar${SPACE*5}| Keyword Doc Should Be 9 ... Summary line ... @@ -110,14 +110,19 @@ Non ASCII Keyword Source Info Keyword Name Should Be 0 curdir Keyword Should Not Have Source 0 - Keyword Lineno Should Be 0 65 + Keyword Lineno Should Be 0 71 '*.resource' extension is accepted Run Libdoc And Parse Output ${TESTDATADIR}/resource.resource Source Should Be ${TESTDATADIR}/resource.resource Lineno Should Be 1 - Keyword Name Should Be 0 Yay, I got new extension! - Keyword Arguments Should Be 0 Awesome!! - Keyword Doc Should Be 0 Yeah!!! - Keyword Should Not Have Source 0 - Keyword Lineno Should Be 0 2 + Keyword Name Should Be 2 Yay, I got new extension! + Keyword Arguments Should Be 2 Awesome!! + Keyword Doc Should Be 2 Yeah!!! + Keyword Should Not Have Source 2 + Keyword Lineno Should Be 2 5 + +Keyword Tags setting + Keyword Tags Should Be 0 keyword own tags + Keyword Tags Should Be 1 in doc keyword own tags + Keyword Tags Should Be 2 keyword tags diff --git a/atest/robot/libdoc/return_type.robot b/atest/robot/libdoc/return_type.robot new file mode 100644 index 00000000000..dd0c283d324 --- /dev/null +++ b/atest/robot/libdoc/return_type.robot @@ -0,0 +1,49 @@ +*** Settings *** +Suite Setup Run Libdoc And Parse Output ${TESTDATADIR}/ReturnType.py +Test Template Return Type Should Be +Resource libdoc_resource.robot + +*** Test Cases *** +No return + 0 None + +None return + 1 None + +Simple return + 2 int + +Parameterized return + 3 List int + +Union return + 4 Union int float + +Stringified return + 5 Union int float + +Unknown return + 6 Unknown + +Invalid return + [Template] NONE + VAR ${error} + ... [ ERROR ] Error in library 'ReturnType': + ... Adding keyword 'H_invalid_return' failed: + ... Parsing type 'list[int' failed: + ... Error at end: + ... Closing ']' missing. + Should Start With ${OUTPUT} ${error} + +Return types are in typedocs + [Template] Usages Should Be + 0 Standard float + ... E Union Return + ... F Stringified Return + 1 Standard integer + ... C Simple Return + ... D Parameterized Return + ... E Union Return + ... F Stringified Return + 2 Standard list + ... D Parameterized Return diff --git a/atest/robot/libdoc/return_type_json.robot b/atest/robot/libdoc/return_type_json.robot new file mode 100644 index 00000000000..2a2de45eff5 --- /dev/null +++ b/atest/robot/libdoc/return_type_json.robot @@ -0,0 +1,59 @@ +*** Settings *** +Suite Setup Run Libdoc And Parse Model From JSON ${TESTDATADIR}/ReturnType.py +Test Template Return type should be +Resource libdoc_resource.robot +Test Tags require-jsonschema + +*** Test Cases *** +No return + 0 None + +None return + 1 None + +Simple return + 2 {'name': 'int', 'typedoc': 'integer', 'nested': [], 'union': False} + +Parameterized return + 3 {'name': 'List', + ... 'typedoc': 'list', + ... 'nested': [{'name': 'int', 'typedoc': 'integer', 'nested': [], 'union': False}], + ... 'union': False} + +Union return + 4 {'name': 'Union', + ... 'typedoc': None, + ... 'nested': [{'name': 'int', 'typedoc': 'integer', 'nested': [], 'union': False}, + ... {'name': 'float', 'typedoc': 'float', 'nested': [], 'union': False}], + ... 'union': True} + +Stringified return + 5 {'name': 'Union', + ... 'typedoc': None, + ... 'nested': [{'name': 'int', 'typedoc': 'integer', 'nested': [], 'union': False}, + ... {'name': 'float', 'typedoc': 'float', 'nested': [], 'union': False}], + ... 'union': True} + +Unknown return + 6 {'name': 'Unknown', 'typedoc': None, 'nested': [], 'union': False} + +Return types are in typedocs + [Template] Should Be Equal + ${MODEL}[typedocs][0][name] float + ${MODEL}[typedocs][0][usages][0] E Union Return + ${MODEL}[typedocs][0][usages][1] F Stringified Return + ${MODEL}[typedocs][1][name] integer + ${MODEL}[typedocs][1][usages][0] C Simple Return + ${MODEL}[typedocs][1][usages][1] D Parameterized Return + ${MODEL}[typedocs][1][usages][2] E Union Return + ${MODEL}[typedocs][1][usages][3] F Stringified Return + ${MODEL}[typedocs][2][name] list + ${MODEL}[typedocs][2][usages][0] D Parameterized Return + +*** Keywords *** +Return type should be + [Arguments] ${index} @{expected} + VAR ${expected} @{expected} + Should Be Equal As Strings + ... ${MODEL}[keywords][${index}][returnType] + ... ${expected} diff --git a/atest/robot/libdoc/spec_library.robot b/atest/robot/libdoc/spec_library.robot index 1d74736c308..5bfa0089ef2 100644 --- a/atest/robot/libdoc/spec_library.robot +++ b/atest/robot/libdoc/spec_library.robot @@ -1,4 +1,5 @@ *** Settings *** +Library OperatingSystem Suite Setup Run Libdoc And Parse Output ${TESTDATADIR}/ExampleSpec.xml Resource libdoc_resource.robot @@ -85,6 +86,16 @@ Keyword Tags Keyword Tags Should Be 1 Keyword Tags Should Be 2 +Private Keywords + Keyword Should Not Be Private 0 + Keyword Should Be Private 1 + Keyword Should Not Be Private 2 + +Keyword Deprecation + Keyword Should Not Be Deprecated 0 + Keyword Should Be Deprecated 1 + Keyword Should Not Be Deprecated 2 + Keyword Source Info Keyword Should Not Have Source 0 Keyword Should Not Have Lineno 0 @@ -98,6 +109,13 @@ Keyword Source Info Run Libdoc And Parse Output %{TEMPDIR}/Example.libspec Test Everything +SOURCE_DATE_EPOCH is honored in Libdoc output + [Setup] Set Environment Variable SOURCE_DATE_EPOCH 0 + Copy File ${TESTDATADIR}/ExampleSpec.xml %{TEMPDIR}/Example.libspec + Run Libdoc And Parse Output %{TEMPDIR}/Example.libspec + Generated Should Be 1970-01-01T00:00:00+00:00 + [Teardown] Remove Environment Variable SOURCE_DATE_EPOCH + *** Keywords *** Test Everything Name Should Be Example @@ -130,6 +148,12 @@ Test Everything Keyword Tags Should Be 0 tag1 tag2 Keyword Tags Should Be 1 Keyword Tags Should Be 2 + Keyword Should Not Be Private 0 + Keyword Should Be Private 1 + Keyword Should Not Be Private 2 + Keyword Should Not Be Deprecated 0 + Keyword Should Be Deprecated 1 + Keyword Should Not Be Deprecated 2 Keyword Should Not Have Source 0 Keyword Should Not Have Lineno 0 Keyword Should Not Have Source 1 diff --git a/atest/robot/libdoc/suite_file.robot b/atest/robot/libdoc/suite_file.robot new file mode 100644 index 00000000000..9de82cc644d --- /dev/null +++ b/atest/robot/libdoc/suite_file.robot @@ -0,0 +1,70 @@ +*** Settings *** +Suite Setup Run Libdoc And Parse Output ${TESTDATADIR}/suite.robot +Resource libdoc_resource.robot + +*** Test Cases *** +Name + Name Should Be Suite + +Documentation + Doc Should Be Documentation for keywords in suite ``Suite``. + +Version + Version Should Be ${EMPTY} + +Type + Type Should Be SUITE + +Generated + Generated Should Be Defined + +Scope + Scope Should Be GLOBAL + +Source Info + Source Should Be ${TESTDATADIR}/suite.robot + Lineno Should Be 1 + +Spec version + Spec version should be correct + +Tags + Specfile Tags Should Be $\{CURDIR} keyword tags tags + +Suite Has No Inits + Should Have No Init + +Keyword Names + Keyword Name Should Be 0 1. Example + Keyword Name Should Be 1 2. Keyword with some "stuff" to + +Keyword Arguments + Keyword Arguments Should Be 0 + Keyword Arguments Should Be 1 a1 a2=c:\\temp\\ + +Different Argument Types + Keyword Arguments Should Be 2 mandatory optional=default *varargs + ... kwo=default another **kwargs + +Embedded Arguments + Keyword Name Should Be 3 4. Embedded \${arguments} + Keyword Arguments Should Be 3 + +Keyword Documentation + Keyword Doc Should Be 0 Keyword doc with $\{CURDIR}. + Keyword Doc Should Be 1 foo bar `kw` & some "stuff" to .\n\nbaa `\${a1}` + Keyword Doc Should Be 2 Multiple\n\nlines. + +Keyword tags + Keyword Tags Should Be 0 keyword tags tags + Keyword Tags Should Be 1 $\{CURDIR} keyword tags + +Non ASCII + Keyword Doc Should Be 3 Hyvää yötä. дякую! + +Keyword Source Info + Keyword Should Not Have Source 0 + Keyword Lineno Should Be 0 10 + +Test related settings should not cause errors + Should Not Contain ${OUTPUT} ERROR diff --git a/atest/robot/libdoc/suite_init_file.robot b/atest/robot/libdoc/suite_init_file.robot new file mode 100644 index 00000000000..0d1abb685ea --- /dev/null +++ b/atest/robot/libdoc/suite_init_file.robot @@ -0,0 +1,70 @@ +*** Settings *** +Suite Setup Run Libdoc And Parse Output ${TESTDATADIR}/__init__.robot +Resource libdoc_resource.robot + +*** Test Cases *** +Name + Name Should Be Libdoc + +Documentation + Doc Should Be Documentation for keywords in suite ``Libdoc``. + +Version + Version Should Be ${EMPTY} + +Type + Type Should Be SUITE + +Generated + Generated Should Be Defined + +Scope + Scope Should Be GLOBAL + +Source Info + Source Should Be ${TESTDATADIR} + Lineno Should Be 1 + +Spec version + Spec version should be correct + +Tags + Specfile Tags Should Be $\{CURDIR} keyword tags tags + +Suite Has No Inits + Should Have No Init + +Keyword Names + Keyword Name Should Be 0 1. Example + Keyword Name Should Be 1 2. Keyword with some "stuff" to + +Keyword Arguments + Keyword Arguments Should Be 0 + Keyword Arguments Should Be 1 a1 a2=c:\\temp\\ + +Different Argument Types + Keyword Arguments Should Be 2 mandatory optional=default *varargs + ... kwo=default another **kwargs + +Embedded Arguments + Keyword Name Should Be 3 4. Embedded \${arguments} + Keyword Arguments Should Be 3 + +Keyword Documentation + Keyword Doc Should Be 0 Keyword doc with $\{CURDIR}. + Keyword Doc Should Be 1 foo bar `kw` & some "stuff" to .\n\nbaa `\${a1}` + Keyword Doc Should Be 2 Multiple\n\nlines. + +Keyword tags + Keyword Tags Should Be 0 keyword tags tags + Keyword Tags Should Be 1 $\{CURDIR} keyword tags + +Non ASCII + Keyword Doc Should Be 3 Hyvää yötä. дякую! + +Keyword Source Info + Keyword Should Not Have Source 0 + Keyword Lineno Should Be 0 7 + +Test related settings should not cause errors + Should Not Contain ${OUTPUT} ERROR diff --git a/atest/robot/libdoc/type_annotations.robot b/atest/robot/libdoc/type_annotations.robot index e3d8983ec63..a51564c9819 100644 --- a/atest/robot/libdoc/type_annotations.robot +++ b/atest/robot/libdoc/type_annotations.robot @@ -22,7 +22,7 @@ Varargs and kwargs Keyword Arguments Should Be 4 *varargs: int **kwargs: bool Unknown types - Keyword Arguments Should Be 5 unknown: UnknownType unrecognized: Ellipsis + Keyword Arguments Should Be 5 unknown: UnknownType unrecognized: ... Non-type annotations Keyword Arguments Should Be 6 arg: One of the usages in PEP-3107 @@ -35,7 +35,14 @@ Union from typing Keyword Arguments Should Be 8 a: int | str | list | tuple Keyword Arguments Should Be 9 a: int | str | list | tuple | None = None +Nested + Keyword Arguments Should Be 10 a: List[int] b: List[int | float] c: Tuple[Tuple[UnknownType], Dict[str, Tuple[float]]] + + +Literal + Keyword Arguments Should Be 11 a: Literal['on', 'off', 'int'] b: Literal[1, 2, 3] c: Literal[one, True, None] + Union syntax [Tags] require-py3.10 - Keyword Arguments Should Be 10 a: int | str | list | tuple - Keyword Arguments Should Be 11 a: int | str | list | tuple | None = None + Keyword Arguments Should Be 12 a: int | str | list | tuple + Keyword Arguments Should Be 13 a: int | str | list | tuple | None = None diff --git a/atest/robot/libdoc/types_via_keyword_decorator.robot b/atest/robot/libdoc/types_via_keyword_decorator.robot index 3d9576da3d8..8f0c9ebf8ac 100644 --- a/atest/robot/libdoc/types_via_keyword_decorator.robot +++ b/atest/robot/libdoc/types_via_keyword_decorator.robot @@ -13,7 +13,7 @@ Varargs and kwargs Keyword Arguments Should Be 2 *varargs: int **kwargs: bool Unknown types - Keyword Arguments Should Be 3 unknown: UnknownType unrecognized: Ellipsis + Keyword Arguments Should Be 3 unknown: UnknownType unrecognized: ... Non-type annotations Keyword Arguments Should Be 4 arg: One of the usages in PEP-3107 @@ -21,3 +21,11 @@ Non-type annotations Keyword-only arguments Keyword Arguments Should Be 5 * kwo: int with_default: str = value + +Return type + Keyword Arguments Should Be 6 + Return Type Should Be 6 int + +Return type as tuple + Keyword Arguments Should Be 7 arg: int + Return Type Should Be 7 Union int float diff --git a/atest/robot/output/LegacyOutputHelper.py b/atest/robot/output/LegacyOutputHelper.py new file mode 100644 index 00000000000..6c70119fb5e --- /dev/null +++ b/atest/robot/output/LegacyOutputHelper.py @@ -0,0 +1,13 @@ +import re + + +def mask_changing_parts(path): + with open(path, encoding='UTF-8') as file: + content = file.read() + for pattern, replace in [ + (r'"20\d{6} \d{2}:\d{2}:\d{2}\.\d{3}"', '"[timestamp]"'), + (r'generator=".*?"', 'generator="[generator]"'), + (r'source=".*?"', 'source="[source]"') + ]: + content = re.sub(pattern, replace, content) + return content diff --git a/atest/robot/output/expand_keywords.robot b/atest/robot/output/expand_keywords.robot index 931b4283e9f..475584c25ca 100644 --- a/atest/robot/output/expand_keywords.robot +++ b/atest/robot/output/expand_keywords.robot @@ -34,13 +34,18 @@ Tag as pattern Keywords with skip status are expanded s1-s9-t1-k2 s1-s9-t2-k2-k1 # NAME:BuiltIn.Skip +Keywords with fail status are expanded + [Documentation] Expanding happens regardless is test skipped or not. + s1-s1-t2-k2 s1-s2-t7-k1 s1-s7-t1-k1-k1-k1-k1-k1-k1 # NAME:BuiltIn.Fail + *** Keywords *** Run tests with expanding ${options} = Catenate ... --log log.html + ... --skiponfailure fail ... --expandkeywords name:MyKeyword ... --ExpandKeywords NAME:BuiltIn.Sleep - ... --ExpandKeywords NAME:BuiltIn.Fail # Failed and not run keywords aren't expanded so this doesn't match anything. + ... --ExpandKeywords NAME:BuiltIn.Fail ... --ExpandKeywords NAME:BuiltIn.Skip ... --expand "Name:???-Ä* K?ywörd Näm?" ... --expandkeywords name:NO diff --git a/atest/robot/output/flatten_keyword.robot b/atest/robot/output/flatten_keyword.robot index 08b41ff7ef5..fb9a6b5e3c1 100644 --- a/atest/robot/output/flatten_keyword.robot +++ b/atest/robot/output/flatten_keyword.robot @@ -9,153 +9,136 @@ ${FLATTEN} --FlattenKeywords NAME:Keyword3 ... --flat TAG:flattenNOTkitty ... --flatten "name:Flatten controls in keyword" ... --log log.html -${FLAT TEXT} _*Content flattened.*_ -${FLAT HTML}

      Content flattened.\\x3c/b>\\x3c/i>\\x3c/p> +${FLATTENED} Content flattened. ${ERROR} [ ERROR ] Invalid value for option '--flattenkeywords': Expected 'FOR', 'WHILE', 'ITERATION', 'TAG:' or 'NAME:', got 'invalid'.${USAGE TIP}\n *** Test Cases *** Non-matching keyword is not flattened - Should Be Equal ${TC.kws[0].doc} Doc of keyword 2 - Length Should Be ${TC.kws[0].kws} 2 - Length Should Be ${TC.kws[0].msgs} 0 - Check Log Message ${TC.kws[0].kws[0].msgs[0]} 2 - Check Log Message ${TC.kws[0].kws[1].kws[0].msgs[0]} 1 + Should Be Equal ${TC[0].message} ${EMPTY} + Should Be Equal ${TC[0].doc} Doc of keyword 2 + Check Counts ${TC[0]} 0 2 + Check Log Message ${TC[0, 0, 0]} 2 + Check Log Message ${TC[0, 1, 1, 0]} 1 Exact match - Should Be Equal ${TC.kws[1].doc} Doc of keyword 3\n\n${FLAT TEXT} - Length Should Be ${TC.kws[1].kws} 0 - Length Should Be ${TC.kws[1].msgs} 3 - Check Log Message ${TC.kws[1].msgs[0]} 3 - Check Log Message ${TC.kws[1].msgs[1]} 2 - Check Log Message ${TC.kws[1].msgs[2]} 1 + Should Be Equal ${TC[1].message} *HTML* ${FLATTENED} + Should Be Equal ${TC[1].doc} Doc of keyword 3 + Check Counts ${TC[1]} 3 + Check Log Message ${TC[1, 0]} 3 + Check Log Message ${TC[1, 1]} 2 + Check Log Message ${TC[1, 2]} 1 Pattern match - Should Be Equal ${TC.kws[2].doc} ${FLAT TEXT} - Length Should Be ${TC.kws[2].kws} 0 - Length Should Be ${TC.kws[2].msgs} 6 - Check Log Message ${TC.kws[2].msgs[0]} 3 - Check Log Message ${TC.kws[2].msgs[1]} 2 - Check Log Message ${TC.kws[2].msgs[2]} 1 - Check Log Message ${TC.kws[2].msgs[3]} 2 - Check Log Message ${TC.kws[2].msgs[4]} 1 - Check Log Message ${TC.kws[2].msgs[5]} 1 - -Tag match when keyword has documentation - Should Be Equal ${TC.kws[5].doc} Doc of flat keyword.\n\n${FLAT TEXT} - Length Should Be ${TC.kws[5].kws} 0 - Length Should Be ${TC.kws[5].msgs} 1 - -Tag match when keyword has no documentation - Should Be Equal ${TC.kws[6].doc} ${FLAT TEXT} - Length Should Be ${TC.kws[6].kws} 0 - Length Should Be ${TC.kws[6].msgs} 1 + Should Be Equal ${TC[2].message} *HTML* ${FLATTENED} + Should Be Equal ${TC[2].doc} ${EMPTY} + Check Counts ${TC[2]} 6 + Check Log Message ${TC[2, 0]} 3 + Check Log Message ${TC[2, 1]} 2 + Check Log Message ${TC[2, 2]} 1 + Check Log Message ${TC[2, 3]} 2 + Check Log Message ${TC[2, 4]} 1 + Check Log Message ${TC[2, 5]} 1 + +Tag match when keyword has no message + Should Be Equal ${TC[5].message} *HTML* ${FLATTENED} + Should Be Equal ${TC[5].doc} ${EMPTY} + Check Counts ${TC[5]} 1 + +Tag match when keyword has message + Should Be Equal ${TC[6].message} *HTML* Expected e&<aped failure!


      ${FLATTENED} + Should Be Equal ${TC[6].doc} Doc of flat keyword. + Check Counts ${TC[6]} 1 Match full name - Should Be Equal ${TC.kws[3].doc} Logs the given message with the given level.\n\n${FLAT TEXT} - Length Should Be ${TC.kws[3].kws} 0 - Length Should Be ${TC.kws[3].msgs} 1 - Check Log Message ${TC.kws[3].msgs[0]} Flatten me too!! + Should Be Equal ${TC[3].message} *HTML* ${FLATTENED} + Should Be Equal ${TC[3].doc} Logs the given message with the given level. + Check Counts ${TC[3]} 1 + Check Log Message ${TC[3, 0]} Flatten me too!! Flattened in log after execution - Should Contain X Times ${LOG} Doc of keyword 3 1 - Should Contain X Times ${LOG} Doc of keyword 2 1 - Should Contain X Times ${LOG} Doc of keyword 1 1 - Should Contain X Times ${LOG} ${FLAT HTML} 6 - Should Contain ${LOG} *

      Doc of keyword 3\\x3c/p>\\n${FLAT HTML} - Should Contain ${LOG} *${FLAT HTML} - Should Contain ${LOG} *

      Logs the given message with the given level.\\x3c/p>\\n${FLAT HTML} + Should Contain ${LOG} "*Content flattened." Flatten controls in keyword ${tc} = Check Test Case ${TEST NAME} - Length Should Be ${tc.body[0].body.filter(messages=False)} 0 - Length Should Be ${tc.body[0].body.filter(messages=True)} 23 - Length Should Be ${tc.body[0].body} 23 + Check Counts ${tc[0]} 23 @{expected} = Create List ... Outside IF Inside IF 1 Nested IF ... 3 2 1 BANG! ... FOR: 0 1 FOR: 1 1 FOR: 2 1 ... WHILE: 2 1 \${i} = 1 WHILE: 1 1 \${i} = 0 - FOR ${msg} ${exp} IN ZIP ${tc.body[0].body} ${expected} - Check Log Message ${msg} ${exp} + ... AssertionError 1 finally + FOR ${msg} ${exp} IN ZIP ${tc[0].body} ${expected} + Check Log Message ${msg} ${exp} level=IGNORE END - Check log message ${tc.body[0].body[20]} AssertionError level=FAIL - Check log message ${tc.body[0].body[21]} 1 - Check log message ${tc.body[0].body[22]} finally -Flatten for loops +Flatten FOR Run Rebot --flatten For ${OUTFILE COPY} - ${tc} = Check Test Case For loop - Should Be Equal ${tc.kws[0].type} FOR - Should Be Equal ${tc.kws[0].doc} ${FLAT TEXT} - Length Should Be ${tc.kws[0].kws} 0 - Length Should Be ${tc.kws[0].msgs} 60 + ${tc} = Check Test Case FOR loop + Should Be Equal ${tc[0].type} FOR + Should Be Equal ${tc[0].message} *HTML* ${FLATTENED} + Check Counts ${tc[0]} 60 FOR ${index} IN RANGE 10 - Check Log Message ${tc.kws[0].msgs[${index * 6 + 0}]} index: ${index} - Check Log Message ${tc.kws[0].msgs[${index * 6 + 1}]} 3 - Check Log Message ${tc.kws[0].msgs[${index * 6 + 2}]} 2 - Check Log Message ${tc.kws[0].msgs[${index * 6 + 3}]} 1 - Check Log Message ${tc.kws[0].msgs[${index * 6 + 4}]} 2 - Check Log Message ${tc.kws[0].msgs[${index * 6 + 5}]} 1 + Check Log Message ${tc[0, ${index * 6 + 0}]} index: ${index} + Check Log Message ${tc[0, ${index * 6 + 1}]} 3 + Check Log Message ${tc[0, ${index * 6 + 2}]} 2 + Check Log Message ${tc[0, ${index * 6 + 3}]} 1 + Check Log Message ${tc[0, ${index * 6 + 4}]} 2 + Check Log Message ${tc[0, ${index * 6 + 5}]} 1 END -Flatten for loop iterations +Flatten FOR iterations Run Rebot --flatten ForItem ${OUTFILE COPY} - ${tc} = Check Test Case For loop - Should Be Equal ${tc.kws[0].type} FOR - Should Be Empty ${tc.kws[0].doc} - Length Should Be ${tc.kws[0].kws} 10 - Should Be Empty ${tc.kws[0].msgs} + ${tc} = Check Test Case FOR loop + Should Be Equal ${tc[0].type} FOR + Should Be Equal ${tc[0].message} ${EMPTY} + Check Counts ${tc[0]} 0 10 FOR ${index} IN RANGE 10 - Should Be Equal ${tc.kws[0].kws[${index}].type} ITERATION - Should Be Equal ${tc.kws[0].kws[${index}].doc} ${FLAT TEXT} - Should Be Empty ${tc.kws[0].kws[${index}].kws} - Length Should Be ${tc.kws[0].kws[${index}].msgs} 6 - Check Log Message ${tc.kws[0].kws[${index}].msgs[0]} index: ${index} - Check Log Message ${tc.kws[0].kws[${index}].msgs[1]} 3 - Check Log Message ${tc.kws[0].kws[${index}].msgs[2]} 2 - Check Log Message ${tc.kws[0].kws[${index}].msgs[3]} 1 - Check Log Message ${tc.kws[0].kws[${index}].msgs[4]} 2 - Check Log Message ${tc.kws[0].kws[${index}].msgs[5]} 1 + Should Be Equal ${tc[0, ${index}].type} ITERATION + Should Be Equal ${tc[0, ${index}].message} *HTML* ${FLATTENED} + Check Counts ${tc[0, ${index}]} 6 + Check Log Message ${tc[0, ${index}, 0]} index: ${index} + Check Log Message ${tc[0, ${index}, 1]} 3 + Check Log Message ${tc[0, ${index}, 2]} 2 + Check Log Message ${tc[0, ${index}, 3]} 1 + Check Log Message ${tc[0, ${index}, 4]} 2 + Check Log Message ${tc[0, ${index}, 5]} 1 END -Flatten while loops +Flatten WHILE Run Rebot --flatten WHile ${OUTFILE COPY} ${tc} = Check Test Case WHILE loop - Should Be Equal ${tc.body[1].type} WHILE - Should Be Equal ${tc.body[1].doc} ${FLAT TEXT} - Length Should Be ${tc.body[1].kws} 0 - Length Should Be ${tc.body[1].msgs} 70 + Should Be Equal ${tc[1].type} WHILE + Should Be Equal ${tc[1].message} *HTML* ${FLATTENED} + Check Counts ${tc[1]} 70 FOR ${index} IN RANGE 10 - Check Log Message ${tc.body[1].msgs[${index * 7 + 0}]} index: ${index} - Check Log Message ${tc.body[1].msgs[${index * 7 + 1}]} 3 - Check Log Message ${tc.body[1].msgs[${index * 7 + 2}]} 2 - Check Log Message ${tc.body[1].msgs[${index * 7 + 3}]} 1 - Check Log Message ${tc.body[1].msgs[${index * 7 + 4}]} 2 - Check Log Message ${tc.body[1].msgs[${index * 7 + 5}]} 1 + Check Log Message ${tc[1, ${index * 7 + 0}]} index: ${index} + Check Log Message ${tc[1, ${index * 7 + 1}]} 3 + Check Log Message ${tc[1, ${index * 7 + 2}]} 2 + Check Log Message ${tc[1, ${index * 7 + 3}]} 1 + Check Log Message ${tc[1, ${index * 7 + 4}]} 2 + Check Log Message ${tc[1, ${index * 7 + 5}]} 1 ${i}= Evaluate $index + 1 - Check Log Message ${tc.body[1].msgs[${index * 7 + 6}]} \${i} = ${i} + Check Log Message ${tc[1, ${index * 7 + 6}]} \${i} = ${i} END -Flatten while loop iterations +Flatten WHILE iterations Run Rebot --flatten iteration ${OUTFILE COPY} ${tc} = Check Test Case WHILE loop - Should Be Equal ${tc.body[1].type} WHILE - Should Be Empty ${tc.body[1].doc} - Length Should Be ${tc.body[1].body} 10 - Should Be Empty ${tc.body[1].msgs} + Should Be Equal ${tc[1].type} WHILE + Should Be Equal ${tc[1].message} ${EMPTY} + Check Counts ${tc[1]} 0 10 FOR ${index} IN RANGE 10 - Should Be Equal ${tc.kws[1].kws[${index}].type} ITERATION - Should Be Equal ${tc.kws[1].kws[${index}].doc} ${FLAT TEXT} - Should Be Empty ${tc.kws[1].kws[${index}].kws} - Length Should Be ${tc.kws[1].kws[${index}].msgs} 7 - Check Log Message ${tc.kws[1].kws[${index}].msgs[0]} index: ${index} - Check Log Message ${tc.kws[1].kws[${index}].msgs[1]} 3 - Check Log Message ${tc.kws[1].kws[${index}].msgs[2]} 2 - Check Log Message ${tc.kws[1].kws[${index}].msgs[3]} 1 - Check Log Message ${tc.kws[1].kws[${index}].msgs[4]} 2 - Check Log Message ${tc.kws[1].kws[${index}].msgs[5]} 1 + Should Be Equal ${tc[1, ${index}].type} ITERATION + Should Be Equal ${tc[1, ${index}].message} *HTML* ${FLATTENED} + Check Counts ${tc[1, ${index}]} 7 + Check Log Message ${tc[1, ${index}, 0]} index: ${index} + Check Log Message ${tc[1, ${index}, 1]} 3 + Check Log Message ${tc[1, ${index}, 2]} 2 + Check Log Message ${tc[1, ${index}, 3]} 1 + Check Log Message ${tc[1, ${index}, 4]} 2 + Check Log Message ${tc[1, ${index}, 5]} 1 ${i}= Evaluate $index + 1 - Check Log Message ${tc.kws[1].kws[${index}].msgs[6]} \${i} = ${i} + Check Log Message ${tc[1, ${index}, 6]} \${i} = ${i} END Invalid usage @@ -173,3 +156,8 @@ Run And Rebot Flattened Run Rebot ${FLATTEN} ${OUTFILE COPY} ${TC} = Check Test Case Flatten stuff Set Suite Variable $TC + +Check Counts + [Arguments] ${item} ${messages} ${non_messages}=0 + Length Should Be ${item.messages} ${messages} + Length Should Be ${item.non_messages} ${non_messages} diff --git a/atest/robot/output/js_model.robot b/atest/robot/output/js_model.robot index 9c63ece6380..bfdb0d6e3c2 100644 --- a/atest/robot/output/js_model.robot +++ b/atest/robot/output/js_model.robot @@ -44,4 +44,4 @@ Get JS model ${file} = Get File ${OUTDIR}/${type}.html ${strings} = Get Lines Matching Pattern ${file} window.output?"strings"?* ${settings} = Get Lines Matching Pattern ${file} window.settings =* - [Return] ${strings} ${settings} + RETURN ${strings} ${settings} diff --git a/atest/robot/output/json_output.robot b/atest/robot/output/json_output.robot new file mode 100644 index 00000000000..d703bf2b8ec --- /dev/null +++ b/atest/robot/output/json_output.robot @@ -0,0 +1,42 @@ +*** Settings *** +Documentation JSON output is tested in detailed level using unit tests. +Resource atest_resource.robot + +*** Variables *** +${JSON} %{TEMPDIR}/output.json +${XML} %{TEMPDIR}/output.xml + +*** Test Cases *** +JSON output contains same suite information as XML output + Run Tests ${EMPTY} misc + Copy File ${OUTFILE} ${XML} + Run Tests Without Processing Output -o ${JSON} misc + Outputs Should Contain Same Data ${JSON} ${XML} ignore_timestamps=True + +JSON output structure + [Documentation] Full JSON schema validation would be good, but it's too slow with big output files. + ... The test after this one validates a smaller suite against a schema. + ${data} = Evaluate json.load(open($JSON, encoding='UTF-8')) + Lists Should Be Equal ${data} ${{['generator', 'generated', 'rpa', 'suite', 'statistics', 'errors']}} + Should Match ${data}[generator] Robot ?.* (* on *) + Should Match ${data}[generated] 20??-??-??T??:??:??.?????? + Should Be Equal ${data}[rpa] ${False} + Should Be Equal ${data}[suite][name] Misc + Should Be Equal ${data}[suite][suites][1][name] Everything + Should Be Equal ${data}[statistics][total][skip] ${3} + Should Be Equal ${data}[statistics][tags][4][label] f1 + Should Be Equal ${data}[statistics][suites][-1][id] s1-s17 + Should Be Equal ${data}[errors][0][level] ERROR + +JSON output matches schema + [Tags] require-jsonschema + Run Tests Without Processing Output -o OUT.JSON misc/everything.robot + Validate JSON Output ${OUTDIR}/OUT.JSON + +Invalid JSON output file + ${path} = Normalize Path ${JSON} + Remove File ${path} + Create Directory ${path} + Run Tests Without Processing Output -o ${path} misc/pass_and_fail.robot + Stderr Should Match [[] ERROR ] Opening output file '${path}' failed: *${USAGE TIP}\n + [Teardown] Remove Directory ${JSON} diff --git a/atest/robot/output/legacy_output.robot b/atest/robot/output/legacy_output.robot new file mode 100644 index 00000000000..017cf0cc68a --- /dev/null +++ b/atest/robot/output/legacy_output.robot @@ -0,0 +1,28 @@ +*** Settings *** +Library LegacyOutputHelper.py +Resource atest_resource.robot + +*** Test Cases *** +Legacy output with Robot + Run Tests --legacyoutput output/legacy.robot validate output=False + Validate output + +Legacy output with Rebot + Run Tests ${EMPTY} output/legacy.robot + Copy Previous Outfile + Run Rebot --legacy-output ${OUTFILE COPY} validate output=False + Validate output + +Legacy output with Rebot when all times are not set + Run Rebot --legacy-output --test Passing ${OUTFILE COPY} validate output=False + Should Be Equal ${SUITE.start_time} ${None} + Should Be Equal ${SUITE.end_time} ${None} + Should Contain Tests ${SUITE} Passing + +*** Keywords *** +Validate output + Should Contain Tests ${SUITE} Passing Failing Failing setup + ... Failing teardown Controls Embedded Warning + ${output} = Mask Changing Parts ${OUTFILE} + ${expected} = Mask Changing Parts ${DATADIR}/output/legacy.xml + Elements Should Be Equal ${output} ${expected} sort_children=True diff --git a/atest/robot/output/listener_interface/body_items_v3.robot b/atest/robot/output/listener_interface/body_items_v3.robot new file mode 100644 index 00000000000..fab0a6ee538 --- /dev/null +++ b/atest/robot/output/listener_interface/body_items_v3.robot @@ -0,0 +1,75 @@ +*** Settings *** +Suite Setup Run Tests --listener ${DATADIR}/${MODIFIER} ${SOURCE} +Resource atest_resource.robot + +*** Variables *** +${SOURCE} output/listener_interface/body_items_v3/tests.robot +${MODIFIER} output/listener_interface/body_items_v3/Modifier.py +@{ALL TESTS} Library keyword User keyword Non-existing keyword +... Empty keyword Duplicate keyword Invalid keyword +... IF TRY FOR WHILE WHILE with modified limit VAR RETURN +... Invalid syntax Run Keyword + +*** Test Cases *** +Modify library keyword + Check Test Case Library keyword FAIL Expected state to be 'initial', but it was 'set by listener'. + +Modify user keyword + Check Test Case User keyword FAIL Failed by listener once! + Check Test Case Empty keyword PASS ${EMPTY} + +Modify invalid keyword + Check Test Case Non-existing keyword PASS ${EMPTY} + Check Test Case Duplicate keyword PASS ${EMPTY} + Check Test Case Invalid keyword PASS ${EMPTY} + +Modify keyword results + ${tc} = Get Test Case Invalid keyword + Check Keyword Data ${tc[0]} Invalid keyword + ... args=\${secret} + ... tags=end, fixed, start + ... doc=Results can be modified both in start and end! + +Modify FOR + ${tc} = Check Test Case FOR FAIL Listener failed me at 'b'! + Length Should Be ${tc[0].body} 2 + Should Be Equal ${tc[0].assign}[0] secret + Should Be Equal ${tc[0, 0].assign}[\${x}] xxx + Should Be Equal ${tc[0, 1].assign}[\${x}] xxx + +Modify WHILE + ${tc} = Check Test Case WHILE FAIL Fail at iteration 10. + Length Should Be ${tc[0].body} 10 + +Modify WHILE limit + ${tc} = Check Test Case WHILE with modified limit PASS ${EMPTY} + Length Should Be ${tc[1].body} 3 + Check Log Message ${tc[1, 0, 0, 0]} \${x} = 1 + Check Log Message ${tc[1, 1, 0, 0]} \${x} = 2 + Check Log Message ${tc[1, 2]} Modified limit message. + +Modify IF + ${tc} = Check Test Case IF FAIL Executed! + Should Be Equal ${tc[0, 0].message} Secret message! + Should Be Equal ${tc[0, 1].message} Secret message! + Should Be Equal ${tc[0, 2].message} Executed! + +Modify TRY + ${tc} = Check Test Case TRY FAIL Not caught! + Length Should Be ${tc[0].body} 3 + +Modify VAR + ${tc} = Check Test Case VAR FAIL value != VAR by listener + Should Be Equal ${tc[0].value}[0] secret + Should Be Equal ${tc[1].value}[0] secret + +Modify RETURN + ${tc} = Check Test Case RETURN FAIL RETURN by listener != value + Should Be Equal ${tc[0, 1].values}[0] secret + +Validate that all methods are called correctly + Run Tests --variable VALIDATE_EVENTS:True ${SOURCE} + Should contain tests ${SUITE} @{ALL TESTS} + Check Log Message ${SUITE.teardown.messages[0]} Listener StartEndBobyItemOnly is OK. + Check Log Message ${SUITE.teardown.messages[1]} Listener SeparateMethods is OK. + Check Log Message ${SUITE.teardown.messages[2]} Listener SeparateMethodsAlsoForKeywords is OK. diff --git a/atest/robot/output/listener_interface/change_status.robot b/atest/robot/output/listener_interface/change_status.robot new file mode 100644 index 00000000000..be97fe5db3f --- /dev/null +++ b/atest/robot/output/listener_interface/change_status.robot @@ -0,0 +1,73 @@ +*** Settings *** +Suite Setup Run Tests --listener ${DATADIR}/${MODIFIER} ${SOURCE} +Resource atest_resource.robot + +*** Variables *** +${SOURCE} output/listener_interface/body_items_v3/change_status.robot +${MODIFIER} output/listener_interface/body_items_v3/ChangeStatus.py + +*** Test Cases *** +Fail to pass + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Fail args=Pass me! status=PASS message=Failure hidden! + Check Log Message ${tc[0, 0]} Pass me! level=FAIL + Check Keyword Data ${tc[1]} BuiltIn.Log args=I'm run. status=PASS message= + +Pass to fail + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Log args=Fail me! status=FAIL message=Ooops!! + Check Log Message ${tc[0, 0]} Fail me! level=INFO + Check Keyword Data ${tc[1]} BuiltIn.Log args=I'm not run. status=NOT RUN message= + +Pass to fail without a message + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Log args=Silent fail! status=FAIL message= + Check Keyword Data ${tc[1]} BuiltIn.Log args=I'm not run. status=NOT RUN message= + +Skip to fail + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Skip args=Fail me! status=FAIL message=Failing! + Check Log Message ${tc[0, 0]} Fail me! level=SKIP + Check Keyword Data ${tc[1]} BuiltIn.Log args=I'm not run. status=NOT RUN message= + +Fail to skip + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Fail args=Skip me! status=SKIP message=Skipping! + Check Log Message ${tc[0, 0]} Skip me! level=FAIL + Check Keyword Data ${tc[1]} BuiltIn.Log args=I'm not run. status=NOT RUN message= + +Not run to fail + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Log args=Fail me! status=FAIL message=Ooops!! + Check Keyword Data ${tc[1]} BuiltIn.Log args=I'm not run. status=NOT RUN message= + Check Keyword Data ${tc[2]} BuiltIn.Log args=Fail me! status=FAIL message=Failing without running! + Check Keyword Data ${tc[3]} BuiltIn.Log args=I'm not run. status=NOT RUN message= + +Pass and fail to not run + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Log args=Mark not run! status=NOT RUN message= + Check Keyword Data ${tc[1]} BuiltIn.Fail args=Mark not run! status=NOT RUN message=Mark not run! + Check Keyword Data ${tc[2]} BuiltIn.Fail args=I fail! status=FAIL message=I fail! + +Only message + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Fail args=Change me! status=FAIL message=Changed! + Check Keyword Data ${tc[1]} Change message status=NOT RUN message=Changed! + +Control structures + ${tc} = Check Test Case ${TEST NAME} + Check Control Structure ${tc[0]} FOR + Check Control Structure ${tc[1]} WHILE + Check Control Structure ${tc[2]} IF/ELSE ROOT + Check Control Structure ${tc[3]} TRY/EXCEPT ROOT + +*** Keywords *** +Check Control Structure + [Arguments] ${item} ${type} + VAR ${msg} Handled on ${type} level. + Should Be Equal ${item.type} ${type} + Should Be Equal ${item.status} PASS + Should Be Equal ${item.message} ${msg} + Should Be Equal ${item[0].status} FAIL + Should Be Equal ${item[0].message} ${msg} + Check Keyword Data ${item[0, 0]} BuiltIn.Fail args=${msg} status=FAIL message=${msg} diff --git a/atest/robot/output/listener_interface/importing_listeners.robot b/atest/robot/output/listener_interface/importing_listeners.robot index cd82a6b0416..f50534abe50 100644 --- a/atest/robot/output/listener_interface/importing_listeners.robot +++ b/atest/robot/output/listener_interface/importing_listeners.robot @@ -14,6 +14,15 @@ Python Class Listener From A Module With Different Name Python Module Listener module module_listener module_listener +Listener Versions + [Template] NONE + Check Listener File listener-versions.txt + ... V2 + ... V2AsNonInt + ... V3Implicit + ... V3Explicit + ... V3AsNonInt + Listener With Arguments class listeners.WithArgs listeners 6 [Teardown] Check Listener File ${ARGS_FILE} @@ -27,23 +36,33 @@ Listener With Argument Conversion Listener With Path class ${LISTENERS}${/}ListenAll.py ListenAll - [Teardown] File Should Exist %{TEMPDIR}${/}${ALL_FILE2} + [Teardown] File Should Exist %{TEMPDIR}${/}${ALL_FILE2} Listener With Wrong Number Of Arguments [Template] Importing Listener Failed 0 listeners.WithArgs Listener 'WithArgs' expected 1 to 2 arguments, got 0. 1 listeners.WithArgs:1:2:3 Listener 'WithArgs' expected 1 to 2 arguments, got 3. - Non Existing Listener [Template] Importing Listener Failed 2 NonExistingListener *${EMPTY TB}PYTHONPATH:* pattern=True +Unsupported version + [Template] Taking Listener Into Use Failed + 3 unsupported_listeners.V1Listener Unsupported API version '1'. + 4 unsupported_listeners.V4Listener Unsupported API version '4'. + 5 unsupported_listeners.InvalidVersionListener Unsupported API version 'kekkonen'. + *** Keywords *** Run Tests With Listeners ${listeners} = Catenate ... --listener ListenAll ... --listener listeners.ListenSome ... --listener module_listener + ... --listener listener_versions.V2 + ... --listener listener_versions.V2AsNonInt + ... --listener listener_versions.V3Implicit + ... --listener listener_versions.V3Explicit + ... --listener listener_versions.V3AsNonInt ... --listener listeners.WithArgs:value ... --listener "listeners.WithArgs:a1:a;2" ... --listener "listeners.WithArgs;semi;colons:here" @@ -53,11 +72,19 @@ Run Tests With Listeners ... --listener listeners.WithArgs ... --listener listeners.WithArgs:1:2:3 ... --listener NonExistingListener + ... --listener unsupported_listeners.V1Listener + ... --listener unsupported_listeners.V4Listener + ... --listener unsupported_listeners.InvalidVersionListener Run Tests ${listeners} misc/pass_and_fail.robot Importing Listener Failed + [Arguments] ${index} ${name} ${error} ${pattern}=False + VAR ${error} Importing listener '${name.split(':')[0]}' failed: ${error} + Taking Listener Into Use Failed ${index} ${name} ${error} ${pattern} + +Taking Listener Into Use Failed [Arguments] ${index} ${name} ${error} ${pattern}=False Check Log Message ... ${ERRORS}[${index}] - ... Taking listener '${name}' into use failed: Importing listener '${name.split(':')[0]}' failed: ${error} + ... Taking listener '${name}' into use failed: ${error} ... ERROR pattern=${pattern} diff --git a/atest/robot/output/listener_interface/keyword_arguments_v3.robot b/atest/robot/output/listener_interface/keyword_arguments_v3.robot new file mode 100644 index 00000000000..09b8b7d26b1 --- /dev/null +++ b/atest/robot/output/listener_interface/keyword_arguments_v3.robot @@ -0,0 +1,52 @@ +*** Settings *** +Suite Setup Run Tests --listener ${DATADIR}/${MODIFIER} ${SOURCE} +Resource atest_resource.robot + +*** Variables *** +${SOURCE} output/listener_interface/body_items_v3/keyword_arguments.robot +${MODIFIER} output/listener_interface/body_items_v3/ArgumentModifier.py + +*** Test Cases *** +Library keyword arguments + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} Library.Library Keyword + ... args=\${STATE}, number=\${123}, obj=None, escape=c:\\\\temp\\\\new + Check Keyword Data ${tc[1]} Library.Library Keyword + ... args=new, 123, c:\\\\temp\\\\new, NONE + Check Keyword Data ${tc[2]} Library.Library Keyword + ... args=new, number=\${42}, escape=c:\\\\temp\\\\new, obj=Object(42) + Check Keyword Data ${tc[3]} Library.Library Keyword + ... args=number=1.0, escape=c:\\\\temp\\\\new, obj=Object(1), state=new + +User keyword arguments + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} User keyword + ... args=A, B, C, D + Check Keyword Data ${tc[1]} User keyword + ... args=A, B, d=D, c=\${{"c".upper()}} + +Invalid keyword arguments + ${tc} = Check Test Case Library keyword arguments + Check Keyword Data ${tc[4]} Non-existing + ... args=p, n=1 status=FAIL + +Too many arguments + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} Library.Library Keyword + ... args=a, b, c, d, e, f, g status=FAIL + Check Keyword Data ${tc[1]} User keyword + ... args=a, b, c, d, e, f, g status=FAIL + Check Keyword Data ${tc[2]} Library.Library Keyword + ... args=${{', '.join(str(i) for i in range(100))}} status=FAIL + +Conversion error + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} Library.Library Keyword + ... args=whatever, not a number status=FAIL + Check Keyword Data ${tc[1]} Library.Library Keyword + ... args=number=bad status=FAIL + +Positional after named + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} Library.Library Keyword + ... args=positional, number=-1, ooops status=FAIL diff --git a/atest/robot/output/listener_interface/lineno_and_source.robot b/atest/robot/output/listener_interface/lineno_and_source.robot index 2214c99a763..cc61cbe667d 100644 --- a/atest/robot/output/listener_interface/lineno_and_source.robot +++ b/atest/robot/output/listener_interface/lineno_and_source.robot @@ -12,206 +12,254 @@ ${RESOURCE FILE} ${LISTENER DIR}/lineno_and_source.resource *** Test Cases *** Keyword START KEYWORD No Operation 6 NOT SET - END KEYWORD No Operation 6 PASS + \END KEYWORD No Operation 6 PASS User keyword - START KEYWORD User Keyword 9 NOT SET - START KEYWORD No Operation 85 NOT SET - END KEYWORD No Operation 85 PASS - START RETURN ${EMPTY} 86 NOT SET - END RETURN ${EMPTY} 86 PASS - END KEYWORD User Keyword 9 PASS + START KEYWORD User Keyword 9 NOT SET + START KEYWORD No Operation 101 NOT SET + \END KEYWORD No Operation 101 PASS + START RETURN ${EMPTY} 102 NOT SET + \END RETURN ${EMPTY} 102 PASS + \END KEYWORD User Keyword 9 PASS User keyword in resource START KEYWORD User Keyword In Resource 12 NOT SET START KEYWORD No Operation 3 NOT SET source=${RESOURCE FILE} - END KEYWORD No Operation 3 PASS source=${RESOURCE FILE} - END KEYWORD User Keyword In Resource 12 PASS + \END KEYWORD No Operation 3 PASS source=${RESOURCE FILE} + \END KEYWORD User Keyword In Resource 12 PASS Not run keyword START KEYWORD Fail 16 NOT SET - END KEYWORD Fail 16 FAIL + \END KEYWORD Fail 16 FAIL START KEYWORD Fail 17 NOT RUN - END KEYWORD Fail 17 NOT RUN + \END KEYWORD Fail 17 NOT RUN START KEYWORD Non-existing 18 NOT RUN - END KEYWORD Non-existing 18 NOT RUN + \END KEYWORD Non-existing 18 NOT RUN FOR - START FOR \${x} IN [ first | second ] 21 NOT SET + START FOR \${x} IN first second 21 NOT SET START ITERATION \${x} = first 21 NOT SET START KEYWORD No Operation 22 NOT SET - END KEYWORD No Operation 22 PASS - END ITERATION \${x} = first 21 PASS + \END KEYWORD No Operation 22 PASS + \END ITERATION \${x} = first 21 PASS START ITERATION \${x} = second 21 NOT SET START KEYWORD No Operation 22 NOT SET - END KEYWORD No Operation 22 PASS - END ITERATION \${x} = second 21 PASS - END FOR \${x} IN [ first | second ] 21 PASS + \END KEYWORD No Operation 22 PASS + \END ITERATION \${x} = second 21 PASS + \END FOR \${x} IN first second 21 PASS FOR in keyword - START KEYWORD FOR In Keyword 26 NOT SET - START FOR \${x} IN [ once ] 89 NOT SET - START ITERATION \${x} = once 89 NOT SET - START KEYWORD No Operation 90 NOT SET - END KEYWORD No Operation 90 PASS - END ITERATION \${x} = once 89 PASS - END FOR \${x} IN [ once ] 89 PASS - END KEYWORD FOR In Keyword 26 PASS + START KEYWORD FOR In Keyword 26 NOT SET + START FOR \${x} IN once 105 NOT SET + START ITERATION \${x} = once 105 NOT SET + START KEYWORD No Operation 106 NOT SET + \END KEYWORD No Operation 106 PASS + \END ITERATION \${x} = once 105 PASS + \END FOR \${x} IN once 105 PASS + \END KEYWORD FOR In Keyword 26 PASS FOR in IF START IF True 29 NOT SET - START FOR \${x} | \${y} IN [ x | y ] 30 NOT SET + START FOR \${x} \${y} IN x y 30 NOT SET START ITERATION \${x} = x, \${y} = y 30 NOT SET START KEYWORD No Operation 31 NOT SET - END KEYWORD No Operation 31 PASS - END ITERATION \${x} = x, \${y} = y 30 PASS - END FOR \${x} | \${y} IN [ x | y ] 30 PASS - END IF True 29 PASS + \END KEYWORD No Operation 31 PASS + \END ITERATION \${x} = x, \${y} = y 30 PASS + \END FOR \${x} \${y} IN x y 30 PASS + \END IF True 29 PASS FOR in resource START KEYWORD FOR In Resource 36 NOT SET - START FOR \${x} IN [ once ] 6 NOT SET source=${RESOURCE FILE} + START FOR \${x} IN once 6 NOT SET source=${RESOURCE FILE} START ITERATION \${x} = once 6 NOT SET source=${RESOURCE FILE} START KEYWORD Log 7 NOT SET source=${RESOURCE FILE} - END KEYWORD Log 7 PASS source=${RESOURCE FILE} - END ITERATION \${x} = once 6 PASS source=${RESOURCE FILE} - END FOR \${x} IN [ once ] 6 PASS source=${RESOURCE FILE} - END KEYWORD FOR In Resource 36 PASS + \END KEYWORD Log 7 PASS source=${RESOURCE FILE} + \END ITERATION \${x} = once 6 PASS source=${RESOURCE FILE} + \END FOR \${x} IN once 6 PASS source=${RESOURCE FILE} + \END KEYWORD FOR In Resource 36 PASS IF - START IF 1 > 2 39 NOT RUN - START KEYWORD Fail 40 NOT RUN - END KEYWORD Fail 40 NOT RUN - END IF 1 > 2 39 NOT RUN - START ELSE IF 1 < 2 41 NOT SET - START KEYWORD No Operation 42 NOT SET - END KEYWORD No Operation 42 PASS - END ELSE IF 1 < 2 41 PASS - START ELSE ${EMPTY} 43 NOT RUN - START KEYWORD Fail 44 NOT RUN - END KEYWORD Fail 44 NOT RUN - END ELSE ${EMPTY} 43 NOT RUN + START IF 1 > 2 39 NOT RUN + START KEYWORD Fail 40 NOT RUN + \END KEYWORD Fail 40 NOT RUN + \END IF 1 > 2 39 NOT RUN + START ELSE IF 1 < 2 41 NOT SET + START KEYWORD No Operation 42 NOT SET + \END KEYWORD No Operation 42 PASS + \END ELSE IF 1 < 2 41 PASS + START ELSE \ 43 NOT RUN + START KEYWORD Fail 44 NOT RUN + \END KEYWORD Fail 44 NOT RUN + \END ELSE \ 43 NOT RUN IF in keyword - START KEYWORD IF In Keyword 48 NOT SET - START IF True 94 NOT SET - START KEYWORD No Operation 95 NOT SET - END KEYWORD No Operation 95 PASS - START RETURN ${EMPTY} 96 NOT SET - END RETURN ${EMPTY} 96 PASS - END IF True 94 PASS - END KEYWORD IF In Keyword 48 PASS + START KEYWORD IF In Keyword 48 NOT SET + START IF True 110 NOT SET + START KEYWORD No Operation 111 NOT SET + \END KEYWORD No Operation 111 PASS + START RETURN ${EMPTY} 112 NOT SET + \END RETURN ${EMPTY} 112 PASS + \END IF True 110 PASS + \END KEYWORD IF In Keyword 48 PASS IF in FOR - START FOR \${x} IN [ 1 | 2 ] 52 NOT SET - START ITERATION \${x} = 1 52 NOT SET - START IF \${x} == 1 53 NOT SET - START KEYWORD Log 54 NOT SET - END KEYWORD Log 54 PASS - END IF \${x} == 1 53 PASS - START ELSE ${EMPTY} 55 NOT RUN - START KEYWORD Fail 56 NOT RUN - END KEYWORD Fail 56 NOT RUN - END ELSE ${EMPTY} 55 NOT RUN - END ITERATION \${x} = 1 52 PASS - START ITERATION \${x} = 2 52 NOT SET - START IF \${x} == 1 53 NOT RUN - START KEYWORD Log 54 NOT RUN - END KEYWORD Log 54 NOT RUN - END IF \${x} == 1 53 NOT RUN - START ELSE ${EMPTY} 55 NOT SET - START KEYWORD Fail 56 NOT SET - END KEYWORD Fail 56 FAIL - END ELSE ${EMPTY} 55 FAIL - END ITERATION \${x} = 2 52 FAIL - END FOR \${x} IN [ 1 | 2 ] 52 FAIL + START FOR \${x} IN 1 2 52 NOT SET + START ITERATION \${x} = 1 52 NOT SET + START IF \${x} == 1 53 NOT SET + START KEYWORD Log 54 NOT SET + \END KEYWORD Log 54 PASS + \END IF \${x} == 1 53 PASS + START ELSE \ 55 NOT RUN + START KEYWORD Fail 56 NOT RUN + \END KEYWORD Fail 56 NOT RUN + \END ELSE \ 55 NOT RUN + \END ITERATION \${x} = 1 52 PASS + START ITERATION \${x} = 2 52 NOT SET + START IF \${x} == 1 53 NOT RUN + START KEYWORD Log 54 NOT RUN + \END KEYWORD Log 54 NOT RUN + \END IF \${x} == 1 53 NOT RUN + START ELSE \ 55 NOT SET + START KEYWORD Fail 56 NOT SET + \END KEYWORD Fail 56 FAIL + \END ELSE \ 55 FAIL + \END ITERATION \${x} = 2 52 FAIL + \END FOR \${x} IN 1 2 52 FAIL IF in resource - START KEYWORD IF In Resource 61 NOT SET - START IF True 11 NOT SET source=${RESOURCE FILE} - START KEYWORD No Operation 12 NOT SET source=${RESOURCE FILE} - END KEYWORD No Operation 12 PASS source=${RESOURCE FILE} - END IF True 11 PASS source=${RESOURCE FILE} - END KEYWORD IF In Resource 61 PASS + START KEYWORD IF In Resource 61 NOT SET + START IF True 11 NOT SET source=${RESOURCE FILE} + START KEYWORD No Operation 12 NOT SET source=${RESOURCE FILE} + \END KEYWORD No Operation 12 PASS source=${RESOURCE FILE} + \END IF True 11 PASS source=${RESOURCE FILE} + \END KEYWORD IF In Resource 61 PASS TRY START TRY ${EMPTY} 65 NOT SET START KEYWORD Fail 66 NOT SET - END KEYWORD Fail 66 FAIL - END TRY ${EMPTY} 65 FAIL + \END KEYWORD Fail 66 FAIL + \END TRY ${EMPTY} 65 FAIL START EXCEPT AS \${name} 67 NOT SET START TRY ${EMPTY} 68 NOT SET START KEYWORD Fail 69 NOT SET - END KEYWORD Fail 69 FAIL - END TRY ${EMPTY} 68 FAIL + \END KEYWORD Fail 69 FAIL + \END TRY ${EMPTY} 68 FAIL START FINALLY ${EMPTY} 70 NOT SET START KEYWORD Should Be Equal 71 NOT SET - END KEYWORD Should Be Equal 71 PASS - END FINALLY ${EMPTY} 70 PASS - END EXCEPT AS \${name} 67 FAIL + \END KEYWORD Should Be Equal 71 PASS + \END FINALLY ${EMPTY} 70 PASS + \END EXCEPT AS \${name} 67 FAIL START ELSE ${EMPTY} 73 NOT RUN START KEYWORD Fail 74 NOT RUN - END KEYWORD Fail 74 NOT RUN - END ELSE ${EMPTY} 73 NOT RUN + \END KEYWORD Fail 74 NOT RUN + \END ELSE ${EMPTY} 73 NOT RUN TRY in keyword START KEYWORD TRY In Keyword 78 NOT SET - START TRY ${EMPTY} 100 NOT SET - START RETURN ${EMPTY} 101 NOT SET - END RETURN ${EMPTY} 101 PASS - START KEYWORD Fail 102 NOT RUN - END KEYWORD Fail 102 NOT RUN - END TRY ${EMPTY} 100 PASS - START EXCEPT No match AS \${var} 103 NOT RUN - START KEYWORD Fail 104 NOT RUN - END KEYWORD Fail 104 NOT RUN - END EXCEPT No match AS \${var} 103 NOT RUN - START EXCEPT No | Match | 2 AS \${x} 105 NOT RUN - START KEYWORD Fail 106 NOT RUN - END KEYWORD Fail 106 NOT RUN - END EXCEPT No | Match | 2 AS \${x} 105 NOT RUN - START EXCEPT ${EMPTY} 107 NOT RUN - START KEYWORD Fail 108 NOT RUN - END KEYWORD Fail 108 NOT RUN - END EXCEPT ${EMPTY} 107 NOT RUN - END KEYWORD TRY In Keyword 78 PASS + START TRY ${EMPTY} 116 NOT SET + START RETURN ${EMPTY} 117 NOT SET + \END RETURN ${EMPTY} 117 PASS + START KEYWORD Fail 118 NOT RUN + \END KEYWORD Fail 118 NOT RUN + \END TRY ${EMPTY} 116 PASS + START EXCEPT No match AS \${var} 119 NOT RUN + START KEYWORD Fail 120 NOT RUN + \END KEYWORD Fail 120 NOT RUN + \END EXCEPT No match AS \${var} 119 NOT RUN + START EXCEPT No Match 2 AS \${x} 121 NOT RUN + START KEYWORD Fail 122 NOT RUN + \END KEYWORD Fail 122 NOT RUN + \END EXCEPT No Match 2 AS \${x} 121 NOT RUN + START EXCEPT ${EMPTY} 123 NOT RUN + START KEYWORD Fail 124 NOT RUN + \END KEYWORD Fail 124 NOT RUN + \END EXCEPT ${EMPTY} 123 NOT RUN + \END KEYWORD TRY In Keyword 78 PASS TRY in resource START KEYWORD TRY In Resource 81 NOT SET START TRY ${EMPTY} 16 NOT SET source=${RESOURCE FILE} START KEYWORD Log 17 NOT SET source=${RESOURCE FILE} - END KEYWORD Log 17 PASS source=${RESOURCE FILE} - END TRY ${EMPTY} 16 PASS source=${RESOURCE FILE} + \END KEYWORD Log 17 PASS source=${RESOURCE FILE} + \END TRY ${EMPTY} 16 PASS source=${RESOURCE FILE} START FINALLY ${EMPTY} 18 NOT SET source=${RESOURCE FILE} START KEYWORD Log 19 NOT SET source=${RESOURCE FILE} - END KEYWORD Log 19 PASS source=${RESOURCE FILE} - END FINALLY ${EMPTY} 18 PASS source=${RESOURCE FILE} - END KEYWORD TRY In Resource 81 PASS + \END KEYWORD Log 19 PASS source=${RESOURCE FILE} + \END FINALLY ${EMPTY} 18 PASS source=${RESOURCE FILE} + \END KEYWORD TRY In Resource 81 PASS -Test - [Template] Expect test - Keyword 5 - User keyword 8 - User keyword in resource 11 - Not run keyword 14 FAIL - \FOR 20 - FOR in keyword 25 - FOR in IF 28 - FOR in resource 35 - \IF 38 - IF in keyword 47 - IF in FOR 50 FAIL - IF in resource 60 - \TRY 63 FAIL - TRY in keyword 77 - TRY in resource 80 - [Teardown] Validate tests +Run Keyword + START KEYWORD Run Keyword 84 NOT SET + START KEYWORD Log 84 NOT SET + \END KEYWORD Log 84 PASS + \END KEYWORD Run Keyword 84 PASS + START KEYWORD Run Keyword If 85 NOT SET + START KEYWORD User Keyword 85 NOT SET + START KEYWORD No Operation 101 NOT SET + \END KEYWORD No Operation 101 PASS + START RETURN ${EMPTY} 102 NOT SET + \END RETURN ${EMPTY} 102 PASS + \END KEYWORD User Keyword 85 PASS + \END KEYWORD Run Keyword If 85 PASS + +Run Keyword in keyword + START KEYWORD Run Keyword in keyword 89 NOT SET + START KEYWORD Run Keyword 128 NOT SET + START KEYWORD No Operation 128 NOT SET + \END KEYWORD No Operation 128 PASS + \END KEYWORD Run Keyword 128 PASS + \END KEYWORD Run Keyword in keyword 89 PASS + +Run Keyword in resource + START KEYWORD Run Keyword in resource 92 NOT SET + START KEYWORD Run Keyword 23 NOT SET source=${RESOURCE FILE} + START KEYWORD Log 23 NOT SET source=${RESOURCE FILE} + \END KEYWORD Log 23 PASS source=${RESOURCE FILE} + \END KEYWORD Run Keyword 23 PASS source=${RESOURCE FILE} + \END KEYWORD Run Keyword in resource 92 PASS + +In setup and teardown + START SETUP User Keyword 95 NOT SET + START KEYWORD No Operation 101 NOT SET + \END KEYWORD No Operation 101 PASS + START RETURN ${EMPTY} 102 NOT SET + \END RETURN ${EMPTY} 102 PASS + \END SETUP User Keyword 95 PASS + START KEYWORD No Operation 96 NOT SET + \END KEYWORD No Operation 96 PASS + START TEARDOWN Run Keyword 97 NOT SET + START KEYWORD Log 97 NOT SET + \END KEYWORD Log 97 PASS + \END TEARDOWN Run Keyword 97 PASS Suite - START SUITE Lineno And Source - END SUITE Lineno And Source status=FAIL + START SUITE Lineno And Source + \END SUITE Lineno And Source status=FAIL [Teardown] Validate suite +Test + [Template] Expect test + Keyword 5 + User keyword 8 + User keyword in resource 11 + Not run keyword 14 FAIL + \FOR 20 + FOR in keyword 25 + FOR in IF 28 + FOR in resource 35 + \IF 38 + IF in keyword 47 + IF in FOR 50 FAIL + IF in resource 60 + \TRY 63 FAIL + TRY in keyword 77 + TRY in resource 80 + Run Keyword 83 + Run Keyword in keyword 88 + Run Keyword in resource 91 + In setup and teardown 94 + [Teardown] Validate tests + *** Keywords *** Expect [Arguments] ${event} ${type} ${name} ${lineno}=-1 ${status}= ${source}=${TEST CASE FILE} diff --git a/atest/robot/output/listener_interface/listener_failing.robot b/atest/robot/output/listener_interface/listener_failing.robot index 9ac1fd3eded..da2f6870fb2 100644 --- a/atest/robot/output/listener_interface/listener_failing.robot +++ b/atest/robot/output/listener_interface/listener_failing.robot @@ -43,12 +43,11 @@ Listener errors should be reported Library listener errors should be reported FOR ${index} ${method} IN ENUMERATE - ... start_suite start_test start_keyword log_message + ... message start_suite start_test start_keyword log_message ... end_keyword end_test end_suite Error should be reported in execution errors ${index} ${method} failing_listener END Error should be reported in stderr close failing_listener - ... Error in library 'LibraryWithFailingListener': Error should be reported in execution errors [Arguments] ${index} ${method} ${listener} @@ -58,9 +57,8 @@ Error should be reported in execution errors Check log message ${ERRORS}[${index}] ${error} ERROR Error should be reported in stderr - [Arguments] ${method} ${listener} @{prefix} + [Arguments] ${method} ${listener} ${error} = Catenate - ... @{prefix} ... Calling method '${method}' of listener '${listener}' failed: ... Expected failure in ${method}! Stderr Should Contain [ ERROR ] ${error} diff --git a/atest/robot/output/listener_interface/listener_logging.robot b/atest/robot/output/listener_interface/listener_logging.robot index a6acb42e6df..bbeafc6c077 100644 --- a/atest/robot/output/listener_interface/listener_logging.robot +++ b/atest/robot/output/listener_interface/listener_logging.robot @@ -10,16 +10,29 @@ Logging from listener does not break output file All start and end methods can log warnings to execution errors Correct warnings should be shown in execution errors -Methods inside start_keyword and end_keyword can log normal messages +Methods under tests can log normal messages Correct messages should be logged to normal log -Methods outside start_keyword and end_keyword can log messages to syslog +Methods outside tests can log messages to syslog + Correct messages should be logged to syslog + +Logging from listener when using JSON output + [Setup] Run Tests With Logging Listener format=json + Test statuses should be correct + Log and report should be created + Correct messages should be logged to normal log + Correct warnings should be shown in execution errors Correct messages should be logged to syslog *** Keywords *** Run Tests With Logging Listener - ${path} = Normalize Path ${LISTENER DIR}/logging_listener.py - Run Tests --listener ${path} -l l.html -r r.html misc/pass_and_fail.robot + [Arguments] ${format}=xml + Should Be True $format in ('xml', 'json') + VAR ${output} ${OUTDIR}/output.${format} + VAR ${options} + ... --listener ${LISTENER DIR}/logging_listener.py + ... -o ${output} -l l.html -r r.html + Run Tests ${options} misc/pass_and_fail.robot output=${output} Test statuses should be correct Check Test Case Pass @@ -40,14 +53,17 @@ Execution errors should have messages from message and log_message methods Correct start/end warnings should be shown in execution errors ${msgs} = Get start/end messages ${ERRORS} @{kw} = Create List start keyword end keyword + @{var} = Create List start var end var @{return} = Create List start return end return - @{setup} = Create List start setup @{kw} @{kw} @{kw} @{return} end setup - @{uk} = Create List start keyword @{kw} @{kw} @{kw} @{return} end keyword + @{setup} = Create List start setup @{kw} @{kw} @{kw} @{var} @{kw} @{return} end setup + @{uk} = Create List start keyword @{kw} @{kw} @{kw} @{var} @{kw} @{return} end keyword FOR ${index} ${method} IN ENUMERATE ... start_suite ... @{setup} ... start_test ... @{uk} + ... start keyword start keyword end keyword end keyword + ... @{kw} ... end_test ... start_test ... @{uk} @@ -70,62 +86,79 @@ Get start/end messages Correct messages should be logged to normal log 'My Keyword' has correct messages ${SUITE.setup} Suite Setup ${tc} = Check Test Case Pass - 'My Keyword' has correct messages ${tc.kws[0]} Pass + Check Log Message ${tc[0]} start_test INFO + Check Log Message ${tc[1]} start_test WARN + 'My Keyword' has correct messages ${tc[2]} Pass + Check Log Message ${tc[5]} end_test INFO + Check Log Message ${tc[6]} end_test WARN ${tc} = Check Test Case Fail - 'My Keyword' has correct messages ${tc.kws[0]} Fail - 'Fail' has correct messages ${tc.kws[1]} + Check Log Message ${tc[0]} start_test INFO + Check Log Message ${tc[1]} start_test WARN + 'My Keyword' has correct messages ${tc[2]} Fail + 'Fail' has correct messages ${tc[3]} + Check Log Message ${tc[4]} end_test INFO + Check Log Message ${tc[5]} end_test WARN 'My Keyword' has correct messages [Arguments] ${kw} ${name} IF '${name}' == 'Suite Setup' - ${type} = Set Variable setup + VAR ${type} setup ELSE - ${type} = Set Variable keyword + VAR ${type} keyword END - Check Log Message ${kw.body[0]} start ${type} INFO - Check Log Message ${kw.body[1]} start ${type} WARN - Check Log Message ${kw.body[2].body[0]} start keyword INFO - Check Log Message ${kw.body[2].body[1]} start keyword WARN - Check Log Message ${kw.body[2].body[2]} log_message: INFO Hello says "${name}"! INFO - Check Log Message ${kw.body[2].body[3]} log_message: INFO Hello says "${name}"! WARN - Check Log Message ${kw.body[2].body[4]} Hello says "${name}"! INFO - Check Log Message ${kw.body[2].body[5]} end keyword INFO - Check Log Message ${kw.body[2].body[6]} end keyword WARN - Check Log Message ${kw.body[3].body[0]} start keyword INFO - Check Log Message ${kw.body[3].body[1]} start keyword WARN - Check Log Message ${kw.body[3].body[2]} end keyword INFO - Check Log Message ${kw.body[3].body[3]} end keyword WARN - Check Log Message ${kw.body[4].body[0]} start keyword INFO - Check Log Message ${kw.body[4].body[1]} start keyword WARN - Check Log Message ${kw.body[4].body[2]} log_message: INFO \${assign} = JUST TESTING... INFO - Check Log Message ${kw.body[4].body[3]} log_message: INFO \${assign} = JUST TESTING... WARN - Check Log Message ${kw.body[4].body[4]} \${assign} = JUST TESTING... INFO - Check Log Message ${kw.body[4].body[5]} end keyword INFO - Check Log Message ${kw.body[4].body[6]} end keyword WARN - Check Log Message ${kw.body[5].body[0]} start return INFO - Check Log Message ${kw.body[5].body[1]} start return WARN - Check Log Message ${kw.body[5].body[2]} end return INFO - Check Log Message ${kw.body[5].body[3]} end return WARN - Check Log Message ${kw.body[6]} end ${type} INFO - Check Log Message ${kw.body[7]} end ${type} WARN + Check Log Message ${kw[0]} start ${type} INFO + Check Log Message ${kw[1]} start ${type} WARN + Check Log Message ${kw[2, 0]} start keyword INFO + Check Log Message ${kw[2, 1]} start keyword WARN + Check Log Message ${kw[2, 2]} log_message: INFO Hello says "${name}"! INFO + Check Log Message ${kw[2, 3]} log_message: INFO Hello says "${name}"! WARN + Check Log Message ${kw[2, 4]} Hello says "${name}"! INFO + Check Log Message ${kw[2, 5]} end keyword INFO + Check Log Message ${kw[2, 6]} end keyword WARN + Check Log Message ${kw[3, 0]} start keyword INFO + Check Log Message ${kw[3, 1]} start keyword WARN + Check Log Message ${kw[3, 2]} end keyword INFO + Check Log Message ${kw[3, 3]} end keyword WARN + Check Log Message ${kw[4, 0]} start keyword INFO + Check Log Message ${kw[4, 1]} start keyword WARN + Check Log Message ${kw[4, 2]} log_message: INFO \${assign} = JUST TESTING... INFO + Check Log Message ${kw[4, 3]} log_message: INFO \${assign} = JUST TESTING... WARN + Check Log Message ${kw[4, 4]} \${assign} = JUST TESTING... INFO + Check Log Message ${kw[4, 5]} end keyword INFO + Check Log Message ${kw[4, 6]} end keyword WARN + Check Log Message ${kw[5, 0]} start var INFO + Check Log Message ${kw[5, 1]} start var WARN + Check Log Message ${kw[5, 2]} log_message: INFO \${expected} = JUST TESTING... INFO + Check Log Message ${kw[5, 3]} log_message: INFO \${expected} = JUST TESTING... WARN + Check Log Message ${kw[5, 4]} \${expected} = JUST TESTING... INFO + Check Log Message ${kw[5, 5]} end var INFO + Check Log Message ${kw[5, 6]} end var WARN + Check Log Message ${kw[6, 0]} start keyword INFO + Check Log Message ${kw[6, 1]} start keyword WARN + Check Log Message ${kw[6, 2]} end keyword INFO + Check Log Message ${kw[6, 3]} end keyword WARN + Check Log Message ${kw[7, 0]} start return INFO + Check Log Message ${kw[7, 1]} start return WARN + Check Log Message ${kw[7, 2]} end return INFO + Check Log Message ${kw[7, 3]} end return WARN + Check Log Message ${kw[8]} end ${type} INFO + Check Log Message ${kw[9]} end ${type} WARN 'Fail' has correct messages [Arguments] ${kw} - Check Log Message ${kw.body[0]} start keyword INFO - Check Log Message ${kw.body[1]} start keyword WARN - Check Log Message ${kw.body[2]} log_message: FAIL Expected failure INFO - Check Log Message ${kw.body[3]} log_message: FAIL Expected failure WARN - Check Log Message ${kw.body[4]} Expected failure FAIL - Check Log Message ${kw.body[5]} end keyword INFO - Check Log Message ${kw.body[6]} end keyword WARN + Check Log Message ${kw[0]} start keyword INFO + Check Log Message ${kw[1]} start keyword WARN + Check Log Message ${kw[2]} log_message: FAIL Expected failure INFO + Check Log Message ${kw[3]} log_message: FAIL Expected failure WARN + Check Log Message ${kw[4]} Expected failure FAIL + Check Log Message ${kw[5]} end keyword INFO + Check Log Message ${kw[6]} end keyword WARN Correct messages should be logged to syslog FOR ${msg} IN ... message: INFO Robot Framework ... start_suite ... end_suite - ... start_test - ... end_test ... output_file ... log_file ... report_file diff --git a/atest/robot/output/listener_interface/listener_methods.robot b/atest/robot/output/listener_interface/listener_methods.robot index ff96e7c101a..b97e6414441 100644 --- a/atest/robot/output/listener_interface/listener_methods.robot +++ b/atest/robot/output/listener_interface/listener_methods.robot @@ -21,12 +21,12 @@ Listen Some Correct Attributes To Listener Methods ${status} = Log File %{TEMPDIR}/${ATTR_TYPE_FILE} - Stderr Should Not Contain attributeverifyinglistener + Stderr Should Not Contain VerifyAttributes Should Not Contain ${status} FAILED Keyword Tags ${status} = Log File %{TEMPDIR}/${ATTR_TYPE_FILE} - Should Contain X Times ${status} PASSED | tags: [force, keyword, tags] 6 + Should Contain X Times ${status} passed | tags: [force, keyword, tags] 6 Suite And Test Counts Run Tests --listener listeners.SuiteAndTestCounts misc/suites/subsuites misc/suites/subsuites2 @@ -47,8 +47,8 @@ Keyword Status Executing Keywords from Listeners Run Tests --listener listeners.KeywordExecutingListener misc/pass_and_fail.robot ${tc}= Get Test Case Pass - Check Log Message ${tc.kws[0].msgs[0]} Start Pass - Check Log Message ${tc.kws[2].msgs[0]} End Pass + Check Log Message ${tc[0, 0]} Start Pass + Check Log Message ${tc[4, 0]} End Pass Test Template ${listener} = Normalize Path ${LISTENER DIR}/verify_template_listener.py @@ -56,13 +56,19 @@ Test Template Stderr Should Be Empty Keyword Arguments Are Always Strings - ${result} = Run Tests --listener attributeverifyinglistener ${LISTENER DIR}/keyword_argument_types.robot + ${result} = Run Tests --listener VerifyAttributes ${LISTENER DIR}/keyword_argument_types.robot Should Be Empty ${result.stderr} Check Test Tags Run Keyword with already resolved non-string arguments in test data 1 2 Check Test Case Run Keyword with non-string arguments in library ${status} = Log File %{TEMPDIR}/${ATTR_TYPE_FILE} Should Not Contain ${status} FAILED +Keyword Attributes For Control Structures + Run Tests --listener VerifyAttributes misc/for_loops.robot misc/while.robot misc/try_except.robot misc/if_else.robot + Stderr Should Be Empty + ${status} = Log File %{TEMPDIR}/${ATTR_TYPE_FILE} + Should Not Contain ${status} FAILED + TimeoutError occurring during listener method is propagaged [Documentation] Timeouts can only occur inside `log_message`. ... Cannot reliable set timeouts to occur during it, so the listener @@ -79,7 +85,7 @@ Run Tests With Listeners ... --listener ListenAll:%{TEMPDIR}${/}${ALL_FILE2} ... --listener module_listener ... --listener listeners.ListenSome - ... --listener attributeverifyinglistener + ... --listener VerifyAttributes ... --metadata ListenerMeta:Hello Run Tests ${args} misc/pass_and_fail.robot @@ -88,51 +94,74 @@ Check Listen All File @{expected}= Create List Got settings on level: INFO ... SUITE START: Pass And Fail (s1) 'Some tests here' [ListenerMeta: Hello] ... SETUP START: My Keyword ['Suite Setup'] (line 3) - ... KEYWORD START: BuiltIn.Log ['Hello says "\${who}"!', '\${LEVEL1}'] (line 27) + ... KEYWORD START: BuiltIn.Log ['Hello says "\${who}"!', '\${LEVEL1}'] (line 31) ... LOG MESSAGE: [INFO] Hello says "Suite Setup"! ... KEYWORD END: PASS - ... KEYWORD START: BuiltIn.Log ['Debug message', '\${LEVEL2}'] (line 28) + ... KEYWORD START: BuiltIn.Log ['Debug message', '\${LEVEL2}'] (line 32) ... KEYWORD END: PASS - ... KEYWORD START: \${assign} = String.Convert To Upper Case ['Just testing...'] (line 29) + ... KEYWORD START: \${assign} = String.Convert To Upper Case ['Just testing...'] (line 33) ... LOG MESSAGE: [INFO] \${assign} = JUST TESTING... ... KEYWORD END: PASS - ... RETURN START: (line 30) + ... VAR START: \${expected}${SPACE*4}JUST TESTING... (line 34) + ... LOG MESSAGE: [INFO] \${expected} = JUST TESTING... + ... VAR END: PASS + ... KEYWORD START: BuiltIn.Should Be Equal ['\${assign}', '\${expected}'] (line 35) + ... KEYWORD END: PASS + ... RETURN START: (line 36) ... RETURN END: PASS ... SETUP END: PASS - ... TEST START: Pass (s1-t1, line 12) '' ['force', 'pass'] - ... KEYWORD START: My Keyword ['Pass'] (line 15) - ... KEYWORD START: BuiltIn.Log ['Hello says "\${who}"!', '\${LEVEL1}'] (line 27) + ... TEST START: Pass (s1-t1, line 14) '' ['force', 'pass'] + ... KEYWORD START: My Keyword ['Pass'] (line 17) + ... KEYWORD START: BuiltIn.Log ['Hello says "\${who}"!', '\${LEVEL1}'] (line 31) ... LOG MESSAGE: [INFO] Hello says "Pass"! ... KEYWORD END: PASS - ... KEYWORD START: BuiltIn.Log ['Debug message', '\${LEVEL2}'] (line 28) + ... KEYWORD START: BuiltIn.Log ['Debug message', '\${LEVEL2}'] (line 32) ... KEYWORD END: PASS - ... KEYWORD START: \${assign} = String.Convert To Upper Case ['Just testing...'] (line 29) + ... KEYWORD START: \${assign} = String.Convert To Upper Case ['Just testing...'] (line 33) ... LOG MESSAGE: [INFO] \${assign} = JUST TESTING... ... KEYWORD END: PASS - ... RETURN START: (line 30) + ... VAR START: \${expected}${SPACE*4}JUST TESTING... (line 34) + ... LOG MESSAGE: [INFO] \${expected} = JUST TESTING... + ... VAR END: PASS + ... KEYWORD START: BuiltIn.Should Be Equal ['\${assign}', '\${expected}'] (line 35) + ... KEYWORD END: PASS + ... RETURN START: (line 36) ... RETURN END: PASS ... KEYWORD END: PASS + ... KEYWORD START: example.Resource Keyword (line 18) + ... KEYWORD START: BuiltIn.Log ['Hello, resource!'] (line 3) + ... LOG MESSAGE: [INFO] Hello, resource! + ... KEYWORD END: PASS + ... KEYWORD END: PASS + ... KEYWORD START: BuiltIn.Should Be Equal ['\${VARIABLE}', 'From variables.py with arg 1'] (line 19) + ... KEYWORD END: PASS ... TEST END: PASS - ... TEST START: Fail (s1-t2, line 17) 'FAIL Expected failure' ['fail', 'force'] - ... KEYWORD START: My Keyword ['Fail'] (line 20) - ... KEYWORD START: BuiltIn.Log ['Hello says "\${who}"!', '\${LEVEL1}'] (line 27) + ... TEST START: Fail (s1-t2, line 21) 'FAIL Expected failure' ['fail', 'force'] + ... KEYWORD START: My Keyword ['Fail'] (line 24) + ... KEYWORD START: BuiltIn.Log ['Hello says "\${who}"!', '\${LEVEL1}'] (line 31) ... LOG MESSAGE: [INFO] Hello says "Fail"! ... KEYWORD END: PASS - ... KEYWORD START: BuiltIn.Log ['Debug message', '\${LEVEL2}'] (line 28) + ... KEYWORD START: BuiltIn.Log ['Debug message', '\${LEVEL2}'] (line 32) ... KEYWORD END: PASS - ... KEYWORD START: \${assign} = String.Convert To Upper Case ['Just testing...'] (line 29) + ... KEYWORD START: \${assign} = String.Convert To Upper Case ['Just testing...'] (line 33) ... LOG MESSAGE: [INFO] \${assign} = JUST TESTING... ... KEYWORD END: PASS - ... RETURN START: (line 30) + ... VAR START: \${expected}${SPACE*4}JUST TESTING... (line 34) + ... LOG MESSAGE: [INFO] \${expected} = JUST TESTING... + ... VAR END: PASS + ... KEYWORD START: BuiltIn.Should Be Equal ['\${assign}', '\${expected}'] (line 35) + ... KEYWORD END: PASS + ... RETURN START: (line 36) ... RETURN END: PASS ... KEYWORD END: PASS - ... KEYWORD START: BuiltIn.Fail ['Expected failure'] (line 21) + ... KEYWORD START: BuiltIn.Fail ['Expected failure'] (line 25) ... LOG MESSAGE: [FAIL] Expected failure ... KEYWORD END: FAIL ... TEST END: FAIL Expected failure ... SUITE END: FAIL 2 tests, 1 passed, 1 failed ... Output: output.xml Closing... Check Listener File ${filename} @{expected} + Stderr Should Be Empty Calling listener failed [Arguments] ${method} ${error} diff --git a/atest/robot/output/listener_interface/listener_order.robot b/atest/robot/output/listener_interface/listener_order.robot new file mode 100644 index 00000000000..162b4a50154 --- /dev/null +++ b/atest/robot/output/listener_interface/listener_order.robot @@ -0,0 +1,57 @@ +*** Settings *** +Suite Setup Run Tests With Ordered Listeners +Resource atest_resource.robot + +*** Variables *** +${LISTENER} ${DATADIR}/output/listener_interface/ListenerOrder.py + +*** Test Cases *** +Validate normal order + VAR ${expected} + ... LIB 3 (999.9): start_suite + ... CLI 2 (3.14): start_suite + ... CLI 3 (None): start_suite + ... LIB 1 (0): start_suite + ... LIB 2 (None): start_suite + ... CLI 1 (-1): start_suite + ... LIB 3 (999.9): log_message + ... CLI 2 (3.14): log_message + ... CLI 3 (None): log_message + ... LIB 1 (0): log_message + ... LIB 2 (None): log_message + ... CLI 1 (-1): log_message + ... LIB 3 (999.9): end_test + ... CLI 2 (3.14): end_test + ... CLI 3 (None): end_test + ... LIB 1 (0): end_test + ... LIB 2 (None): end_test + ... CLI 1 (-1): end_test + ... separator=\n + File Should Be Equal To %{TEMPDIR}/listener_order.log ${expected}\n + +Validate close order + [Documentation] Library listeners are closed when libraries go out of scope. + VAR ${expected} + ... LIB 1 (0): close + ... LIB 2 (None): close + ... LIB 3 (999.9): close + ... CLI 2 (3.14): close + ... CLI 3 (None): close + ... CLI 1 (-1): close + ... separator=\n + File Should Be Equal To %{TEMPDIR}/listener_close_order.log ${expected}\n + +Invalid priority + ${listener} = Normalize Path ${LISTENER} + Check Log Message ${ERRORS}[0] Taking listener '${listener}:NOT USED:invalid' into use failed: Invalid listener priority 'invalid'. ERROR + Check Log Message ${ERRORS}[1] Error in library 'BAD': Registering listeners failed: Taking listener 'SELF' into use failed: Invalid listener priority 'bad'. ERROR + +*** Keywords *** +Run Tests With Ordered Listeners + ${listener} = Normalize Path ${LISTENER} + VAR ${options} + ... --listener "${listener}:CLI 1:-1" + ... --listener "${listener}:CLI 2:3.14" + ... --listener "${listener}:NOT USED:invalid" + ... --listener "${listener}:CLI 3" + Run Tests ${options} output/listener_interface/listener_order.robot diff --git a/atest/robot/output/listener_interface/listener_resource.robot b/atest/robot/output/listener_interface/listener_resource.robot index 6b94649e09a..23d4da59ca3 100644 --- a/atest/robot/output/listener_interface/listener_resource.robot +++ b/atest/robot/output/listener_interface/listener_resource.robot @@ -42,4 +42,4 @@ Get Listener File [Arguments] ${file} ${path} = Join Path %{TEMPDIR} ${file} ${content} = Get File ${path} - [Return] ${content} + RETURN ${content} diff --git a/atest/robot/output/listener_interface/listener_v3.robot b/atest/robot/output/listener_interface/listener_v3.robot index d533bbd7c35..031dd246aaa 100644 --- a/atest/robot/output/listener_interface/listener_v3.robot +++ b/atest/robot/output/listener_interface/listener_v3.robot @@ -1,5 +1,5 @@ *** Settings *** -Suite Setup Run Tests --listener ${LISTENER DIR}/v3.py -l l -r r -b d -x x misc/pass_and_fail.robot +Suite Setup Run Tests --listener ${LISTENER DIR}/v3.py -l l -r r -b d -x x -L trace misc/pass_and_fail.robot Resource listener_resource.robot *** Variables *** @@ -8,11 +8,11 @@ ${SEPARATOR} ${EMPTY + '-' * 78} *** Test Cases *** New tests and keywords can be added ${tc} = Check test case Added by start_suite [start suite] FAIL [start] [end] - Check keyword data ${tc.kws[0]} BuiltIn.No Operation + Check keyword data ${tc[0]} BuiltIn.No Operation ${tc} = Check test case Added by startTest PASS Dynamically added! [end] - Check keyword data ${tc.kws[0]} BuiltIn.Fail args=Dynamically added! status=FAIL + Check keyword data ${tc[0]} BuiltIn.Fail args=Dynamically added! status=FAIL ${tc} = Check test case Added by end_Test FAIL [start] [end] - Check keyword data ${tc.kws[0]} BuiltIn.Log args=Dynamically added!, INFO + Check keyword data ${tc[0]} BuiltIn.Log args=Dynamically added!, INFO Stdout Should Contain SEPARATOR=\n ... Added by start_suite [start suite] :: [start suite] ${SPACE*17} | FAIL | ... [start] [end] @@ -63,12 +63,34 @@ Changing current element docs does not change console output, but does change ou Check Test Doc Pass [start suite] [start suite] [start test] [end test] Log messages and timestamps can be changed - ${tc} = Get test case Pass [start suite] - Check log message ${tc.kws[0].kws[0].msgs[0]} HELLO SAYS "PASS"! - Should be equal ${tc.kws[0].kws[0].msgs[0].timestamp} 20151216 15:51:20.141 + ${tc} = Get Test Case Pass [start suite] + Check Keyword Data ${tc[0, 0]} BuiltIn.Log args=Hello says "\${who}"!, \${LEVEL1} + Check Log Message ${tc[0, 0, 0]} HELLO SAYS "PASS"! + Should Be Equal ${tc[0, 0, 0].timestamp} ${datetime(2015, 12, 16, 15, 51, 20, 141000)} + +Log message can be removed by setting message to `None` + ${tc} = Get Test Case Fail [start suite] + Check Keyword Data ${tc[0, 0]} BuiltIn.Log args=Hello says "\${who}"!, \${LEVEL1} + Should Be Empty ${tc[0, 0].body} + File Should Not Contain ${OUTDIR}/d.txt HELLO SAYS "FAIL"! + File Should Not Contain ${OUTDIR}/d.txt None Syslog messages can be changed - Syslog Should Contain Match 20151216 15:51:20.141 | INFO \ | TESTS EXECUTION ENDED. STATISTICS: + Syslog Should Contain Match 2015-12-16 15:51:20.141000 | INFO \ | TESTS EXECUTION ENDED. STATISTICS: + +Library import + Stdout Should Contain Imported library 'BuiltIn' with 107 keywords. + Stdout Should Contain Imported library 'String' with 32 keywords. + ${tc} = Get Test Case Pass [start suite] + Check Keyword Data ${tc[0, 0]} BuiltIn.Log doc=Changed! args=Hello says "\${who}"!, \${LEVEL1} + +Resource import + Stdout Should Contain Imported resource 'example' with 2 keywords. + ${tc} = Get Test Case Pass [start suite] + Check Keyword Data ${tc[1, 1]} example.New! doc=Dynamically created. + +Variables import + Stdout Should Contain Imported variables 'variables.py' without much info. File methods and close are called Stderr Should Be Equal To SEPARATOR=\n @@ -78,3 +100,9 @@ File methods and close are called ... Log: l.html ... Report: r.html ... Close\n + +File methods when files are disabled + Run Tests Without Processing Output --listener ${LISTENER DIR}/v3.py -o NONE -r NONE -l NONE misc/pass_and_fail.robot + Stderr Should Be Equal To SEPARATOR=\n + ... Output: None + ... Close\n diff --git a/atest/robot/output/listener_interface/log_levels.robot b/atest/robot/output/listener_interface/log_levels.robot index e48ad12f0ac..3bf2727bb0e 100644 --- a/atest/robot/output/listener_interface/log_levels.robot +++ b/atest/robot/output/listener_interface/log_levels.robot @@ -11,10 +11,14 @@ Log messages are collected on INFO level by default Logged messages should be ... INFO: Hello says "Suite Setup"! ... INFO: \${assign} = JUST TESTING... + ... INFO: \${expected} = JUST TESTING... ... INFO: Hello says "Pass"! ... INFO: \${assign} = JUST TESTING... + ... INFO: \${expected} = JUST TESTING... + ... INFO: Hello, resource! ... INFO: Hello says "Fail"! ... INFO: \${assign} = JUST TESTING... + ... INFO: \${expected} = JUST TESTING... ... FAIL: Expected failure Log messages are collected on specified level @@ -23,12 +27,28 @@ Log messages are collected on specified level ... INFO: Hello says "Suite Setup"! ... DEBUG: Debug message ... INFO: \${assign} = JUST TESTING... + ... INFO: \${expected} = JUST TESTING... + ... DEBUG: Argument types are: + ... + ... ... INFO: Hello says "Pass"! ... DEBUG: Debug message ... INFO: \${assign} = JUST TESTING... + ... INFO: \${expected} = JUST TESTING... + ... DEBUG: Argument types are: + ... + ... + ... INFO: Hello, resource! + ... DEBUG: Argument types are: + ... + ... ... INFO: Hello says "Fail"! ... DEBUG: Debug message ... INFO: \${assign} = JUST TESTING... + ... INFO: \${expected} = JUST TESTING... + ... DEBUG: Argument types are: + ... + ... ... FAIL: Expected failure ... DEBUG: Traceback (most recent call last): ... ${SPACE*2}None diff --git a/atest/robot/output/listener_interface/output_files.robot b/atest/robot/output/listener_interface/output_files.robot index c03b1afa115..f75323b1188 100644 --- a/atest/robot/output/listener_interface/output_files.robot +++ b/atest/robot/output/listener_interface/output_files.robot @@ -1,7 +1,6 @@ *** Settings *** Documentation Testing that listener gets information about different output files. ... Tests also that the listener can be taken into use with path. -Suite Setup Run Some Tests Suite Teardown Remove Listener Files Resource listener_resource.robot @@ -9,23 +8,38 @@ Resource listener_resource.robot ${LISTENERS} ${CURDIR}${/}..${/}..${/}..${/}testresources${/}listeners *** Test Cases *** -Output Files - ${file} = Get Listener File ${ALL_FILE} - ${expected} = Catenate SEPARATOR=\n +Output files + ${options} = Catenate + ... --listener "${LISTENERS}${/}ListenAll.py" + ... --output myout.xml + ... --report myrep.html + ... --log mylog.html + ... --xunit myxun.xml + ... --debugfile mydeb.txt + Run Tests ${options} misc/pass_and_fail.robot output=${OUTDIR}/myout.xml + Validate result files ... Debug: mydeb.txt ... Output: myout.xml + ... Xunit: myxun.xml ... Log: mylog.html ... Report: myrep.html - ... Closing...\n - Should End With ${file} ${expected} -*** Keywords *** -Run Some Tests +Output files disabled ${options} = Catenate - ... --listener "${LISTENERS}${/}ListenAll.py" - ... --log mylog.html - ... --report myrep.html - ... --output myout.xml - ... --debugfile mydeb.txt - Run Tests ${options} misc/pass_and_fail.robot output=${OUTDIR}/myout.xml - Should Be Equal ${SUITE.name} Pass And Fail + ... --listener "${LISTENERS}${/}ListenAll.py:output_file_disabled=True" + ... --log NONE + ... --report NONE + ... --output NONE + Run Tests Without Processing Output ${options} misc/pass_and_fail.robot + Validate result files + ... Output: None + +*** Keywords *** +Validate result files + [Arguments] @{files} + ${file} = Get Listener File ${ALL_FILE} + ${expected} = Catenate SEPARATOR=\n + ... @{files} + ... Closing...\n + Should End With ${file} ${expected} + Stderr Should Be Empty diff --git a/atest/robot/output/listener_interface/recursion.robot b/atest/robot/output/listener_interface/recursion.robot new file mode 100644 index 00000000000..2b951649ca0 --- /dev/null +++ b/atest/robot/output/listener_interface/recursion.robot @@ -0,0 +1,41 @@ +*** Settings *** +Suite Setup Run Tests --listener ${LISTENER DIR}/Recursion.py ${LISTENER DIR}/recursion.robot +Resource listener_resource.robot + +*** Test Cases *** +Limited recursion in start_keyword, end_keyword and log_message + ${tc} = Check Test Case Limited recursion + Length Should Be ${tc.body} 1 + VAR ${kw} ${tc[0]} + Check Keyword Data ${kw} BuiltIn.Log args=Limited 3 children=5 + Check Keyword Data ${kw[0]} BuiltIn.Log args=Limited 2 (by start_keyword) children=4 + Check Keyword Data ${kw[0, 0]} BuiltIn.Log args=Limited 1 (by start_keyword) children=1 + Check Log Message ${kw[0, 0, 0]} Limited 1 (by start_keyword) + Check Log Message ${kw[0, 1]} Limited 1 (by log_message) + Check Log Message ${kw[0, 2]} Limited 2 (by start_keyword) + Check Keyword Data ${kw[0, 3]} BuiltIn.Log args=Limited 1 (by end_keyword) children=1 + Check Log Message ${kw[0, 3, 0]} Limited 1 (by end_keyword) + Check Log Message ${kw[1]} Limited 1 (by log_message) + Check Log Message ${kw[2]} Limited 2 (by log_message) + Check Log Message ${kw[3]} Limited 3 + Check Keyword Data ${kw[4]} BuiltIn.Log args=Limited 2 (by end_keyword) children=4 + Check Keyword Data ${kw[4, 0]} BuiltIn.Log args=Limited 1 (by start_keyword) children=1 + Check Log Message ${kw[4, 0, 0]} Limited 1 (by start_keyword) + Check Log Message ${kw[4, 1]} Limited 1 (by log_message) + Check Log Message ${kw[4, 2]} Limited 2 (by end_keyword) + Check Keyword Data ${kw[4, 3]} BuiltIn.Log args=Limited 1 (by end_keyword) children=1 + Check Log Message ${kw[4, 3, 0]} Limited 1 (by end_keyword) + +Unlimited recursion in start_keyword, end_keyword and log_message + Check Test Case Unlimited recursion + Check Recursion Error ${ERRORS[0]} start_keyword Recursive execution stopped. + Check Recursion Error ${ERRORS[1]} end_keyword Recursive execution stopped. + Check Recursion Error ${ERRORS[2]} log_message RecursionError: * + +*** Keywords *** +Check Recursion Error + [Arguments] ${msg} ${method} ${error} + ${listener} = Normalize Path ${LISTENER DIR}/Recursion.py + Check Log Message ${msg} + ... Calling method '${method}' of listener '${listener}' failed: ${error} + ... ERROR pattern=True diff --git a/atest/robot/output/listener_interface/result_model.robot b/atest/robot/output/listener_interface/result_model.robot new file mode 100644 index 00000000000..3f56c5c0472 --- /dev/null +++ b/atest/robot/output/listener_interface/result_model.robot @@ -0,0 +1,29 @@ +*** Settings *** +Suite Setup Run Tests --listener "${LISTENER DIR}/ResultModel.py;${MODEL FILE}" --loglevel DEBUG ${LISTENER DIR}/result_model.robot +Resource listener_resource.robot + +*** Variables *** +${MODEL FILE} %{TEMPDIR}/listener_result_model.json + +*** Test Cases *** +Result model is consistent with information sent to listeners + Should Be Empty ${ERRORS} + +Result model build during execution is same as saved to output.xml + ${expected} = Check Test Case Test + ${actual} = Evaluate robot.result.TestCase.from_json($MODEL_FILE) + ${suite} = Evaluate robot.result.TestSuite.from_dict({'tests': [$actual]}) # Required to get correct id. + Dictionaries Should Be Equal ${actual.to_dict()} ${expected.to_dict()} + +Messages below log level and messages explicitly removed are not included + ${tc} = Check Test Case Test + Check Keyword Data ${tc[2, 1]} BuiltIn.Log args=User keyword, DEBUG children=3 + Check Log Message ${tc[2, 1, 0]} Starting KEYWORD + Check Log Message ${tc[2, 1, 1]} User keyword DEBUG + Check Log Message ${tc[2, 1, 2]} Ending KEYWORD + Check Keyword Data ${tc[2, 2]} BuiltIn.Log args=Not logged, TRACE children=2 + Check Log Message ${tc[2, 2, 0]} Starting KEYWORD + Check Log Message ${tc[2, 2, 1]} Ending KEYWORD + Check Keyword Data ${tc[2, 3]} BuiltIn.Log args=Remove me! children=2 + Check Log Message ${tc[2, 3, 0]} Starting KEYWORD + Check Log Message ${tc[2, 3, 1]} Ending KEYWORD diff --git a/atest/robot/output/listener_interface/unsupported_listener_version.robot b/atest/robot/output/listener_interface/unsupported_listener_version.robot deleted file mode 100644 index 6828330164c..00000000000 --- a/atest/robot/output/listener_interface/unsupported_listener_version.robot +++ /dev/null @@ -1,28 +0,0 @@ -*** Settings *** -Suite Setup Run Tests With Listeners -Resource listener_resource.robot -Test Template Taking listener into use should have failed - -*** Test Cases *** -Unsupported version - 0 unsupported_listeners.V1ClassListener - ... Listener 'unsupported_listeners.V1ClassListener' uses unsupported API version '1'. - 1 unsupported_listeners.InvalidVersionClassListener - ... Listener 'unsupported_listeners.InvalidVersionClassListener' uses unsupported API version 'kekkonen'. - -No version information - 2 unsupported_listeners - ... Listener 'unsupported_listeners' does not have mandatory 'ROBOT_LISTENER_API_VERSION' attribute. - -*** Keywords *** -Run Tests With Listeners - ${listeners} = Catenate - ... --listener unsupported_listeners.V1ClassListener - ... --listener unsupported_listeners.InvalidVersionClassListener - ... --listener unsupported_listeners - Run Tests ${listeners} misc/pass_and_fail.robot - -Taking listener into use should have failed - [Arguments] ${index} ${name} ${error} - Check Log Message ${ERRORS}[${index}] - ... Taking listener '${name}' into use failed: ${error} ERROR diff --git a/atest/robot/output/listener_interface/using_run_keyword.robot b/atest/robot/output/listener_interface/using_run_keyword.robot index 264b0d70699..be7635fe20a 100644 --- a/atest/robot/output/listener_interface/using_run_keyword.robot +++ b/atest/robot/output/listener_interface/using_run_keyword.robot @@ -4,178 +4,289 @@ Resource listener_resource.robot *** Test Cases *** In start_suite when suite has no setup - Should Be Equal ${SUITE.setup.name} Implicit setup - Should Be Equal ${SUITE.setup.body[0].name} BuiltIn.Log - Check Log Message ${SUITE.setup.body[0].body[0]} start_suite - Length Should Be ${SUITE.setup.body} 1 + Check Keyword Data ${SUITE.setup} Implicit setup type=SETUP children=1 + Validate Log ${SUITE.setup[0]} start_suite In end_suite when suite has no teardown - Should Be Equal ${SUITE.teardown.name} Implicit teardown - Should Be Equal ${SUITE.teardown.body[0].name} BuiltIn.Log - Check Log Message ${SUITE.teardown.body[0].body[0]} end_suite - Length Should Be ${SUITE.teardown.body} 1 + Check Keyword Data ${SUITE.teardown} Implicit teardown type=TEARDOWN children=1 + Validate Log ${SUITE.teardown[0]} end_suite In start_suite when suite has setup - ${suite} = Set Variable ${SUITE.suites[1]} - Should Be Equal ${suite.setup.name} Suite Setup - Should Be Equal ${suite.setup.body[0].name} BuiltIn.Log - Check Log Message ${suite.setup.body[0].body[0]} start_suite - Length Should Be ${suite.setup.body} 5 + VAR ${kw} ${SUITE.suites[1].setup} + Check Keyword Data ${kw} Suite Setup type=SETUP children=5 + Validate Log ${kw[0]} start_suite + Check Keyword Data ${kw[1]} BuiltIn.Log args=start_keyword children=1 + Check Log Message ${kw[1, 0]} start_keyword + Validate Log ${kw[2]} Keyword + Check Keyword Data ${kw[3]} Keyword children=3 + Check Keyword Data ${kw[3, 0]} BuiltIn.Log args=start_keyword children=1 + Check Log Message ${kw[3, 0, 0]} start_keyword + Check Keyword Data ${kw[3, 1]} BuiltIn.Log args=Keyword children=3 + Check Keyword Data ${kw[3, 2]} BuiltIn.Log args=end_keyword children=1 + Check Log Message ${kw[3, 2, 0]} end_keyword + Check Keyword Data ${kw[4]} BuiltIn.Log args=end_keyword children=1 + Check Log Message ${kw[4, 0]} end_keyword In end_suite when suite has teardown - ${suite} = Set Variable ${SUITE.suites[1]} - Should Be Equal ${suite.teardown.name} Suite Teardown - Should Be Equal ${suite.teardown.body[-1].name} BuiltIn.Log - Check Log Message ${suite.teardown.body[-1].body[0]} end_suite - Length Should Be ${suite.teardown.body} 5 + VAR ${kw} ${SUITE.suites[1].teardown} + Check Keyword Data ${kw} Suite Teardown type=TEARDOWN children=5 + Check Keyword Data ${kw[0]} BuiltIn.Log args=start_keyword children=1 + Check Log Message ${kw[0, 0]} start_keyword + Validate Log ${kw[1]} Keyword + Check Keyword Data ${kw[2]} Keyword children=3 + Check Keyword Data ${kw[2, 0]} BuiltIn.Log args=start_keyword children=1 + Check Log Message ${kw[2, 0, 0]} start_keyword + Check Keyword Data ${kw[2, 1]} BuiltIn.Log args=Keyword children=3 + Check Keyword Data ${kw[2, 2]} BuiltIn.Log args=end_keyword children=1 + Check Log Message ${kw[2, 2, 0]} end_keyword + Check Keyword Data ${kw[3]} BuiltIn.Log args=end_keyword children=1 + Check Log Message ${kw[3, 0]} end_keyword + Validate Log ${kw[4]} end_suite In start_test and end_test when test has no setup or teardown - ${tc} = Check Test Case First One - Should Be Equal ${tc.body[0].name} BuiltIn.Log - Check Log Message ${tc.body[0].body[0]} start_test - Should Be Equal ${tc.body[-1].name} BuiltIn.Log - Check Log Message ${tc.body[-1].body[0]} end_test - Length Should Be ${tc.body} 5 + ${tc} = Check Test Case First One + Length Should Be ${tc.body} 5 Should Not Be True ${tc.setup} Should Not Be True ${tc.teardown} + Validate Log ${tc[0]} start_test + Validate Log ${tc[1]} Test 1 + Validate Log ${tc[2]} Logging with debug level DEBUG + Check Keyword Data ${tc[3]} logs on trace tags=kw, tags children=3 + Check Keyword Data ${tc[3, 0]} BuiltIn.Log args=start_keyword children=1 + Check Keyword Data ${tc[3, 1]} BuiltIn.Log args=Log on \${TEST NAME}, TRACE children=3 + Check Keyword Data ${tc[3, 2]} BuiltIn.Log args=end_keyword children=1 + Validate Log ${tc[4]} end_test In start_test and end_test when test has setup and teardown - ${tc} = Check Test Case Test with setup and teardown - Should Be Equal ${tc.body[0].name} BuiltIn.Log - Check Log Message ${tc.body[0].body[0]} start_test - Should Be Equal ${tc.body[-1].name} BuiltIn.Log - Check Log Message ${tc.body[-1].body[0]} end_test - Length Should Be ${tc.body} 3 - Should Be Equal ${tc.setup.name} Test Setup - Should Be Equal ${tc.teardown.name} Test Teardown + ${tc} = Check Test Case Test with setup and teardown + Length Should Be ${tc.body} 3 + Check Keyword Data ${tc.setup} Test Setup type=SETUP children=4 + Check Keyword Data ${tc.teardown} Test Teardown type=TEARDOWN children=4 + Validate Log ${tc[0]} start_test + Check Keyword Data ${tc[1]} Keyword children=3 + Check Keyword Data ${tc[1, 0]} BuiltIn.Log args=start_keyword children=1 + Check Log Message ${tc[1, 0, 0]} start_keyword + Check Keyword Data ${tc[1, 1]} BuiltIn.Log args=Keyword children=3 + Check Keyword Data ${tc[1, 2]} BuiltIn.Log args=end_keyword children=1 + Check Log Message ${tc[1, 2, 0]} end_keyword + Validate Log ${tc[2]} end_test In start_keyword and end_keyword with library keyword - ${tc} = Check Test Case First One - Should Be Equal ${tc.body[1].name} BuiltIn.Log - Should Be Equal ${tc.body[1].body[0].name} BuiltIn.Log - Check Log Message ${tc.body[1].body[0].body[0]} start_keyword - Check Log Message ${tc.body[1].body[1]} Test 1 - Should Be Equal ${tc.body[1].body[2].name} BuiltIn.Log - Check Log Message ${tc.body[1].body[2].body[0]} end_keyword - Length Should Be ${tc.body[1].body} 3 + ${tc} = Check Test Case First One + Should Be Equal ${tc[1].full_name} BuiltIn.Log + Should Be Equal ${tc[1, 0].full_name} BuiltIn.Log + Check Log Message ${tc[1, 0, 0]} start_keyword + Check Log Message ${tc[1, 1]} Test 1 + Should Be Equal ${tc[1, 2].full_name} BuiltIn.Log + Check Log Message ${tc[1, 2, 0]} end_keyword + Length Should Be ${tc[1].body} 3 In start_keyword and end_keyword with user keyword - ${tc} = Check Test Case First One - Should Be Equal ${tc.body[3].name} logs on trace - Should Be Equal ${tc.body[3].body[0].name} BuiltIn.Log - Check Log Message ${tc.body[3].body[0].body[0]} start_keyword - Should Be Equal ${tc.body[3].body[1].name} BuiltIn.Log - Should Be Equal ${tc.body[3].body[1].body[0].name} BuiltIn.Log - Check Log Message ${tc.body[3].body[1].body[0].body[0]} start_keyword - Should Be Equal ${tc.body[3].body[1].body[1].name} BuiltIn.Log - Check Log Message ${tc.body[3].body[1].body[1].body[0]} end_keyword - Length Should Be ${tc.body[3].body[1].body} 2 - Should Be Equal ${tc.body[3].body[2].name} BuiltIn.Log - Check Log Message ${tc.body[3].body[2].body[0]} end_keyword - Length Should Be ${tc.body[3].body} 3 + ${tc} = Check Test Case First One + Should Be Equal ${tc[3].full_name} logs on trace + Should Be Equal ${tc[3, 0].full_name} BuiltIn.Log + Check Log Message ${tc[3, 0, 0]} start_keyword + Should Be Equal ${tc[3, 1].full_name} BuiltIn.Log + Should Be Equal ${tc[3, 1, 0].full_name} BuiltIn.Log + Check Log Message ${tc[3, 1, 0, 1]} start_keyword + Should Be Equal ${tc[3, 1, 2].full_name} BuiltIn.Log + Check Log Message ${tc[3, 1, 2, 1]} end_keyword + Length Should Be ${tc[3, 1].body} 3 + Should Be Equal ${tc[3, 2].full_name} BuiltIn.Log + Check Log Message ${tc[3, 2, 0]} end_keyword + Length Should Be ${tc[3].body} 3 In start_keyword and end_keyword with FOR loop - ${tc} = Check Test Case FOR loop in test - ${for} = Set Variable ${tc.body[1]} - Should Be Equal ${for.type} FOR - Length Should Be ${for.body} 5 - Length Should Be ${for.body.filter(keywords=True)} 2 - Should Be Equal ${for.body[0].name} BuiltIn.Log - Check Log Message ${for.body[0].body[0]} start_keyword - Should Be Equal ${for.body[-1].name} BuiltIn.Log - Check Log Message ${for.body[-1].body[0]} end_keyword + ${tc} = Check Test Case FOR + ${for} = Set Variable ${tc[1]} + Should Be Equal ${for.type} FOR + Length Should Be ${for.body} 5 + Length Should Be ${for.keywords} 2 + Should Be Equal ${for[0].full_name} BuiltIn.Log + Check Log Message ${for[0, 0]} start_keyword + Should Be Equal ${for[-1].full_name} BuiltIn.Log + Check Log Message ${for[-1,0]} end_keyword In start_keyword and end_keyword with WHILE - ${tc} = Check Test Case While loop executed multiple times - ${while} = Set Variable ${tc.body[2]} - Should Be Equal ${while.type} WHILE - Length Should Be ${while.body} 7 - Length Should Be ${while.body.filter(keywords=True)} 2 - Should Be Equal ${while.body[0].name} BuiltIn.Log - Check Log Message ${while.body[0].body[0]} start_keyword - Should Be Equal ${while.body[-1].name} BuiltIn.Log - Check Log Message ${while.body[-1].body[0]} end_keyword - - In start_keyword and end_keyword with IF/ELSE - ${tc} = Check Test Case IF structure - Should Be Equal ${tc.body[1].type} IF/ELSE ROOT - Length Should Be ${tc.body[1].body} 3 # Listener is not called with root - Validate IF branch ${tc.body[1].body[0]} IF NOT RUN # but is called with unexecuted branches. - Validate IF branch ${tc.body[1].body[1]} ELSE IF PASS - Validate IF branch ${tc.body[1].body[2]} ELSE NOT RUN + ${tc} = Check Test Case While loop executed multiple times + ${while} = Set Variable ${tc[2]} + Should Be Equal ${while.type} WHILE + Length Should Be ${while.body} 7 + Length Should Be ${while.keywords} 2 + Should Be Equal ${while[0].full_name} BuiltIn.Log + Check Log Message ${while[0, 0]} start_keyword + Should Be Equal ${while[-1].full_name} BuiltIn.Log + Check Log Message ${while[-1,0]} end_keyword + +In start_keyword and end_keyword with IF/ELSE + ${tc} = Check Test Case IF structure + Should Be Equal ${tc[1].type} VAR + Should Be Equal ${tc[2].type} IF/ELSE ROOT + Length Should Be ${tc[2].body} 3 # Listener is not called with root + Validate IF branch ${tc[2, 0]} IF NOT RUN # but is called with unexecuted branches. + Validate IF branch ${tc[2, 1]} ELSE IF PASS + Validate IF branch ${tc[2, 2]} ELSE NOT RUN In start_keyword and end_keyword with TRY/EXCEPT - ${tc} = Check Test Case Everything - Should Be Equal ${tc.body[1].type} TRY/EXCEPT ROOT - Length Should Be ${tc.body[1].body} 5 # Listener is not called with root - Validate FOR branch ${tc.body[1].body[0]} TRY FAIL - Validate FOR branch ${tc.body[1].body[1]} EXCEPT NOT RUN # but is called with unexecuted branches. - Validate FOR branch ${tc.body[1].body[2]} EXCEPT PASS - Validate FOR branch ${tc.body[1].body[3]} ELSE NOT RUN - Validate FOR branch ${tc.body[1].body[4]} FINALLY PASS + ${tc} = Check Test Case Everything + Should Be Equal ${tc[1].type} TRY/EXCEPT ROOT + Length Should Be ${tc[1].body} 5 # Listener is not called with root + Validate FOR branch ${tc[1, 0]} TRY FAIL + Validate FOR branch ${tc[1, 1]} EXCEPT NOT RUN # but is called with unexecuted branches. + Validate FOR branch ${tc[1, 2]} EXCEPT PASS + Validate FOR branch ${tc[1, 3]} ELSE NOT RUN + Validate FOR branch ${tc[1, 4]} FINALLY PASS In start_keyword and end_keyword with BREAK and CONTINUE - ${tc} = Check Test Case WHILE loop in keyword - FOR ${iter} IN @{tc.body[1].body[2].body[1:-1]} - Should Be Equal ${iter.body[3].body[0].body[1].type} CONTINUE - Should Be Equal ${iter.body[3].body[0].body[1].body[0].name} BuiltIn.Log - Check Log Message ${iter.body[3].body[0].body[1].body[0].body[0]} start_keyword - Should Be Equal ${iter.body[3].body[0].body[1].body[1].name} BuiltIn.Log - Check Log Message ${iter.body[3].body[0].body[1].body[1].body[0]} end_keyword - Should Be Equal ${iter.body[4].body[0].body[1].type} BREAK - Should Be Equal ${iter.body[4].body[0].body[1].body[0].name} BuiltIn.Log - Check Log Message ${iter.body[4].body[0].body[1].body[0].body[0]} start_keyword - Should Be Equal ${iter.body[4].body[0].body[1].body[1].name} BuiltIn.Log - Check Log Message ${iter.body[4].body[0].body[1].body[1].body[0]} end_keyword + ${tc} = Check Test Case WHILE loop in keyword + FOR ${iter} IN @{tc[1, 2][1:-1]} + Should Be Equal ${iter[3, 0, 1].type} CONTINUE + Should Be Equal ${iter[3, 0, 1, 0].full_name} BuiltIn.Log + Check Log Message ${iter[3, 0, 1, 0, 0]} start_keyword + Should Be Equal ${iter[3, 0, 1, 1].full_name} BuiltIn.Log + Check Log Message ${iter[3, 0, 1, 1, 0]} end_keyword + Should Be Equal ${iter[4, 0, 1].type} BREAK + Should Be Equal ${iter[4, 0, 1, 0].full_name} BuiltIn.Log + Check Log Message ${iter[4, 0, 1, 0, 0]} start_keyword + Should Be Equal ${iter[4, 0, 1, 1].full_name} BuiltIn.Log + Check Log Message ${iter[4, 0, 1, 1, 0]} end_keyword END In start_keyword and end_keyword with RETURN - ${tc} = Check Test Case Second One - Should Be Equal ${tc.body[3].body[1].body[1].body[2].type} RETURN - Should Be Equal ${tc.body[3].body[1].body[1].body[2].body[0].name} BuiltIn.Log - Check Log Message ${tc.body[3].body[1].body[1].body[2].body[0].body[0]} start_keyword - Should Be Equal ${tc.body[3].body[1].body[1].body[2].body[1].name} BuiltIn.Log - Check Log Message ${tc.body[3].body[1].body[1].body[2].body[1].body[0]} end_keyword + ${tc} = Check Test Case Second One + Should Be Equal ${tc[3, 1, 1, 2].type} RETURN + Should Be Equal ${tc[3, 1, 1, 2, 0].full_name} BuiltIn.Log + Check Log Message ${tc[3, 1, 1, 2, 0, 1]} start_keyword + Should Be Equal ${tc[3, 1, 1, 2, 1].full_name} BuiltIn.Log + Check Log Message ${tc[3, 1, 1, 2, 1, 1]} end_keyword + +With JSON output + [Documentation] Mainly test that executed keywords don't cause problems. + ... + ... Some data, such as keywords and messages on suite level, + ... are discarded and thus the exact output isn't the same as + ... with XML. + ... + ... Cannot validate output, because it doesn't match the schema. + Run Tests With Keyword Running Listener format=json validate=False + Should Contain Tests ${SUITE} + ... First One + ... Second One + ... Test with setup and teardown + ... Test with failing setup + ... Test with failing teardown + ... Failing test with failing teardown + ... FOR + ... FOR IN RANGE + ... FOR IN ENUMERATE + ... FOR IN ZIP + ... WHILE loop executed multiple times + ... WHILE loop in keyword + ... IF structure + ... Everything + ... Library keyword + ... User keyword and RETURN + ... Test documentation, tags and timeout + ... Test setup and teardown + ... Keyword Keyword documentation, tags and timeout + ... Keyword setup and teardown + ... Failure + ... VAR + ... IF + ... TRY + ... FOR and CONTINUE + ... WHILE and BREAK + ... GROUP + ... Syntax error + +In dry-run + Run Tests With Keyword Running Listener --dry-run + Should Contain Tests ${SUITE} + ... First One + ... Test with setup and teardown + ... FOR + ... FOR IN ENUMERATE + ... FOR IN ZIP + ... WHILE loop executed multiple times + ... WHILE loop in keyword + ... IF structure + ... Everything + ... Library keyword + ... User keyword and RETURN + ... Test documentation, tags and timeout + ... Test setup and teardown + ... Keyword Keyword documentation, tags and timeout + ... Keyword setup and teardown + ... VAR + ... IF + ... TRY + ... FOR and CONTINUE + ... WHILE and BREAK + ... GROUP + ... Second One=FAIL:Several failures occurred:\n\n1) No keyword with name 'Not executed' found.\n\n2) No keyword with name 'Not executed' found. + ... Test with failing setup=PASS + ... Test with failing teardown=PASS + ... Failing test with failing teardown=PASS + ... FOR IN RANGE=FAIL:No keyword with name 'Not executed!' found. + ... Failure=PASS + ... Syntax error=FAIL:Several failures occurred:\n\n1) Non-existing setting 'Bad'.\n\n2) Non-existing setting 'Ooops'. *** Keywords *** Run Tests With Keyword Running Listener - ${path} = Normalize Path ${LISTENER DIR}/keyword_running_listener.py - ${files} = Catenate + [Arguments] ${options}= ${format}=xml ${validate}=True + VAR ${listener} ${LISTENER DIR}/keyword_running_listener.py + VAR ${output} ${OUTDIR}/output.${format} + VAR ${files} ... misc/normal.robot ... misc/setups_and_teardowns.robot ... misc/for_loops.robot ... misc/while.robot ... misc/if_else.robot ... misc/try_except.robot - Run Tests --listener ${path} ${files} validate output=True - Should Be Empty ${ERRORS} + ... misc/everything.robot + Run Tests --listener ${listener} ${options} -L debug -o ${output} ${files} output=${output} validate output=${validate} + Length Should Be ${ERRORS} 1 + +Validate Log + [Arguments] ${kw} ${message} ${level}=INFO + IF $level == 'INFO' + VAR ${args} ${message} + ELSE + VAR ${args} ${message}, ${level} + END + Check Keyword Data ${kw} BuiltIn.Log args=${args} children=3 + Check Keyword Data ${kw[0]} BuiltIn.Log args=start_keyword children=1 + Check Log Message ${kw[0, 0]} start_keyword + Check Log Message ${kw[1]} ${message} ${level} + Check Keyword Data ${kw[2]} BuiltIn.Log args=end_keyword children=1 + Check Log Message ${kw[2, 0]} end_keyword Validate IF branch [Arguments] ${branch} ${type} ${status} - Should Be Equal ${branch.type} ${type} - Should Be Equal ${branch.status} ${status} - Length Should Be ${branch.body} 3 - Should Be Equal ${branch.body[0].name} BuiltIn.Log - Check Log Message ${branch.body[0].body[0]} start_keyword + Should Be Equal ${branch.type} ${type} + Should Be Equal ${branch.status} ${status} + Length Should Be ${branch.body} 3 + Should Be Equal ${branch[0].full_name} BuiltIn.Log + Check Log Message ${branch[0, 0]} start_keyword IF $status == 'PASS' - Should Be Equal ${branch.body[1].name} BuiltIn.Log - Should Be Equal ${branch.body[1].body[0].name} BuiltIn.Log - Check Log Message ${branch.body[1].body[0].body[0]} start_keyword - Check Log Message ${branch.body[1].body[1]} else if branch - Should Be Equal ${branch.body[1].body[2].name} BuiltIn.Log - Check Log Message ${branch.body[1].body[2].body[0]} end_keyword + Should Be Equal ${branch[1].full_name} BuiltIn.Log + Should Be Equal ${branch[1, 0].full_name} BuiltIn.Log + Check Log Message ${branch[1, 0, 0]} start_keyword + Check Log Message ${branch[1, 1]} else if branch + Should Be Equal ${branch[1, 2].full_name} BuiltIn.Log + Check Log Message ${branch[1, 2, 0]} end_keyword ELSE - Should Be Equal ${branch.body[1].name} BuiltIn.Fail - Should Be Equal ${branch.body[1].status} NOT RUN + Should Be Equal ${branch[1].full_name} BuiltIn.Fail + Should Be Equal ${branch[1].status} NOT RUN END - Should Be Equal ${branch.body[-1].name} BuiltIn.Log - Check Log Message ${branch.body[-1].body[0]} end_keyword + Should Be Equal ${branch[-1].full_name} BuiltIn.Log + Check Log Message ${branch[-1,0]} end_keyword Validate FOR branch [Arguments] ${branch} ${type} ${status} - Should Be Equal ${branch.type} ${type} - Should Be Equal ${branch.status} ${status} - Should Be Equal ${branch.body[0].name} BuiltIn.Log - Check Log Message ${branch.body[0].body[0]} start_keyword - Should Be Equal ${branch.body[-1].name} BuiltIn.Log - Check Log Message ${branch.body[-1].body[0]} end_keyword + Should Be Equal ${branch.type} ${type} + Should Be Equal ${branch.status} ${status} + Should Be Equal ${branch[0].full_name} BuiltIn.Log + Check Log Message ${branch[0, 0]} start_keyword + Should Be Equal ${branch[-1].full_name} BuiltIn.Log + Check Log Message ${branch[-1,0]} end_keyword diff --git a/atest/robot/output/names_needing_escaping.robot b/atest/robot/output/names_needing_escaping.robot index b7942b154c8..50006670bf3 100644 --- a/atest/robot/output/names_needing_escaping.robot +++ b/atest/robot/output/names_needing_escaping.robot @@ -34,4 +34,4 @@ Check TC And UK Name [Arguments] ${name} ${tc} = Check Test Case ${name} Should Be Equal ${tc.name} ${name} - Should Be Equal ${tc.kws[0].name} ${name} + Should Be Equal ${tc[0].name} ${name} diff --git a/atest/robot/output/processing_output.robot b/atest/robot/output/processing_output.robot index 522772bc735..e7265026383 100644 --- a/atest/robot/output/processing_output.robot +++ b/atest/robot/output/processing_output.robot @@ -45,12 +45,19 @@ Minimal hand-created output My Run Robot And Rebot [Arguments] ${params} ${paths} Run Tests Without Processing Output ${params} ${paths} + Validate Elapsed In Output Copy Previous Outfile Run Rebot ${EMPTY} ${OUTFILE COPY} + Validate Elapsed In Output + +Validate Elapsed In Output + ${statuses} = Get Elements ${OUTFILE} .//status + FOR ${elem} IN @{statuses} + Should Match Regexp ${elem.attrib}[elapsed] ^\\d+\\.\\d+$ + END Check Normal Suite Defaults [Arguments] ${suite} ${message}= ${setup}=${None} ${teardown}=${None} - Log ${suite.name} Check Suite Defaults ${suite} ${message} ${setup} ${teardown} Check Normal Suite Times ${suite} @@ -61,27 +68,28 @@ Check Minimal Suite Defaults Check Normal Suite Times [Arguments] ${suite} - Timestamp Should Be Valid ${suite.starttime} - Timestamp Should Be Valid ${suite.endtime} - Elapsed Time Should Be Valid ${suite.elapsedtime} - Should Be True ${suite.elapsedtime} >= 1 + Timestamp Should Be Valid ${suite.start_time} + Timestamp Should Be Valid ${suite.end_time} + Elapsed Time Should Be Valid ${suite.elapsed_time} minimum=0.001 Check Minimal Suite Times [Arguments] ${suite} - Should Be Equal ${suite.starttime} ${NONE} - Should Be Equal ${suite.endtime} ${NONE} - Should Be Equal ${suite.elapsedtime} ${0} + Should Be Equal ${suite.start_time} ${NONE} + Should Be Equal ${suite.end_time} ${NONE} + Elapsed Time Should Be ${suite.elapsed_time} 0 Check Suite Defaults [Arguments] ${suite} ${message}= ${setup}=${None} ${teardown}=${None} - Should Be Equal ${suite.message} ${message} - Should Be Equal ${suite.setup.name} ${setup} - Should Be Equal ${suite.teardown.name} ${teardown} + Should Be Equal ${suite.message} ${message} + Should Be Equal ${suite.setup.full_name} ${setup} + Should Be Equal ${suite.teardown.full_name} ${teardown} Check Suite Got From Misc/suites/ Directory Check Normal Suite Defaults ${SUITE} teardown=BuiltIn.Log Should Be Equal ${SUITE.status} FAIL - Should Contain Suites ${SUITE} Suite With Prefix Fourth Subsuites Subsuites2 Suite With Double Underscore Tsuite1 Tsuite2 Tsuite3 + Should Contain Suites ${SUITE} Suite With Prefix Fourth Subsuites + ... Custom name for 📂 'subsuites2' Suite With Double Underscore + ... Tsuite1 Tsuite2 Tsuite3 Should Be Empty ${SUITE.tests} Should Contain Suites ${SUITE.suites[2]} Sub1 Sub2 FOR ${s} IN diff --git a/atest/robot/output/source_and_lineno_output.robot b/atest/robot/output/source_and_lineno_output.robot index 17c77812fae..0b8837406d8 100644 --- a/atest/robot/output/source_and_lineno_output.robot +++ b/atest/robot/output/source_and_lineno_output.robot @@ -2,6 +2,9 @@ Resource atest_resource.robot Suite Setup Run Tests ${EMPTY} misc/suites/subsuites2 +*** Variables *** +${SOURCE} ${{pathlib.Path(r'${DATADIR}/misc/suites/subsuites2')}} + *** Test Cases *** Suite source and test lineno in output after execution Source info should be correct @@ -13,10 +16,9 @@ Suite source and test lineno in output after Rebot *** Keywords *** Source info should be correct - ${source} = Normalize Path ${DATADIR}/misc/suites/subsuites2 - Should Be Equal ${SUITE.source} ${source} - Should Be Equal ${SUITE.suites[0].source} ${source}${/}sub.suite.4.robot + Should Be Equal ${SUITE.source} ${SOURCE} + Should Be Equal ${SUITE.suites[0].source} ${SOURCE / 'sub.suite.4.robot'} Should Be Equal ${SUITE.suites[0].tests[0].lineno} ${2} - Should Be Equal ${SUITE.suites[1].source} ${source}${/}subsuite3.robot - Should Be Equal ${SUITE.suites[1].tests[0].lineno} ${8} - Should Be Equal ${SUITE.suites[1].tests[1].lineno} ${13} + Should Be Equal ${SUITE.suites[1].source} ${SOURCE / 'subsuite3.robot'} + Should Be Equal ${SUITE.suites[1].tests[0].lineno} ${9} + Should Be Equal ${SUITE.suites[1].tests[1].lineno} ${14} diff --git a/atest/robot/output/statistics.robot b/atest/robot/output/statistics.robot index 9ab66e25f89..0190482c298 100644 --- a/atest/robot/output/statistics.robot +++ b/atest/robot/output/statistics.robot @@ -43,13 +43,13 @@ Combined Tag Statistics Name Can Be Given Tag Node Should Be Correct ${stats[0]} Combined tag with new name AND-OR-NOT ... 1 0 info=combined combined=d1 AND d2 -Suite statistics should be Correct +Suite statistics should be correct ${stats} = Get Element ${OUTFILE} statistics/suite Suite Node Should Be Correct ${stats[0]} Suites 12 1 Suite Node Should Be Correct ${stats[1]} Suites.Suite With Prefix 1 0 Suite Node Should Be Correct ${stats[2]} Suites.Fourth 0 1 Suite Node Should Be Correct ${stats[3]} Suites.Subsuites 2 0 - Suite Node Should Be Correct ${stats[4]} Suites.Subsuites2 3 0 + Suite Node Should Be Correct ${stats[4]} Suites.Custom name for 📂 'subsuites2' 3 0 Suite Node Should Be Correct ${stats[5]} Suites.Suite With Double Underscore 1 0 Suite Node Should Be Correct ${stats[6]} Suites.Tsuite1 3 0 Suite Node Should Be Correct ${stats[7]} Suites.Tsuite2 1 0 diff --git a/atest/robot/output/statistics_in_log_and_report.robot b/atest/robot/output/statistics_in_log_and_report.robot index 95ab992c2cc..d879fab6141 100644 --- a/atest/robot/output/statistics_in_log_and_report.robot +++ b/atest/robot/output/statistics_in_log_and_report.robot @@ -66,7 +66,7 @@ Verify suite stats ... id:s1-s2 pass:0 fail:1 skip:0 Verify stat ${stats[3]} label:Suites.Subsuites name:Subsuites ... id:s1-s3 pass:2 fail:0 skip:0 - Verify stat ${stats[4]} label:Suites.Subsuites2 name:Subsuites2 + Verify stat ${stats[4]} label:Suites.Custom name for 📂 'subsuites2' name:Custom name for 📂 'subsuites2' ... id:s1-s4 pass:3 fail:0 skip:0 Verify stat ${stats[5]} label:Suites.Suite With Double Underscore name:Suite With Double Underscore ... id:s1-s5 pass:1 fail:0 skip:0 diff --git a/atest/robot/output/statistics_with_rebot.robot b/atest/robot/output/statistics_with_rebot.robot index 9e83e99cf91..d71c8ecfdad 100644 --- a/atest/robot/output/statistics_with_rebot.robot +++ b/atest/robot/output/statistics_with_rebot.robot @@ -33,13 +33,13 @@ Tag statistics should be Correct Tag Node Should Be Correct ${stats[7]} XxX ... 12 1 -Suite statistics should be Correct +Suite statistics should be correct ${stats} = Get Element ${OUTFILE} statistics/suite Node Should Be Correct ${stats[0]} Suites 12 1 Node Should Be Correct ${stats[1]} Suites.Suite With Prefix 1 0 Node Should Be Correct ${stats[2]} Suites.Fourth 0 1 Node Should Be Correct ${stats[3]} Suites.Subsuites 2 0 - Node Should Be Correct ${stats[4]} Suites.Subsuites2 3 0 + Node Should Be Correct ${stats[4]} Suites.Custom name for 📂 'subsuites2' 3 0 Node Should Be Correct ${stats[5]} Suites.Suite With Double Underscore 1 0 Node Should Be Correct ${stats[6]} Suites.Tsuite1 3 0 Node Should Be Correct ${stats[7]} Suites.Tsuite2 1 0 diff --git a/atest/robot/output/xunit.robot b/atest/robot/output/xunit.robot index 82e28d590a1..25843cde935 100644 --- a/atest/robot/output/xunit.robot +++ b/atest/robot/output/xunit.robot @@ -18,7 +18,7 @@ XUnit File Is Created File Structure Is Correct ${root} = Get Root Node - Suite Stats Should Be ${root} 8 3 1 ${SUITE.starttime} + Suite Stats Should Be ${root} 8 3 1 ${SUITE.start_time} ${tests} = Get XUnit Nodes testcase Length Should Be ${tests} 8 ${fails} = Get XUnit Nodes testcase/failure @@ -29,7 +29,7 @@ File Structure Is Correct ${skips} = Get XUnit Nodes testcase/skipped Length Should Be ${skips} 1 Element Attribute Should Be ${skips}[0] message - ... Test failed but skip-on-failure mode was active and it was marked skipped.\n\nOriginal failure:\n${MESSAGES} + ... Failed test skipped using 'täg' tag.\n\nOriginal failure:\n${MESSAGES} Element Attribute Should Be ${skips}[0] type SkipExecution Element Should Not Exist ${root} testsuite/properties @@ -118,9 +118,9 @@ XUnit File Testsuite Properties From Metadata Element Attribute Should be ${property_elements}[0] name Escaping Element Attribute Should be ${property_elements}[0] value Three backslashes \\\\\\\ & \${version} Element Attribute Should be ${property_elements}[1] name Multiple columns - Element Attribute Should be ${property_elements}[1] value Value in multiple columns + Element Attribute Should be ${property_elements}[1] value Value in${SPACE*4}multiple${SPACE*4}columns Element Attribute Should be ${property_elements}[2] name multiple lines - Element Attribute Should be ${property_elements}[2] value Metadata in multiple lines\nis parsed using\nsame semantics as documentation.\n| table |\n| ! | + Element Attribute Should be ${property_elements}[2] value Metadata in multiple lines\nis parsed using\nsame semantics${SPACE*4}as${SPACE*4}documentation.\n| table |\n|${SPACE*3}!${SPACE*3}| Element Attribute Should be ${property_elements}[3] name Name Element Attribute Should be ${property_elements}[3] value Value Element Attribute Should be ${property_elements}[4] name Overridden @@ -144,14 +144,13 @@ Get XUnit Nodes RETURN ${nodes} Suite Stats Should Be - [Arguments] ${elem} ${tests} ${failures} ${skipped} ${starttime} + [Arguments] ${elem} ${tests} ${failures} ${skipped} ${start_time} Element Attribute Should Be ${elem} tests ${tests} Element Attribute Should Be ${elem} failures ${failures} Element Attribute Should Be ${elem} skipped ${skipped} Element Attribute Should Match ${elem} time ?.??? Element Attribute Should Be ${elem} errors 0 - Element Attribute Should Be ${elem} timestamp - ... ${{datetime.datetime.strptime($starttime, '%Y%m%d %H:%M:%S.%f').strftime('%Y-%m-%dT%H:%M:%S.%f')}} + Element Attribute Should Be ${elem} timestamp ${start_time.isoformat()} Verify Outputs Stderr should be empty diff --git a/atest/robot/parsing/caching_libs_and_resources.robot b/atest/robot/parsing/caching_libs_and_resources.robot index eed9f7c46de..4a543f8a3d0 100644 --- a/atest/robot/parsing/caching_libs_and_resources.robot +++ b/atest/robot/parsing/caching_libs_and_resources.robot @@ -18,16 +18,16 @@ Process Resource Files Only Once [Setup] Run Tests And Set $SYSLOG parsing/resource_parsing # Check that tests are run ok ${tc} = Check Test Case Test 1.1 - Check Log Message ${tc.kws[0].kws[0].msgs[0]} variable value from 02 resource - Check Log Message ${tc.kws[1].msgs[0]} variable value from 02 resource + Check Log Message ${tc[0, 0, 0]} variable value from 02 resource + Check Log Message ${tc[1, 0]} variable value from 02 resource ${tc} = Check Test Case Test 4.1 - Check Log Message ${tc.kws[0].kws[0].msgs[0]} variable value from 02 resource - Check Log Message ${tc.kws[1].msgs[0]} variable value from 02 resource + Check Log Message ${tc[0, 0, 0]} variable value from 02 resource + Check Log Message ${tc[1, 0]} variable value from 02 resource ${tc} = Check Test Case Test 4.2 - Check Log Message ${tc.kws[0].kws[0].msgs[0]} variable value from 03 resource - Check Log Message ${tc.kws[0].kws[1].msgs[0]} variable value from 02 resource - Check Log Message ${tc.kws[0].kws[2].kws[0].msgs[0]} variable value from 02 resource - Check Log Message ${tc.kws[1].msgs[0]} variable value from 03 resource + Check Log Message ${tc[0, 0, 0]} variable value from 03 resource + Check Log Message ${tc[0, 1, 0]} variable value from 02 resource + Check Log Message ${tc[0, 2, 0, 0]} variable value from 02 resource + Check Log Message ${tc[1, 0]} variable value from 03 resource ${dir} = Normalize Path ${DATADIR}/parsing/resource_parsing Should Contain X Times ${SYSLOG} Parsing file '${dir}${/}02_resource.robot' 1 Should Contain X Times ${SYSLOG} Parsing resource file '${dir}${/}02_resource.robot' 1 diff --git a/atest/robot/parsing/custom_parsers.robot b/atest/robot/parsing/custom_parsers.robot new file mode 100644 index 00000000000..9a6b59c3ec0 --- /dev/null +++ b/atest/robot/parsing/custom_parsers.robot @@ -0,0 +1,130 @@ +*** Settings *** +Resource atest_resource.robot + +*** Variables *** +${DIR} ${{pathlib.Path(r'${DATADIR}/parsing/custom')}} + +*** Test Cases *** +Single file + [Documentation] Also tests parser implemented as a module. + Run Tests --parser ${DIR}/custom.py ${DIR}/tests.custom + Validate Suite ${SUITE} Tests ${DIR}/tests.custom + ... Passing=PASS + ... Failing=FAIL:Error message + ... Empty=FAIL:Test cannot be empty. + +Directory + [Documentation] Also tests parser implemented as a class. + Run Tests --parser ${DIR}/CustomParser.py ${DIR} + Validate Directory Suite + +Directory with init + Run Tests --parser ${DIR}/CustomParser.py:init=True ${DIR} + Validate Directory Suite init=True + +Extension with multiple parts + [Documentation] Also tests usage with `--parse-include`. + Run Tests --parser ${DIR}/CustomParser.py:multi.part.ext --parse-include *.multi.part.ext ${DIR} + Validate Suite ${SUITE} Custom ${DIR} custom=False + ... Passing=PASS + Validate Suite ${SUITE.suites[0]} Tests ${DIR}/tests.multi.part.ext + ... Passing=PASS + +Override Robot parser + Run Tests --parser ${DIR}/CustomParser.py:.robot ${DIR}/tests.robot + Validate Suite ${SUITE} Tests ${DIR}/tests.robot + ... Test in Robot file=PASS + Run Tests --parser ${DIR}/CustomParser.py:ROBOT ${DIR} + Validate Suite ${SUITE} Custom ${DIR} custom=False + ... Test in Robot file=PASS + Validate Suite ${SUITE.suites[0]} Tests ${DIR}/tests.robot + ... Test in Robot file=PASS + +Multiple parsers + Run Tests --parser ${DIR}/CustomParser.py:ROBOT --PARSER ${DIR}/custom.py ${DIR} + Validate Directory Suite custom_robot=True + +Directory with init when parser does not support inits + Parsing Should Fail init + ... Parsing '${DIR}${/}__init__.init' failed: + ... 'CustomParser' does not support parsing initialization files. + +Incompatible parser + Parsing Should Fail parse=False + ... Importing parser '${DIR}${/}CustomParser.py' failed: + ... 'CustomParser' does not have mandatory 'parse' method. + Parsing Should Fail extension= + ... Importing parser '${DIR}${/}CustomParser.py' failed: + ... 'CustomParser' does not have mandatory 'EXTENSION' or 'extension' attribute. + +Failing parser + Parsing Should Fail fail=True + ... Parsing '${DIR}${/}more.custom' failed: + ... Calling 'CustomParser.parse()' failed: + ... TypeError: Ooops! + Parsing Should Fail fail=True:init=True + ... Parsing '${DIR}${/}__init__.init' failed: + ... Calling 'CustomParser.parse_init()' failed: + ... TypeError: Ooops in init! + +Bad return value + Parsing Should Fail bad_return=True + ... Parsing '${DIR}${/}more.custom' failed: + ... Calling 'CustomParser.parse()' failed: + ... TypeError: Return value should be 'robot.running.TestSuite', got 'string'. + Parsing Should Fail bad_return=True:init=True + ... Parsing '${DIR}${/}__init__.init' failed: + ... Calling 'CustomParser.parse_init()' failed: + ... TypeError: Return value should be 'robot.running.TestSuite', got 'integer'. + +*** Keywords *** +Validate Suite + [Arguments] ${suite} ${name} ${source} ${custom}=True &{tests} + ${source} = Normalize Path ${source} + Should Be Equal ${suite.name} ${name} + Should Be Equal As Strings ${suite.source} ${source} + IF ${custom} + Should Be Equal ${suite.metadata}[Parser] Custom + ELSE + Should Not Contain ${suite.metadata} Parser + END + Should Contain Tests ${suite} &{tests} + +Validate Directory Suite + [Arguments] ${init}=False ${custom_robot}=False + Validate Suite ${SUITE} ${{'📁' if ${init} else 'Custom'}} ${DIR} ${init} + ... Passing=PASS + ... Failing=FAIL:Error message + ... Empty=FAIL:Test cannot be empty. + ... Test in Robot file=PASS + ... Yet another test=PASS + Validate Suite ${SUITE.suites[0]} More ${DIR}/more.custom + ... Yet another test=PASS + Validate Suite ${SUITE.suites[1]} Tests ${DIR}/tests.custom + ... Passing=PASS + ... Failing=FAIL:Error message + ... Empty=FAIL:Test cannot be empty. + Validate Suite ${SUITE.suites[2]} Tests ${DIR}/tests.robot custom=${custom robot} + ... Test in Robot file=PASS + FOR ${test} IN @{SUITE.all_tests} + IF ${init} + Should Contain Tags ${test} tag from init + Should Be Equal ${test.timeout} 42 seconds + IF '${test.name}' != 'Empty' + Check Log Message ${test.setup[0]} setup from init + Check Log Message ${test.teardown[0]} teardown from init + END + ELSE + Should Not Be True ${test.tags} + Should Not Be True ${test.timeout} + Should Not Be True ${test.setup} + Should Not Be True ${test.teardown} + END + END + +Parsing should fail + [Arguments] ${config} @{error} + ${result} = Run Tests --parser ${DIR}/CustomParser.py:${config} ${DIR} output=None + ${error} = Catenate @{error} + Should Be Equal ${result.rc} ${252} + Should Be Equal ${result.stderr} [ ERROR ] ${error}${USAGETIP} diff --git a/atest/robot/parsing/data_formats/formats_resource.robot b/atest/robot/parsing/data_formats/formats_resource.robot index 376810d8caf..b1e12ed467d 100644 --- a/atest/robot/parsing/data_formats/formats_resource.robot +++ b/atest/robot/parsing/data_formats/formats_resource.robot @@ -7,6 +7,7 @@ ${TSV DIR} ${FORMATS DIR}/tsv ${TXT DIR} ${FORMATS DIR}/txt ${ROBOT DIR} ${FORMATS DIR}/robot ${REST DIR} ${FORMATS DIR}/rest +${JSON DIR} ${FORMATS DIR}/json ${MIXED DIR} ${FORMATS DIR}/mixed_data ${RESOURCE DIR} ${FORMATS DIR}/resources @{SAMPLE TESTS} Passing Failing User Keyword Nön-äscïï Own Tags Default Tags Variable Table @@ -32,7 +33,7 @@ Run Sample File And Check Tests ${test} = Check Test Case Test Timeout Should Be Equal ${test.timeout} 10 milliseconds ${test} = Check Test Case Keyword Timeout - Should Be Equal ${test.kws[0].timeout} 2 milliseconds + Should Be Equal ${test[0].timeout} 2 milliseconds Check Test Doc Document Testing the metadata parsing. ${test} = Check Test Case Default Fixture Setup Should Not Be Defined ${test} @@ -51,15 +52,17 @@ Run Suite Dir And Check Results Should Contain Suites ${SUITE.suites[1]} Sub Suite1 Sub Suite2 Should Contain Tests ${SUITE} @{SAMPLE_TESTS} @{SUBSUITE_TESTS} ${path} = Normalize Path ${path} - Syslog Should Contain | INFO \ | Data source '${path}${/}invalid.${type}' has no tests or tasks. - Syslog Should Contain | INFO \ | Data source '${path}${/}empty.${type}' has no tests or tasks. + IF $type != 'json' + Syslog Should Contain | INFO \ | Data source '${path}${/}invalid.${type}' has no tests or tasks. + Syslog Should Contain | INFO \ | Data source '${path}${/}empty.${type}' has no tests or tasks. + END Syslog Should Contain | INFO \ | Ignoring file or directory '${path}${/}not_a_picture.jpg'. Check Suite With Init [Arguments] ${suite} Should Be Equal ${suite.name} With Init Should Be Equal ${suite.doc} Testing suite init file - Check Log Message ${suite.setup.kws[0].messages[0]} Running suite setup + Check Log Message ${suite.setup[0].messages[0]} Running suite setup Teardown Should Not Be Defined ${suite} Should Contain Suites ${suite} Sub Suite1 Sub Suite2 Should Contain Tests ${suite} @{SUBSUITE_TESTS} diff --git a/atest/robot/parsing/data_formats/json.robot b/atest/robot/parsing/data_formats/json.robot new file mode 100644 index 00000000000..ebcae1ec497 --- /dev/null +++ b/atest/robot/parsing/data_formats/json.robot @@ -0,0 +1,32 @@ +*** Settings *** +Resource formats_resource.robot + +*** Test Cases *** +One JSON + Run sample file and check tests ${EMPTY} ${JSON DIR}/sample.rbt + +JSON With JSON Resource + Previous Run Should Have Been Successful + Check Test Case Resource File + +Invalid JSON Resource + Previous Run Should Have Been Successful + ${path} = Normalize Path atest/testdata/parsing/data_formats/json/sample.rbt + ${inva} = Normalize Path ${JSON DIR}/_invalid.json + Check Log Message ${ERRORS}[0] + ... Error in file '${path}' on line 12: Parsing JSON resource file '${inva}' failed: Loading JSON data failed: Invalid JSON data: * + ... level=ERROR pattern=True + +Invalid JSON Suite + ${result} = Run Tests ${EMPTY} ${JSON DIR}/_invalid.json output=None + Should Be Equal As Integers ${result.rc} 252 + ${path} = Normalize Path ${JSON DIR}/_invalid.json + Should Start With ${result.stderr} + ... [ ERROR ] Parsing '${path}' failed: Loading JSON data failed: Invalid JSON data: + +JSON Directory + Run Suite Dir And Check Results -F json:rbt ${JSON DIR} + +Directory With JSON Init + Previous Run Should Have Been Successful + Check Suite With Init ${SUITE.suites[1]} diff --git a/atest/robot/parsing/data_formats/resource_extensions.robot b/atest/robot/parsing/data_formats/resource_extensions.robot index d28e15c85a7..e168ea65964 100644 --- a/atest/robot/parsing/data_formats/resource_extensions.robot +++ b/atest/robot/parsing/data_formats/resource_extensions.robot @@ -5,11 +5,11 @@ Resource atest_resource.robot *** Test Cases *** Resource with '*.resource' extension ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[1].msgs[0]} nested.resource - Check Log Message ${tc.kws[0].kws[3].msgs[0]} resource.resource - Check Log Message ${tc.kws[1].kws[1].msgs[0]} nested.resource - Check Log Message ${tc.kws[4].msgs[0]} resource.resource - Check Log Message ${tc.kws[5].msgs[0]} nested.resource + Check Log Message ${tc[0, 0, 1, 0]} nested.resource + Check Log Message ${tc[0, 3, 0]} resource.resource + Check Log Message ${tc[1, 1, 0]} nested.resource + Check Log Message ${tc[4, 0]} resource.resource + Check Log Message ${tc[5, 0]} nested.resource '*.resource' files are not parsed for tests Should Contain Suites ${SUITE} Tests @@ -33,9 +33,15 @@ Resource with '*.rest' extension [Tags] require-docutils Check Test Case ${TESTNAME} +Resource with '*.rsrc' extension + Check Test Case ${TESTNAME} + +Resource with '*.json' extension + Check Test Case ${TESTNAME} + Resource with invalid extension Check Test Case ${TESTNAME} - Error in file 0 parsing/data_formats/resource_extensions/tests.robot 6 + Error in file 0 parsing/data_formats/resource_extensions/tests.robot 10 ... Invalid resource file extension '.invalid'. - ... Supported extensions are '.resource', '.robot', '.txt', '.tsv', '.rst' and '.rest'. + ... Supported extensions are '.json', '.resource', '.rest', '.robot', '.rsrc', '.rst', '.tsv' and '.txt'. Length should be ${ERRORS} 1 diff --git a/atest/robot/parsing/data_formats/rest.robot b/atest/robot/parsing/data_formats/rest.robot index 7120a31e463..6b13fb1bb58 100644 --- a/atest/robot/parsing/data_formats/rest.robot +++ b/atest/robot/parsing/data_formats/rest.robot @@ -5,15 +5,38 @@ Resource formats_resource.robot *** Test Cases *** One reST using code-directive Run sample file and check tests ${EMPTY} ${RESTDIR}/sample.rst - Stderr Should Be Empty ReST With reST Resource Previous Run Should Have Been Successful Check Test Case Resource File +Parsing errors have correct source + Previous Run Should Have Been Successful + Error in file 0 ${RESTDIR}/sample.rst 14 + ... Non-existing setting 'Invalid'. + Error in file 1 ${RESTDIR}/../resources/rest_directive_resource.rst 3 + ... Non-existing setting 'Invalid Resource'. + Length should be ${ERRORS} 2 + ReST Directory Run Suite Dir And Check Results -F rst:rest ${RESTDIR} Directory With reST Init Previous Run Should Have Been Successful Check Suite With Init ${SUITE.suites[1]} + +Parsing errors in init file have correct source + Previous Run Should Have Been Successful + Error in file 0 ${RESTDIR}/sample.rst 14 + ... Non-existing setting 'Invalid'. + Error in file 1 ${RESTDIR}/with_init/__init__.rst 4 + ... Non-existing setting 'Invalid Init'. + Error in file 2 ${RESTDIR}/../resources/rest_directive_resource.rst 3 + ... Non-existing setting 'Invalid Resource'. + Length should be ${ERRORS} 3 + +'.robot.rst' files are parsed automatically + Run Tests ${EMPTY} ${RESTDIR}/with_init + Should Be Equal ${SUITE.name} With Init + Should Be Equal ${SUITE.suites[0].name} Sub Suite2 + Should Contain Tests ${SUITE} Suite2 Test diff --git a/atest/robot/parsing/ignore_bom.robot b/atest/robot/parsing/ignore_bom.robot index c8bb2b799a6..6897f32c885 100644 --- a/atest/robot/parsing/ignore_bom.robot +++ b/atest/robot/parsing/ignore_bom.robot @@ -7,12 +7,12 @@ Resource atest_resource.robot Byte order mark in plain text file [Setup] File Should Have Bom parsing/bom.robot ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} Hyvää päivää €åppa! + Check log message ${tc[0, 0]} Hyvää päivää €åppa! Byte order mark in TSV file [Setup] File Should Have Bom parsing/bom.robot ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} Hyvää päivää €åppa! + Check log message ${tc[0, 0]} Hyvää päivää €åppa! *** Keywords *** File Should Have Bom diff --git a/atest/robot/parsing/line_continuation.robot b/atest/robot/parsing/line_continuation.robot index d90847facad..59b13411de2 100644 --- a/atest/robot/parsing/line_continuation.robot +++ b/atest/robot/parsing/line_continuation.robot @@ -1,5 +1,5 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} parsing/line_continuation.robot +Suite Setup Run Tests ${EMPTY} parsing/line_continuation.robot Resource atest_resource.robot *** Test Cases *** @@ -10,11 +10,11 @@ Multiline suite documentation and metadata Multiline suite level settings Should Contain Tags ${SUITE.tests[0]} ... ... t1 t2 t3 t4 t5 t6 t7 t8 t9 - Check Log Message ${SUITE.tests[0].teardown.msgs[0]} 1st - Check Log Message ${SUITE.tests[0].teardown.msgs[1]} ${EMPTY} - Check Log Message ${SUITE.tests[0].teardown.msgs[2]} 2nd last - Check Log Message ${SUITE.tests[0].teardown.msgs[3]} ${EMPTY} - Length Should Be ${SUITE.tests[0].teardown.msgs} 4 + Check Log Message ${SUITE.tests[0].teardown[0]} 1st + Check Log Message ${SUITE.tests[0].teardown[1]} ${EMPTY} + Check Log Message ${SUITE.tests[0].teardown[2]} 2nd last + Check Log Message ${SUITE.tests[0].teardown[3]} ${EMPTY} + Length Should Be ${SUITE.tests[0].teardown.body} 4 Multiline import Check Test Case ${TEST NAME} @@ -24,21 +24,21 @@ Multiline variables Multiline arguments with library keyword ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} one - Check Log Message ${tc.kws[0].msgs[1]} two - Check Log Message ${tc.kws[0].msgs[2]} three - Check Log Message ${tc.kws[0].msgs[3]} ${EMPTY} - Check Log Message ${tc.kws[0].msgs[4]} four - Check Log Message ${tc.kws[0].msgs[5]} five + Check Log Message ${tc[0, 0]} one + Check Log Message ${tc[0, 1]} two + Check Log Message ${tc[0, 2]} three + Check Log Message ${tc[0, 3]} ${EMPTY} + Check Log Message ${tc[0, 4]} four + Check Log Message ${tc[0, 5]} five Multiline arguments with user keyword ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} 1 - Check Log Message ${tc.kws[0].kws[0].msgs[1]} ${EMPTY} - Check Log Message ${tc.kws[0].kws[0].msgs[2]} 2 - Check Log Message ${tc.kws[0].kws[0].msgs[3]} 3 - Check Log Message ${tc.kws[0].kws[0].msgs[4]} 4 - Check Log Message ${tc.kws[0].kws[0].msgs[5]} 5 + Check Log Message ${tc[0, 0, 0]} 1 + Check Log Message ${tc[0, 0, 1]} ${EMPTY} + Check Log Message ${tc[0, 0, 2]} 2 + Check Log Message ${tc[0, 0, 3]} 3 + Check Log Message ${tc[0, 0, 4]} 4 + Check Log Message ${tc[0, 0, 5]} 5 Multiline assignment Check Test Case ${TEST NAME} @@ -50,18 +50,21 @@ Multiline test settings ${tc} = Check Test Case ${TEST NAME} @{expected} = Evaluate ['my'+str(i) for i in range(1,6)] Should Contain Tags ${tc} @{expected} - Should Be Equal ${tc.doc} One.\nTwo.\nThree.\n\nSecond paragraph. - Check Log Message ${tc.setup.msgs[0]} first - Check Log Message ${tc.setup.msgs[1]} ${EMPTY} - Check Log Message ${tc.setup.msgs[2]} last + Should Be Equal ${tc.doc} One.\nTwo.\nThree.\n\n${SPACE*32}Second paragraph. + Check Log Message ${tc.setup[0]} first + Check Log Message ${tc.setup[1]} ${EMPTY} + Check Log Message ${tc.setup[2]} last -Multiline user keyword settings - Check Test Case ${TEST NAME} +Multiline user keyword settings and control structures + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} Multiline user keyword settings and control structures + ... \${x} 1, 2 tags=keyword, tags + Check Log Message ${tc[0].teardown[0]} Bye! -Multiline for Loop declaration +Multiline FOR Loop declaration Check Test Case ${TEST NAME} -Multiline in for loop body +Multiline in FOR loop body Check Test Case ${TEST NAME} Escaped empty cells before line continuation do not work diff --git a/atest/robot/parsing/non_ascii_spaces.robot b/atest/robot/parsing/non_ascii_spaces.robot index c077abe9767..3a7743ec85d 100644 --- a/atest/robot/parsing/non_ascii_spaces.robot +++ b/atest/robot/parsing/non_ascii_spaces.robot @@ -5,19 +5,19 @@ Resource atest_resource.robot *** Test Cases *** In suite settings ${tc} = Check Test Case In test and keywords - Check Log Message ${tc.setup.kws[0].msgs[0]} ':\\xa0:' - Check Log Message ${tc.setup.kws[1].msgs[0]} : : - Check Log Message ${tc.teardown.kws[0].msgs[0]} ':\\u1680:' - Check Log Message ${tc.teardown.kws[1].msgs[0]} : : + Check Log Message ${tc.setup[0, 0]} ':\\xa0:' + Check Log Message ${tc.setup[1, 0]} : : + Check Log Message ${tc.teardown[0, 0]} ':\\u1680:' + Check Log Message ${tc.teardown[1, 0]} : : In test and keywords ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} ':\\xa0:' - Check Log Message ${tc.kws[0].kws[1].msgs[0]} : : - Check Log Message ${tc.kws[1].kws[0].msgs[0]} ':\\u1680:' - Check Log Message ${tc.kws[1].kws[1].msgs[0]} : : - Check Log Message ${tc.kws[2].kws[0].msgs[0]} ':\\u3000:' - Check Log Message ${tc.kws[2].kws[1].msgs[0]} : : + Check Log Message ${tc[0, 0, 0]} ':\\xa0:' + Check Log Message ${tc[0, 1, 0]} : : + Check Log Message ${tc[1, 0, 0]} ':\\u1680:' + Check Log Message ${tc[1, 1, 0]} : : + Check Log Message ${tc[2, 0, 0]} ':\\u3000:' + Check Log Message ${tc[2, 1, 0]} : : As separator Check Test Case ${TESTNAME} @@ -39,7 +39,10 @@ In FOR separator In ELSE IF ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.body[0].body[3].body[0].msgs[0]} Should be executed + Check Log Message ${tc[0, 3, 0, 0]} Should be executed In inline ELSE IF Check Test Case ${TESTNAME} + +With embedded arguments and BDD prefixes + Check Test Case ${TESTNAME} diff --git a/atest/robot/parsing/paths_are_not_case_normalized.robot b/atest/robot/parsing/paths_are_not_case_normalized.robot index b47e380b3dd..82a599a17ad 100644 --- a/atest/robot/parsing/paths_are_not_case_normalized.robot +++ b/atest/robot/parsing/paths_are_not_case_normalized.robot @@ -7,7 +7,7 @@ Suite name is not case normalized Should Be Equal ${SUITE.name} suiTe 8 Suite source should not be case normalized - Should End With ${SUITE.source} multiple_suites${/}suiTe_8.robot + Should Be True str($SUITE.source).endswith(r'multiple_suites${/}suiTe_8.robot') Outputs are not case normalized Stdout Should Contain ${/}LOG.html diff --git a/atest/robot/parsing/same_setting_multiple_times.robot b/atest/robot/parsing/same_setting_multiple_times.robot index 4e5c3224ff6..82854d277c9 100644 --- a/atest/robot/parsing/same_setting_multiple_times.robot +++ b/atest/robot/parsing/same_setting_multiple_times.robot @@ -5,111 +5,76 @@ Resource atest_resource.robot *** Test Cases *** Suite Documentation Should Be Equal ${SUITE.doc} S1 - Setting multiple times 0 3 Documentation Suite Metadata Should Be Equal ${SUITE.metadata['Foo']} M2 Suite Setup - Should Be Equal ${SUITE.setup.name} BuiltIn.Log Many - Setting multiple times 1 7 Suite Setup + Should Be Equal ${SUITE.setup.full_name} BuiltIn.Log Many Suite Teardown - Should Be Equal ${SUITE.teardown.name} BuiltIn.Comment - Setting multiple times 2 9 Suite Teardown + Should Be Equal ${SUITE.teardown.full_name} BuiltIn.Comment Force and Default Tags Check Test Tags Use Defaults D1 - Setting multiple times 7 18 Force Tags - Setting multiple times 8 19 Force Tags - Setting multiple times 9 21 Default Tags - Setting multiple times 10 22 Default Tags Test Setup ${tc} = Check Test Case Use Defaults - Should Be Equal ${tc.setup.name} BuiltIn.Log Many - Setting multiple times 3 11 Test Setup + Should Be Equal ${tc.setup.full_name} BuiltIn.Log Many Test Teardown ${tc} = Check Test Case Use Defaults Teardown Should Not Be Defined ${tc} - Setting multiple times 4 13 Test Teardown Test Template ${tc} = Check Test Case Use Defaults - Check Keyword Data ${tc.kws[0]} BuiltIn.Log Many args=Sleep, 0.1s - Setting multiple times 6 16 Test Template + Check Keyword Data ${tc[0]} BuiltIn.Log Many args=Sleep, 0.1s Test Timeout ${tc} = Check Test Case Use Defaults Should Be Equal ${tc.timeout} 1 second - Setting multiple times 11 24 Test Timeout Test [Documentation] ${tc} = Check Test Case Test Settings - Should Be Equal ${tc.doc} T1 - Setting multiple times 12 32 Documentation + Should Be Equal ${tc[0].type} ERROR + Should Be Equal ${tc[0].status} FAIL + Should Be Equal ${tc[0].values[0]} [Documentation] Test [Tags] Check Test Tags Test Settings - Setting multiple times 13 34 Tags - Setting multiple times 14 35 Tags Test [Setup] ${tc} = Check Test Case Test Settings - Should Be Equal ${tc.setup.name} BuiltIn.Log Many - Setting multiple times 15 37 Setup + Should Be Equal ${tc.setup.full_name} BuiltIn.Log Many Test [Teardown] ${tc} = Check Test Case Test Settings Teardown Should Not Be Defined ${tc} - Setting multiple times 16 39 Teardown - Setting multiple times 17 40 Teardown Test [Template] ${tc} = Check Test Case Test Settings - Check Keyword Data ${tc.kws[0]} BuiltIn.Log args=No Operation - Setting multiple times 18 42 Template + Check Keyword Data ${tc[7]} BuiltIn.Log args=No Operation Test [Timeout] ${tc} = Check Test Case Test Settings Should Be Equal ${tc.timeout} 2 seconds - Setting multiple times 19 44 Timeout Keyword [Arguments] ${tc} = Check Test Case Keyword Settings - Check Keyword Data ${tc.kws[0]} Keyword Settings assign=\${ret} args=1, 2, 3 tags=K1 - Check Log Message ${tc.kws[0].msgs[0]} Arguments: [ \${a1}='1' | \${a2}='2' | \${a3}='3' ] TRACE - Setting multiple times 20 55 Arguments + Check Keyword Data ${tc[0]} Keyword Settings assign=\${ret} args=1, 2, 3 tags=K1 status=FAIL + Check Log Message ${tc[0, 0]} Arguments: [ \${a1}='1' | \${a2}='2' | \${a3}='3' ] TRACE Keyword [Documentation] ${tc} = Check Test Case Keyword Settings - Should Be Equal ${tc.kws[0].doc} ${EMPTY} - Setting multiple times 21 57 Documentation - Setting multiple times 22 58 Documentation + Should Be Equal ${tc[0].doc} ${EMPTY} Keyword [Tags] ${tc} = Check Test Case Keyword Settings - Should Be True list($tc.kws[0].tags) == ['K1'] - Setting multiple times 23 60 Tags + Should Be True list($tc[0].tags) == ['K1'] Keyword [Timeout] ${tc} = Check Test Case Keyword Settings - Should Be Equal ${tc.kws[0].timeout} ${NONE} - Setting multiple times 24 62 Timeout - Setting multiple times 25 63 Timeout + Should Be Equal ${tc[0].timeout} ${NONE} Keyword [Return] - ${tc} = Check Test Case Keyword Settings - Check Log Message ${tc.kws[0].msgs[1]} Return: 'R0' TRACE - Check Log Message ${tc.kws[0].msgs[2]} \${ret} = R0 - Setting multiple times 26 66 Return - Setting multiple times 27 67 Return - Setting multiple times 28 68 Return - -*** Keywords *** -Setting multiple times - [Arguments] ${index} ${lineno} ${setting} - Error In File - ... ${index} parsing/same_setting_multiple_times.robot ${lineno} - ... Setting '${setting}' is allowed only once. Only the first value is used. + Check Test Case Keyword Settings diff --git a/atest/robot/parsing/spaces_and_tabs.robot b/atest/robot/parsing/spaces_and_tabs.robot index 1d514e1903a..f517f7239ae 100644 --- a/atest/robot/parsing/spaces_and_tabs.robot +++ b/atest/robot/parsing/spaces_and_tabs.robot @@ -14,16 +14,16 @@ Lot of spaces Trailing spaces ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} No spaces at end - Check Log Message ${tc.kws[1].msgs[0]} One space at end - Check Log Message ${tc.kws[2].msgs[0]} Two spaces at end - Check Log Message ${tc.kws[3].msgs[0]} Ten spaces at end - Check Log Message ${tc.kws[4].msgs[0]} Tab at end + Check Log Message ${tc[0, 0]} No spaces at end + Check Log Message ${tc[1, 0]} One space at end + Check Log Message ${tc[2, 0]} Two spaces at end + Check Log Message ${tc[3, 0]} Ten spaces at end + Check Log Message ${tc[4, 0]} Tab at end Tabs ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} I ignore tabs DEBUG + Check Log Message ${tc[0, 0]} I ignore tabs DEBUG Tabs and spaces ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} I ignore tabs (and spaces) DEBUG + Check Log Message ${tc[0, 0]} I ignore tabs (and spaces) DEBUG diff --git a/atest/robot/parsing/suite_metadata.robot b/atest/robot/parsing/suite_metadata.robot index 64b3162ddd1..b0e359f485e 100644 --- a/atest/robot/parsing/suite_metadata.robot +++ b/atest/robot/parsing/suite_metadata.robot @@ -12,14 +12,14 @@ Metadata NAME Value Metadata In Multiple Columns - Multiple columns Value in multiple columns + Multiple columns Value in${SPACE*4}multiple${SPACE*4}columns Metadata In Multiple Lines Multiple lines Metadata in multiple lines ... is parsed using - ... same semantics as documentation. + ... same semantics${SPACE*4}as${SPACE*4}documentation. ... | table | - ... | ! | + ... |${SPACE*3}!${SPACE*3}| Metadata With Variables Variables Version: 1.2 diff --git a/atest/robot/parsing/suite_names.robot b/atest/robot/parsing/suite_names.robot new file mode 100644 index 00000000000..329ff59104a --- /dev/null +++ b/atest/robot/parsing/suite_names.robot @@ -0,0 +1,45 @@ +*** Settings *** +Documentation Tests for default and custom suite names. +... Using `--name` is tested elsewhere. +Suite Setup Run Tests ${EMPTY} misc/suites misc/multiple_suites +Test Template Should Be Equal +Resource atest_resource.robot + +*** Test Cases *** +Combined suite name + ${SUITE.name} Suites & Multiple Suites + +Directory suite name + ${SUITE.suites[0].name} Suites + ${SUITE.suites[1].name} Multiple Suites + +File suite name + ${SUITE.suites[0].suites[1].name} Fourth + ${SUITE.suites[1].suites[9].name} Suite 9 Name + +Names with upper case chars are not title cased + ${SUITE.suites[1].suites[7].name} SUite7 + ${SUITE.suites[1].suites[8].name} suiTe 8 + ${SUITE.suites[1].suites[1].suites[1].name} .Sui.te.2. + +Spaces are preserved + ${SUITE.suites[1].suites[6].name} Suite 6 + +Dots in name + ${SUITE.suites[1].suites[1].name} Sub.Suite.1 + ${SUITE.suites[1].suites[1].suites[1].name} .Sui.te.2. + +Name with prefix + ${SUITE.suites[0].suites[0].name} Suite With Prefix + ${SUITE.suites[0].suites[0].suites[0].name} Tests With Prefix + ${SUITE.suites[1].suites[1].name} Sub.Suite.1 + +Name with double underscore at end + ${SUITE.suites[0].suites[4].name} Suite With Double Underscore + ${SUITE.suites[0].suites[4].suites[0].name} Tests With Double Underscore + +Custom directory suite name + ${SUITE.suites[0].suites[3].name} Custom name for 📂 'subsuites2' + +Custom file suite name + ${SUITE.suites[0].suites[3].suites[1].name} Custom name for 📜 'subsuite3.robot' diff --git a/atest/robot/parsing/suite_settings.robot b/atest/robot/parsing/suite_settings.robot index c890b0a0b4d..40a69865eee 100644 --- a/atest/robot/parsing/suite_settings.robot +++ b/atest/robot/parsing/suite_settings.robot @@ -7,7 +7,7 @@ Resource atest_resource.robot *** Test Cases *** Suite Name - Should Be Equal ${SUITE.name} Suite Settings + Should Be Equal ${SUITE.name} Custom name Suite Documentation ${doc} = Catenate SEPARATOR=\n @@ -16,11 +16,14 @@ Suite Documentation ... is shortdoc on console. ... ... Documentation can have multiple rows - ... and also multiple columns. + ... and${SPACE*4}also${SPACE*4}multiple${SPACE*4}columns. + ... ... Newlines can also be added literally with "\n". + ... If a row ends with a newline + ... or backslash no automatic newline is added. ... ... | table | =header= | - ... | foo | bar | + ... | foo${SPACE*3}|${SPACE*4}bar${SPACE*3}| ... | ragged | ... ... Variables work since Robot 1.2 and doc_from_cli works too. @@ -30,8 +33,8 @@ Suite Documentation Should Be Equal ${SUITE.doc} ${doc} Suite Name And Documentation On Console - Stdout Should Contain Suite Settings :: 1st logical line (i.e. paragraph) is shortdoc on console.${SPACE * 3}\n - Stdout Should Contain Suite Settings :: 1st logical line (i.e. paragraph) is shortdoc on... | PASS |\n + Stdout Should Contain Custom name :: 1st logical line (i.e. paragraph) is shortdoc on console.${SPACE * 6}\n + Stdout Should Contain Custom name :: 1st logical line (i.e. paragraph) is shortdoc on co... | PASS |\n Test Setup ${test} = Check Test Case Test Case @@ -51,11 +54,11 @@ Suite Teardown Verify Teardown ${SUITE} BuiltIn.Log Default suite teardown Invalid Setting - Error In File 0 parsing/suite_settings.robot 27 + Error In File 0 parsing/suite_settings.robot 32 ... Non-existing setting 'Invalid Setting'. Small typo should provide recommendation. - Error In File 1 parsing/suite_settings.robot 28 + Error In File 1 parsing/suite_settings.robot 33 ... SEPARATOR=\n ... Non-existing setting 'Megadata'. Did you mean: ... ${SPACE*4}Metadata @@ -71,5 +74,5 @@ Verify Teardown Verify Fixture [Arguments] ${fixture} ${expected_name} ${expected_message} - Should be Equal ${fixture.name} ${expected_name} + Should be Equal ${fixture.full_name} ${expected_name} Check Log Message ${fixture.messages[0]} ${expected_message} diff --git a/atest/robot/parsing/table_names.robot b/atest/robot/parsing/table_names.robot index 6224f229644..21d8109333e 100644 --- a/atest/robot/parsing/table_names.robot +++ b/atest/robot/parsing/table_names.robot @@ -3,47 +3,55 @@ Suite Setup Run Tests ${EMPTY} parsing/table_names.robot Resource atest_resource.robot *** Test Cases *** -Setting Table - Should Be Equal ${SUITE.doc} Testing different ways to write "Setting(s)". +Settings section + Should Be Equal ${SUITE.doc} Testing different ways to write "Settings". Check Test Tags Test Case Settings -Variable Table - Check First Log Entry Test Case Variable - Check First Log Entry Test Cases Variables +Variables section + Check First Log Entry Test Case Variables + Check First Log Entry Test Cases VARIABLES -Test Case Table +Test Cases section Check Test Case Test Case Check Test Case Test Cases -Keyword Table +Keywords section ${tc} = Check Test Case Test Case - Check Log Message ${tc.kws[1].kws[0].kws[0].msgs[0]} "Keywords" was executed + Check Log Message ${tc[1, 0, 0, 0]} "Keywords" was executed -Comment Table - Check Test Case Comment tables exist - Length Should Be ${ERRORS} 1 +Comments section + Check Test Case Comment section exist + Length Should Be ${ERRORS} 6 -Section Names Are Space Sensitive +Section names are space sensitive ${path} = Normalize Path ${DATADIR}/parsing/table_names.robot Invalid Section Error 0 table_names.robot 43 * * * K e y w o r d * * * -Invalid Tables +Singular headers are deprecated + Should Be Equal ${SUITE.metadata['Singular headers']} Deprecated + Check Test Case Singular headers are deprecated + Deprecated Section Warning 1 table_names.robot 47 *** Setting *** *** Settings *** + Deprecated Section Warning 2 table_names.robot 49 *** variable*** *** Variables *** + Deprecated Section Warning 3 table_names.robot 51 ***TEST CASE*** *** Test Cases *** + Deprecated Section Warning 4 table_names.robot 54 *keyword *** Keywords *** + Deprecated Section Warning 5 table_names.robot 57 *** Comment *** *** Comments *** + +Invalid sections [Setup] Run Tests ${EMPTY} parsing/invalid_table_names.robot ${tc} = Check Test Case Test in valid table - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Keyword in valid table - Check Log Message ${tc.kws[1].kws[0].msgs[0]} Keyword in valid table in resource - Length Should Be ${ERRORS} 5 + ${path} = Normalize Path ${DATADIR}/parsing/invalid_tables_resource.robot + Check Log Message ${tc[0, 0, 0]} Keyword in valid table + Length Should Be ${ERRORS} 4 Invalid Section Error 0 invalid_table_names.robot 1 *** Error *** Invalid Section Error 1 invalid_table_names.robot 8 *** *** - Invalid Section Error 2 invalid_table_names.robot 17 *one more table cause an error - Invalid Section Error 3 invalid_tables_resource.robot 1 *** *** test and task= - Invalid Section Error 4 invalid_tables_resource.robot 10 ***Resource Error*** test and task= + Invalid Section Error 2 invalid_table_names.robot 18 *one more table cause an error + Error In File 3 parsing/invalid_table_names.robot 6 Error in file '${path}' on line 1: Unrecognized section header '*** ***'. Valid sections: 'Settings', 'Variables', 'Keywords' and 'Comments'. *** Keywords *** Check First Log Entry [Arguments] ${test case name} ${expected} ${tc} = Check Test Case ${test case name} - Check Log Message ${tc.kws[0].msgs[0]} ${expected} + Check Log Message ${tc[0, 0]} ${expected} Invalid Section Error [Arguments] ${index} ${file} ${lineno} ${header} ${test and task}=, 'Test Cases', 'Tasks' @@ -51,3 +59,9 @@ Invalid Section Error ... Unrecognized section header '${header}'. ... Valid sections: 'Settings', 'Variables'${test and task}, ... 'Keywords' and 'Comments'. + +Deprecated Section Warning + [Arguments] ${index} ${file} ${lineno} ${used} ${expected} + Error In File ${index} parsing/${file} ${lineno} + ... Singular section headers like '${used}' are deprecated. Use plural format like '${expected}' instead. + ... level=WARN diff --git a/atest/robot/parsing/test_case_settings.robot b/atest/robot/parsing/test_case_settings.robot index d366d9656bc..b321b6df9ea 100644 --- a/atest/robot/parsing/test_case_settings.robot +++ b/atest/robot/parsing/test_case_settings.robot @@ -42,17 +42,21 @@ Documentation Verify Documentation Documentation in single line and column. Documentation in multiple columns - Verify Documentation Documentation for this test case in multiple columns + Verify Documentation Documentation${SPACE*4}for this test case${SPACE*4}in multiple columns Documentation in multiple rows Verify Documentation 1st logical line ... is shortdoc. ... ... This documentation has multiple rows - ... and also multiple columns. + ... and also${SPACE*4}multiple columns. + ... + ... Newlines can also be added literally with "\n". + ... If a row ends with a newline + ... or backslash no automatic newline is added. ... ... | table | =header= | - ... | foo | bar | + ... | foo${SPACE*3}|${SPACE*4}bar${SPACE*3}| ... | ragged | Documentation with variables @@ -87,7 +91,7 @@ Empty and NONE tags are ignored Duplicate tags are ignored and first used format has precedence [Documentation] Case, space and underscore insensitive - Verify Tags FORCE-1 Test_1 test 2 + Verify Tags force-1 Test_1 test 2 Tags in multiple rows Verify Tags force-1 test-0 test-1 test-2 test-3 test-4 test-5 @@ -141,17 +145,12 @@ Setup and teardown with escaping Template [Documentation] Mainly tested elsewhere ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Hello, world! - Check Log Message ${tc.kws[1].msgs[0]} Hi, tellus! + Check Log Message ${tc[0, 0]} Hello, world! + Check Log Message ${tc[1, 0]} Hi, tellus! Timeout Verify Timeout 1 day -Timeout with message - Verify Timeout 1 minute 39 seconds 999 milliseconds - Error In File 0 parsing/test_case_settings.robot 184 - ... Setting 'Timeout' accepts only one value, got 2. - Default timeout Verify Timeout 1 minute 39 seconds 999 milliseconds @@ -176,15 +175,13 @@ Multiple settings Invalid setting Check Test Case ${TEST NAME} - Error In File 1 parsing/test_case_settings.robot 217 - ... Non-existing setting 'Invalid'. + +Setting not valid with tests + Check Test Case ${TEST NAME} Small typo should provide recommendation - Check Test Doc ${TEST NAME} - Error In File 2 parsing/test_case_settings.robot 221 - ... SEPARATOR=\n - ... Non-existing setting 'Doc U ment a tion'. Did you mean: - ... ${SPACE*4}Documentation + Check Test Case ${TEST NAME} + *** Keywords *** Verify Documentation @@ -200,14 +197,14 @@ Verify Tags Verify Setup [Arguments] ${message} ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.setup.name} BuiltIn.Log - Check Log Message ${tc.setup.msgs[0]} ${message} + Should Be Equal ${tc.setup.full_name} BuiltIn.Log + Check Log Message ${tc.setup[0]} ${message} Verify Teardown [Arguments] ${message} ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.teardown.name} BuiltIn.Log - Check Log Message ${tc.teardown.msgs[0]} ${message} + Should Be Equal ${tc.teardown.full_name} BuiltIn.Log + Check Log Message ${tc.teardown[0]} ${message} Verify Timeout [Arguments] ${timeout} diff --git a/atest/robot/parsing/test_suite_names.robot b/atest/robot/parsing/test_suite_names.robot deleted file mode 100644 index 278160739de..00000000000 --- a/atest/robot/parsing/test_suite_names.robot +++ /dev/null @@ -1,47 +0,0 @@ -*** Settings *** -Suite Setup Run Tests ${EMPTY} misc/multiple_suites -Resource atest_resource.robot -Documentation Giving suite names from commandline is tested in robot/cli/runner/suite_name_doc_and_metadata.txt - - -*** Test Cases *** -Root Directory Suite Name - Should Be Equal ${SUITE.name} Multiple Suites - -Prefix Is Removed From File Suite Name - Should Be Equal ${SUITE.suites[0].name} Suite First - -Prefix Is Removed From Directory Suite Name - Should Be Equal ${SUITE.suites[1].name} Sub.Suite.1 - -Child File Suite Name - Should Be Equal ${SUITE.suites[6].name} Suite 6 - -Child Directory Suite Name - Should Be Equal ${SUITE.suites[1].name} Sub.Suite.1 - -Dots in suite names - Should Be Equal ${SUITE.suites[1].name} Sub.Suite.1 - Should Be Equal ${SUITE.suites[1].suites[1].name} .Sui.te.2. - -Names without uppercase chars are titlecased - Should Be Equal ${SUITE.suites[1].name} Sub.Suite.1 - Should Be Equal ${SUITE.suites[6].name} Suite 6 - Should Be Equal ${SUITE.suites[9].name} Suite 9 Name - -Names with uppercase chars are not titlecased - Should Be Equal ${SUITE.suites[7].name} SUite7 - Should Be Equal ${SUITE.suites[8].name} suiTe 8 - Should Be Equal ${SUITE.suites[1].suites[1].name} .Sui.te.2. - -Underscores are converted to spaces - Should Be Equal ${SUITE.suites[8].name} suiTe 8 - Should Be Equal ${SUITE.suites[9].name} Suite 9 Name - -Spaces are preserved - Should Be Equal ${SUITE.suites[6].name} Suite 6 - -Root File Suite Name - [Setup] Run Tests ${EMPTY} misc/pass_and_fail.robot - Should Be Equal ${SUITE.name} Pass And Fail - diff --git a/atest/robot/parsing/translations.robot b/atest/robot/parsing/translations.robot new file mode 100644 index 00000000000..ebf6386d6e0 --- /dev/null +++ b/atest/robot/parsing/translations.robot @@ -0,0 +1,108 @@ +*** Settings *** +Resource atest_resource.robot + +*** Test Cases *** +Finnish + Run Tests --language fi parsing/translations/finnish/tests.robot + Validate Translations + +Finnish task aliases + [Documentation] + ... Also tests that + ... - '--language' works when running a directory, + ... - it is possible to use language class docstring, and + ... - '-' is ignored in the given name to support e.g. 'pt-br'. + Run Tests --language fin-nish --rpa parsing/translations/finnish + Validate Task Translations + +Custom + Run Tests --lang ${DATADIR}/parsing/translations/custom/custom.py parsing/translations/custom/tests.robot + Validate Translations + +Custom task aliases + Run Tests --lang ${DATADIR}/parsing/translations/custom/custom.py --rpa parsing/translations/custom/tasks.robot + Validate Task Translations + +Custom Per file configuration + Run Tests -P ${DATADIR}/parsing/translations/custom parsing/translations/custom/custom_per_file.robot + Validate Translations + +Invalid + ${result} = Run Tests Without Processing Output --lang bad parsing/finnish.robot + Should Be Equal ${result.rc} ${252} + Should Be Empty ${result.stdout} + ${error} = Catenate SEPARATOR=\n + ... Invalid value for option '--language': Importing language file 'bad' failed: ModuleNotFoundError: No module named 'bad' + ... Traceback \\(most recent call last\\): + ... .*${USAGE TIP} + Should Match Regexp ${result.stderr} ^\\[ ERROR \\] ${error}$ flags=DOTALL + +Per file configuration + Run Tests ${EMPTY} parsing/translations/per_file_config/fi.robot + Validate Translations + +Per file configuration with multiple languages + Run Tests ${EMPTY} parsing/translations/per_file_config/many.robot + Should Be Equal ${SUITE.doc} Exemplo + ${tc} = Check Test Case ตัวอย่าง + Should Be Equal ${tc.doc} приклад + +Invalid per file configuration + Error in file 0 parsing/translations/per_file_config/many.robot 4 + ... Invalid language configuration: + ... Language 'invalid' not found nor importable as a language module. + Error in file 1 parsing/translations/per_file_config/many.robot 5 + ... Invalid language configuration: + ... Language 'another invalid value' not found nor importable as a language module. + +Per file configuration bleeds to other files + [Documentation] This is a technical limitation and will hopefully change! + Run Tests ${EMPTY} parsing/translations/per_file_config/fi.robot parsing/translations/finnish/tests.robot + Validate Translations ${SUITE.suites[0]} + Validate Translations ${SUITE.suites[1]} + +*** Keywords *** +Validate Translations + [Arguments] ${suite}=${SUITE} + Should Be Equal ${suite.name} Custom name + Should Be Equal ${suite.doc} Suite documentation. + Should Be Equal ${suite.metadata}[Metadata] Value + Should Be Equal ${suite.setup.full_name} Suite Setup + Should Be Equal ${suite.teardown.full_name} Suite Teardown + Should Be Equal ${suite.status} PASS + ${tc} = Check Test Case Test without settings + Should Be Equal ${tc.doc} ${EMPTY} + Should Be Equal ${tc.tags} ${{['test', 'tags']}} + Should Be Equal ${tc.timeout} 1 minute + Should Be Equal ${tc.setup.full_name} Test Setup + Should Be Equal ${tc.teardown.full_name} Test Teardown + Should Be Equal ${tc[0].full_name} Test Template + Should Be Equal ${tc[0].tags} ${{['keyword', 'tags']}} + ${tc} = Check Test Case Test with settings + Should Be Equal ${tc.doc} Test documentation. + Should Be Equal ${tc.tags} ${{['test', 'tags', 'own tag']}} + Should Be Equal ${tc.timeout} ${NONE} + Should Be Equal ${tc.setup.full_name} ${NONE} + Should Be Equal ${tc.teardown.full_name} ${NONE} + Should Be Equal ${tc[0].full_name} Keyword + Should Be Equal ${tc[0].doc} Keyword documentation. + Should Be Equal ${tc[0].tags} ${{['keyword', 'tags', 'own tag']}} + Should Be Equal ${tc[0].timeout} 1 hour + Should Be Equal ${tc[0].setup.full_name} BuiltIn.Log + Should Be Equal ${tc[0].teardown.full_name} BuiltIn.No Operation + +Validate Task Translations + ${tc} = Check Test Case Task without settings + Should Be Equal ${tc.doc} ${EMPTY} + Should Be Equal ${tc.tags} ${{['task', 'tags']}} + Should Be Equal ${tc.timeout} 1 minute + Should Be Equal ${tc.setup.full_name} Task Setup + Should Be Equal ${tc.teardown.full_name} Task Teardown + Should Be Equal ${tc[0].full_name} Task Template + ${tc} = Check Test Case Task with settings + Should Be Equal ${tc.doc} Task documentation. + Should Be Equal ${tc.tags} ${{['task', 'tags', 'own tag']}} + Should Be Equal ${tc.timeout} ${NONE} + Should Be Equal ${tc.setup.full_name} ${NONE} + Should Be Equal ${tc.teardown.full_name} ${NONE} + Should Be Equal ${tc[0].full_name} BuiltIn.Log diff --git a/atest/robot/parsing/user_keyword_settings.robot b/atest/robot/parsing/user_keyword_settings.robot index bad894c487d..8ab9eaec0ea 100644 --- a/atest/robot/parsing/user_keyword_settings.robot +++ b/atest/robot/parsing/user_keyword_settings.robot @@ -5,12 +5,12 @@ Resource atest_resource.robot *** Test Cases *** Name ${tc} = Check Test Case Normal name - Should Be Equal ${tc.kws[0].name} Normal name + Should Be Equal ${tc[0].full_name} Normal name Names are not formatted ${tc} = Check Test Case Names are not formatted - FOR ${kw} IN @{tc.kws} - Should Be Equal ${kw.name} user_keyword nameS _are_not_ FORmatted + FOR ${kw} IN @{tc.body} + Should Be Equal ${kw.full_name} user_keyword nameS _are_not_ FORmatted END No documentation @@ -20,7 +20,7 @@ Documentation Verify Documentation Documentation for this user keyword Documentation in multiple columns - Verify Documentation Documentation for this user keyword in multiple columns + Verify Documentation Documentation${SPACE * 4}for this user keyword${SPACE*10}in multiple columns Documentation in multiple rows Verify Documentation 1st line is shortdoc. @@ -43,19 +43,19 @@ Documentation with escaping Arguments [Documentation] Tested more thoroughly elsewhere. ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} mandatory - Check Log Message ${tc.kws[0].kws[0].msgs[1]} default - Should Be True ${tc.kws[0].args} == ('mandatory',) - Check Log Message ${tc.kws[1].kws[0].msgs[0]} 1 - Check Log Message ${tc.kws[1].kws[0].msgs[1]} 2 - Should Be True ${tc.kws[1].args} == ('1', '2') - Check Log Message ${tc.kws[2].kws[0].msgs[0]} 1 - Check Log Message ${tc.kws[2].kws[0].msgs[1]} 2 - Check Log Message ${tc.kws[2].kws[0].msgs[2]} 3 - Check Log Message ${tc.kws[2].kws[0].msgs[3]} 4 - Check Log Message ${tc.kws[2].kws[0].msgs[4]} 5 - Check Log Message ${tc.kws[2].kws[0].msgs[5]} key=6 - Should Be True ${tc.kws[2].args} == ('\${1}', '\${2}', '\${3}', '\${4}', '\${5}', 'key=\${6}') + Check Log Message ${tc[0, 0, 0]} mandatory + Check Log Message ${tc[0, 0, 1]} default + Should Be True ${tc[0].args} == ('mandatory',) + Check Log Message ${tc[1, 0, 0]} 1 + Check Log Message ${tc[1, 0, 1]} 2 + Should Be True ${tc[1].args} == ('1', '2') + Check Log Message ${tc[2, 0, 0]} 1 + Check Log Message ${tc[2, 0, 1]} 2 + Check Log Message ${tc[2, 0, 2]} 3 + Check Log Message ${tc[2, 0, 3]} 4 + Check Log Message ${tc[2, 0, 4]} 5 + Check Log Message ${tc[2, 0, 5]} key=6 + Should Be True ${tc[2].args} == ('\${1}', '\${2}', '\${3}', '\${4}', '\${5}', 'key=\${6}') Teardown Verify Teardown Keyword teardown @@ -67,16 +67,33 @@ Teardown with escaping Verify Teardown \${notvar} is not a variable Return - Check Test Case ${TEST NAME} + [Documentation] [Return] is deprecated. In parsing it is transformed to RETURN. + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0, 0].type} RETURN + Should Be Equal ${tc[0, 0].values} ${{('Return value',)}} + Error in File 0 parsing/user_keyword_settings.robot 167 + ... The '[[]Return]' setting is deprecated. Use the 'RETURN' statement instead. level=WARN Return using variables - Check Test Case ${TEST NAME} + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0, 1].type} RETURN + Should Be Equal ${tc[0, 1].values} ${{('\${ret}',)}} + Error in File 1 parsing/user_keyword_settings.robot 171 + ... The '[[]Return]' setting is deprecated. Use the 'RETURN' statement instead. level=WARN Return multiple - Check Test Case ${TEST NAME} + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0, 1].type} RETURN + Should Be Equal ${tc[0, 1].values} ${{('\${arg1}', '+', '\${arg2}', '=', '\${result}')}} + Error in File 2 parsing/user_keyword_settings.robot 176 + ... The '[[]Return]' setting is deprecated. Use the 'RETURN' statement instead. level=WARN Return with escaping - Check Test Case ${TEST NAME} + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0, 0].type} RETURN + Should Be Equal ${tc[0, 0].values} ${{('\\\${XXX}', 'c:\\\\temp', '\\', '\\\\')}} + Error in File 3 parsing/user_keyword_settings.robot 179 + ... The '[[]Return]' setting is deprecated. Use the 'RETURN' statement instead. level=WARN Timeout Verify Timeout 2 minutes 3 seconds @@ -89,41 +106,36 @@ Invalid timeout Multiple settings Verify Documentation Documentation for a user keyword - Verify Teardown Teardown World - Verify Timeout 6 minutes + Verify Teardown Teardown World + Verify Timeout 6 minutes Invalid setting Check Test Case ${TEST NAME} - Error In File 0 parsing/user_keyword_settings.robot 195 - ... Non-existing setting 'Invalid Setting'. - Error In File 1 parsing/user_keyword_settings.robot 199 - ... Non-existing setting 'invalid'. -Small typo should provide recommendation +Setting not valid with user keywords Check Test Case ${TEST NAME} - Error In File 2 parsing/user_keyword_settings.robot 203 - ... SEPARATOR=\n - ... Non-existing setting 'Doc Umentation'. Did you mean: - ... ${SPACE*4}Documentation -Invalid empty line continuation in arguments should throw an error - Error in File 3 parsing/user_keyword_settings.robot 206 - ... Creating keyword 'Invalid empty line continuation in arguments should throw an error' failed: Invalid argument specification: Invalid argument syntax ''. +Small typo should provide recommendation + Check Test Case ${TEST NAME} +Invalid empty line continuation in arguments should throw an error + Error in File 4 parsing/user_keyword_settings.robot 214 + ... Creating keyword 'Invalid empty line continuation in arguments should throw an error' failed: + ... Invalid argument specification: Invalid argument syntax ''. *** Keywords *** Verify Documentation [Arguments] ${doc} ${test}=${TEST NAME} ${tc} = Check Test Case ${test} - Should Be Equal ${tc.kws[0].doc} ${doc} + Should Be Equal ${tc[0].doc} ${doc} Verify Teardown [Arguments] ${message} ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].teardown.name} BuiltIn.Log - Check Log Message ${tc.kws[0].teardown.msgs[0]} ${message} + Should Be Equal ${tc[0].teardown.full_name} BuiltIn.Log + Check Log Message ${tc[0].teardown[0]} ${message} Verify Timeout [Arguments] ${timeout} ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].timeout} ${timeout} + Should Be Equal ${tc[0].timeout} ${timeout} diff --git a/atest/robot/parsing/utf8_data/utf8_in_tsv.robot b/atest/robot/parsing/utf8_data/utf8_in_tsv.robot index 5cf83c7bd4a..8b63e3cd8cf 100644 --- a/atest/robot/parsing/utf8_data/utf8_in_tsv.robot +++ b/atest/robot/parsing/utf8_data/utf8_in_tsv.robot @@ -1,25 +1,25 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} parsing/utf8_data.tsv -Resource atest_resource.robot +Suite Setup Run Tests ${EMPTY} parsing/utf8_data.tsv +Resource atest_resource.robot *** Test Cases *** UTF-8 In Metadata - Should Be Equal ${SUITE.doc} Testing that reading and writing of Unicode (äöå §½€ etc.) works properly. - Should Be Equal as Strings ${SUITE.metadata} {Ä: §} - Check Test Tags UTF-8 tag-§ tag-€ - Check Test Doc UTF-8 äöå §½€ + Should Be Equal ${SUITE.doc} Testing that reading and writing of Unicode (äöå §½€ etc.) works properly. + Should Be Equal As Strings ${SUITE.metadata} {Ä: §} + Check Test Tags UTF-8 tag-§ tag-€ + Check Test Doc UTF-8 äöå §½€ UTF-8 In Keyword Arguments - ${tc} = Check Test Case UTF-8 - Check Log Message ${tc.setup.msgs[0]} äöå - Check Log Message ${tc.kws[0].msgs[0]} §½€ - Check Log Message ${tc.kws[1].msgs[0]} äöå §½€ - Check Log Message ${tc.kws[2].kws[0].msgs[0]} äöå - Check Log Message ${tc.kws[2].kws[1].msgs[0]} äöå §½€ - Check Log Message ${tc.kws[2].kws[2].msgs[0]} §½€ + ${tc} = Check Test Case UTF-8 + Check Log Message ${tc.setup[0]} äöå + Check Log Message ${tc[0, 0]} §½€ + Check Log Message ${tc[1, 0]} äöå §½€ + Check Log Message ${tc[2, 0, 0]} äöå + Check Log Message ${tc[2, 1, 0]} äöå §½€ + Check Log Message ${tc[2, 2, 0]} §½€ UTF-8 In Test Case And UK Names - ${tc} = Check Test Case UTF-8 Name Äöå §½€" - Check Keyword Data ${tc.kws[0]} Äöå §½€ \${ret} - Check Log Message ${tc.kws[1].msgs[0]} äöå §½€ - Check Log Message ${tc.kws[3].msgs[0]} value + ${tc} = Check Test Case UTF-8 Name Äöå §½€" + Check Keyword Data ${tc[0]} Äöå §½€ \${ret} + Check Log Message ${tc[1, 0]} äöå §½€ + Check Log Message ${tc[3, 0]} value diff --git a/atest/robot/parsing/utf8_data/utf8_in_txt.robot b/atest/robot/parsing/utf8_data/utf8_in_txt.robot index fca9e1856d3..c22049aa238 100644 --- a/atest/robot/parsing/utf8_data/utf8_in_txt.robot +++ b/atest/robot/parsing/utf8_data/utf8_in_txt.robot @@ -1,25 +1,25 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} parsing/utf8_data.robot -Resource atest_resource.robot +Suite Setup Run Tests ${EMPTY} parsing/utf8_data.robot +Resource atest_resource.robot *** Test Cases *** UTF-8 In Metadata - Should Be Equal ${SUITE.doc} Testing that reading and writing of Unicode (äöå §½€ etc.) works properly. - Should Be Equal as Strings ${SUITE.metadata} {Ä: §} - Check Test Tags UTF-8 tag-§ tag-€ - Check Test Doc UTF-8 äöå §½€ + Should Be Equal ${SUITE.doc} Testing that reading and writing of Unicode (äöå §½€ etc.) works properly. + Should Be Equal As Strings ${SUITE.metadata} {Ä: §} + Check Test Tags UTF-8 tag-§ tag-€ + Check Test Doc UTF-8 äöå §½€ UTF-8 In Keyword Arguments - ${tc} = Check Test Case UTF-8 - Check Log Message ${tc.setup.msgs[0]} äöå - Check Log Message ${tc.kws[0].msgs[0]} §½€ - Check Log Message ${tc.kws[1].msgs[0]} äöå §½€ - Check Log Message ${tc.kws[2].kws[0].msgs[0]} äöå - Check Log Message ${tc.kws[2].kws[1].msgs[0]} äöå §½€ - Check Log Message ${tc.kws[2].kws[2].msgs[0]} §½€ + ${tc} = Check Test Case UTF-8 + Check Log Message ${tc.setup[0]} äöå + Check Log Message ${tc[0, 0]} §½€ + Check Log Message ${tc[1, 0]} äöå §½€ + Check Log Message ${tc[2, 0, 0]} äöå + Check Log Message ${tc[2, 1, 0]} äöå §½€ + Check Log Message ${tc[2, 2, 0]} §½€ UTF-8 In Test Case And UK Names - ${tc} = Check Test Case UTF-8 Name Äöå §½€" - Check Keyword Data ${tc.kws[0]} Äöå §½€ \${ret} - Check Log Message ${tc.kws[1].msgs[0]} äöå §½€ - Check Log Message ${tc.kws[3].msgs[0]} value + ${tc} = Check Test Case UTF-8 Name Äöå §½€" + Check Keyword Data ${tc[0]} Äöå §½€ \${ret} + Check Log Message ${tc[1, 0]} äöå §½€ + Check Log Message ${tc[3, 0]} value diff --git a/atest/robot/rebot/combine.robot b/atest/robot/rebot/combine.robot index 02612e85ab3..f8aedbd16ad 100644 --- a/atest/robot/rebot/combine.robot +++ b/atest/robot/rebot/combine.robot @@ -81,49 +81,34 @@ Suite Metadata Should Be Equal ${SUITE2.metadata['Other Meta']} Another value Suite Times - Should Be Equal ${SUITE3.starttime} ${NONE} - Should Be Equal ${SUITE3.endtime} ${NONE} - Elapsed Time Should Be Valid ${SUITE3.elapsedtime} - Should Be True ${SUITE3.elapsedtime} == ${MILLIS1} + ${MILLIS2} + 9999 - Timestamp Should Be Valid ${SUITE3.suites[0].starttime} - Timestamp Should Be Valid ${SUITE3.suites[0].endtime} - Elapsed Time Should Be Valid ${SUITE3.suites[0].elapsedtime} - Should Be Equal ${SUITE3.suites[0].elapsedtime} ${MILLIS1} - Timestamp Should Be Valid ${SUITE3.suites[1].starttime} - Timestamp Should Be Valid ${SUITE3.suites[1].endtime} - Elapsed Time Should Be Valid ${SUITE3.suites[1].elapsedtime} - Should Be Equal ${SUITE3.suites[1].elapsedtime} ${MILLIS2} - Should Be Equal ${SUITE3.suites[2].starttime} 20061227 11:59:59.000 - Should Be Equal ${SUITE3.suites[2].endtime} 20061227 12:00:08.999 - Should Be Equal ${SUITE3.suites[2].elapsedtime} ${9999} + Should Be Equal ${SUITE3.start_time} ${NONE} + Should Be Equal ${SUITE3.end_time} ${NONE} + Elapsed Time Should Be ${SUITE3.elapsed_time} ${ELAPSED1} + ${ELAPSED2} + 9.999 + Timestamp Should Be Valid ${SUITE3.suites[0].start_time} + Timestamp Should Be Valid ${SUITE3.suites[0].end_time} + Elapsed Time Should Be ${SUITE3.suites[0].elapsed_time} ${ELAPSED1} + Timestamp Should Be Valid ${SUITE3.suites[1].start_time} + Timestamp Should Be Valid ${SUITE3.suites[1].end_time} + Elapsed Time Should Be ${SUITE3.suites[1].elapsed_time} ${ELAPSED2} + Timestamp Should Be ${SUITE3.suites[2].start_time} 2006-12-27 11:59:59 + Timestamp Should Be ${SUITE3.suites[2].end_time} 2006-12-27 12:00:08.999 + Elapsed Time Should Be ${SUITE3.suites[2].elapsed_time} 9.999 Suite Times In Recombine - Should Be Equal ${SUITE4.starttime} ${NONE} - Should Be Equal ${SUITE4.endtime} ${NONE} - Should Be True ${SUITE4.elapsedtime} == 9999 + ${MILLIS1} + ${MILLIS2} - Should Be Equal ${SUITE4.suites[0].starttime} 20061227 11:59:59.000 - Should Be Equal ${SUITE4.suites[0].endtime} 20061227 12:00:08.999 - Should Be Equal ${SUITE4.suites[0].elapsedtime} ${9999} - Should Be Equal ${SUITE4.suites[1].starttime} ${NONE} - Should Be Equal ${SUITE4.suites[1].endtime} ${NONE} - Timestamp Should Be Valid ${SUITE4.suites[1].suites[0].starttime} - Timestamp Should Be Valid ${SUITE4.suites[1].suites[0].endtime} - Elapsed Time Should Be Valid ${SUITE4.suites[1].suites[0].elapsedtime} - Should Be Equal ${SUITE4.suites[1].suites[0].elapsedtime} ${MILLIS1} - Timestamp Should Be Valid ${SUITE4.suites[1].suites[1].starttime} - Timestamp Should Be Valid ${SUITE4.suites[1].suites[1].endtime} - Elapsed Time Should Be Valid ${SUITE4.suites[1].suites[1].elapsedtime} - Should Be Equal ${SUITE4.suites[1].suites[1].elapsedtime} ${MILLIS2} - -Elapsed Time Should Be Written To Output When Start And End Time Are Not Known - ${combined} = Get Element ${COMB OUT 1} suite/status - Element Attribute Should Be ${combined} starttime N/A - Element Attribute Should Be ${combined} endtime N/A - Should Be True int($combined.get('elapsedtime')) >= 0 - ${originals} = Get Elements ${COMB OUT 1} suite/suite/status - Element Attribute Should Match ${originals[0]} starttime 20?????? ??:??:??.??? - Element Attribute Should Match ${originals[0]} endtime 20?????? ??:??:??.??? - Element Should Not Have Attribute ${originals[0]} elapsedtime + Should Be Equal ${SUITE4.start_time} ${NONE} + Should Be Equal ${SUITE4.end_time} ${NONE} + Elapsed Time Should Be ${SUITE4.elapsed_time} ${ELAPSED1} + ${ELAPSED2} + 9.999 + Timestamp Should Be ${SUITE4.suites[0].start_time} 2006-12-27 11:59:59 + Timestamp Should Be ${SUITE4.suites[0].end_time} 2006-12-27 12:00:08.999 + Elapsed Time Should Be ${SUITE4.suites[0].elapsed_time} 9.999 + Should Be Equal ${SUITE4.suites[1].start_time} ${NONE} + Should Be Equal ${SUITE4.suites[1].end_time} ${NONE} + Timestamp Should Be Valid ${SUITE4.suites[1].suites[0].start_time} + Timestamp Should Be Valid ${SUITE4.suites[1].suites[0].end_time} + Elapsed Time Should Be ${SUITE4.suites[1].suites[0].elapsed_time} ${ELAPSED1} + Timestamp Should Be Valid ${SUITE4.suites[1].suites[1].start_time} + Timestamp Should Be Valid ${SUITE4.suites[1].suites[1].end_time} + Elapsed Time Should Be ${SUITE4.suites[1].suites[1].elapsed_time} ${ELAPSED2} Combined Suite Names Are Correct In Statistics ${suites} = Get Suite Stat Nodes ${COMB OUT 1} @@ -152,11 +137,11 @@ Create inputs for Rebot Create first input for Rebot Create Output With Robot ${TEMP OUT 1} ${EMPTY} misc/pass_and_fail.robot - Set Suite Variable $MILLIS1 ${ORIG ELAPSED} + Set Suite Variable $ELAPSED1 ${ORIG ELAPSED.total_seconds()} Create second input for Rebot Create Output With Robot ${TEMP OUT 2} ${EMPTY} misc/normal.robot - Set Suite Variable $MILLIS2 ${ORIG ELAPSED} + Set Suite Variable $ELAPSED2 ${ORIG ELAPSED.total_seconds()} Combine without options Run Rebot ${EMPTY} ${TEMP OUT 1} ${TEMP OUT 2} diff --git a/atest/robot/rebot/compatibility.robot b/atest/robot/rebot/compatibility.robot index 1c5ed3bc3d8..4df330d0753 100644 --- a/atest/robot/rebot/compatibility.robot +++ b/atest/robot/rebot/compatibility.robot @@ -15,18 +15,23 @@ RF 4.0 compatibility RF 5.0 compatibility Run Rebot And Validate Statistics rebot/output-5.0.xml 175 10 +Suite only + Run Rebot And Validate Statistics rebot/suite_only.xml 179 10 3 + Message directly under test Run Rebot And Validate Statistics rebot/issue-3762.xml 1 0 ${tc} = Check Test Case test A - Check Log Message ${tc.body[0]} Hi from test WARN - Check Log Message ${tc.body[1].body[0]} Hi from keyword WARN - Check Log Message ${tc.body[2]} Hi from test again INFO + Check Log Message ${tc[0]} Hi from test WARN + Check Log Message ${tc[1, 0]} Hi from keyword WARN + Check Log Message ${tc[2]} Hi from test again INFO *** Keywords *** Run Rebot And Validate Statistics - [Arguments] ${path} ${passed} ${failed} ${validate}=True + [Arguments] ${path} ${passed} ${failed} ${skipped}=0 ${validate}=True Run Rebot ${EMPTY} ${path} validate output=${validate} - ${total} ${passed} ${failed} = Evaluate ${passed} + ${failed}, ${passed}, ${failed} - Should Be Equal ${SUITE.statistics.total} ${total} - Should Be Equal ${SUITE.statistics.passed} ${passed} - Should Be Equal ${SUITE.statistics.failed} ${failed} + ${total} ${passed} ${failed} ${skipped} = + ... Evaluate ${passed} + ${failed} + ${skipped}, ${passed}, ${failed}, ${skipped} + Should Be Equal ${SUITE.statistics.total} ${total} + Should Be Equal ${SUITE.statistics.passed} ${passed} + Should Be Equal ${SUITE.statistics.failed} ${failed} + Should Be Equal ${SUITE.statistics.skipped} ${skipped} diff --git a/atest/robot/rebot/filter_by_names.robot b/atest/robot/rebot/filter_by_names.robot index 66d9275c572..971b8a36e7a 100644 --- a/atest/robot/rebot/filter_by_names.robot +++ b/atest/robot/rebot/filter_by_names.robot @@ -25,7 +25,7 @@ ${INPUT FILE} %{TEMPDIR}${/}robot-test-file.xml --test not matching Failing Rebot ... Suite 'Root' contains no tests matching name 'nonex'. - ... --test nonex ${INPUT FILE} + ... --test nonex --test not matching with multiple inputs Failing Rebot @@ -35,6 +35,18 @@ ${INPUT FILE} %{TEMPDIR}${/}robot-test-file.xml ... Suite 'My Name' contains no tests matching name 'nonex'. ... --test nonex -N "My Name" ${INPUT FILE} ${INPUT FILE} +--test and --include must both match + Run And Check Tests --test first --include t1 -i f1 First + Failing Rebot + ... Suite 'Root' contains no tests matching name 'fifth' and matching tag 't1'. + ... --test fifth --include t1 + +--exclude wins over --test + Run And Check Tests --test fi* --exclude t1 Fifth + Failing Rebot + ... Suite 'Root' contains no tests matching name 'first' and not matching tag 'f1'. + ... --test first --exclude f1 + --suite once Run And Check Suites --suite tsuite1 Tsuite1 @@ -51,10 +63,11 @@ ${INPUT FILE} %{TEMPDIR}${/}robot-test-file.xml Should Contain Suites ${SUITE} Suites Should Contain Suites ${SUITE.suites[0].suites[0]} Sub1 Sub2 ---suite with end of long name - Run And Check Suites --suite suites.subsuites Subsuites - Should Contain Suites ${SUITE} Suites - Should Contain Suites ${SUITE.suites[0].suites[0]} Sub1 Sub2 +--suite matching end of long name is not enough anymore + [Documentation] This was supported until RF 7.0. + Failing Rebot + ... Suite 'Root' contains no tests in suite 'suites.subsuites'. + ... --suite suites.subsuites ${INPUT FILE} --suite not matching Failing Rebot @@ -70,33 +83,50 @@ ${INPUT FILE} %{TEMPDIR}${/}robot-test-file.xml ... --name CustomName --suite nonex ${INPUT FILE} ${INPUT FILE} --suite and --test together - Run And Check Suites and Tests --suite tsuite1 --suite tsuite3 --test *1first --test nomatch Tsuite1 Suite1 First + [Documentation] Validate that only tests matching --test under suites matching --suite are selected. + Run Suites --suite root.*.tsuite2 --suite manytests --test *first* --test nomatch --log log + Should Contain Suites ${SUITE} Many Tests Suites + Should Contain Tests ${SUITE.suites[0]} First + Should Contain Tests ${SUITE.suites[1]} Suite2 First + Check Stats --suite and --test together not matching Failing Rebot ... Suite 'Root' contains no tests matching name 'first', 'nonex' or '*one' in suites 'nonex' or 'suites'. ... --suite nonex --suite suites --test first --test nonex --test *one ${INPUT FILE} +--suite with --include/--exclude + Run Suites --suite tsuite[13] --include t? --exclude t2 + Should Contain Suites ${SUITE} Suites + Should Contain Suites ${SUITE.suites[0]} Tsuite1 Tsuite3 + Should Contain Tests ${SUITE} Suite1 First Suite3 First + +--suite, --test, --include and --exclude + Run Suites --suite sub* --suite "custom name *" --test "subsuite3 second" -t *first -s nomatch -t nomatch --include f1 --exclude t1 + Should Contain Suites ${SUITE} Suites + Should Contain Suites ${SUITE.suites[0]} Custom name for 📂 'subsuites2' Subsuites + Should Contain Tests ${SUITE} SubSuite2 First SubSuite3 Second + Elapsed Time [Documentation] Test setting start, end and elapsed times correctly when filtering by tags - Comment 1) Rebot hand-edited output with predefined times and check that times are read correctly. (A sanity check) + # 1) Rebot hand-edited output with predefined times and check that times are read correctly. (A sanity check) Run Rebot ${EMPTY} rebot${/}times.xml - Check Times ${SUITE.tests[0]} 20061227 12:00:00.000 20061227 12:00:01.000 1000 # Incl-1 - Check Times ${SUITE.tests[1]} 20061227 12:00:01.000 20061227 12:00:03.000 2000 # Incl-12 - Check Times ${SUITE.tests[2]} 20061227 12:00:03.000 20061227 12:00:07.000 4000 # Incl-123 - Check Times ${SUITE.tests[3]} 20061227 12:00:07.000 20061227 12:00:07.001 0001 # Excl-1 - Check Times ${SUITE.tests[4]} 20061227 12:00:07.001 20061227 12:00:07.003 0002 # Excl-12 - Check Times ${SUITE.tests[5]} 20061227 12:00:07.003 20061227 12:00:07.007 0004 # Excl-123 - Check Times ${SUITE} 20061227 11:59:59.000 20061227 12:00:08.999 9999 # Suite + Times Should Be ${SUITE.tests[0]} 2006-12-27 12:00:00.000 2006-12-27 12:00:01.000 1.000 # Incl-1 + Times Should Be ${SUITE.tests[1]} 2006-12-27 12:00:01.000 2006-12-27 12:00:03.000 2.000 # Incl-12 + Times Should Be ${SUITE.tests[2]} 2006-12-27 12:00:03.000 2006-12-27 12:00:07.000 4.000 # Incl-123 + Times Should Be ${SUITE.tests[3]} 2006-12-27 12:00:07.000 2006-12-27 12:00:07.001 0.001 # Excl-1 + Times Should Be ${SUITE.tests[4]} 2006-12-27 12:00:07.001 2006-12-27 12:00:07.003 0.002 # Excl-12 + Times Should Be ${SUITE.tests[5]} 2006-12-27 12:00:07.003 2006-12-27 12:00:07.007 0.004 # Excl-123 + Times Should Be ${SUITE} 2006-12-27 11:59:59.000 2006-12-27 12:00:08.999 9.999 # Suite Should Be Equal As Integers ${SUITE.test_count} 6 - Comment 2) Filter output created in earlier step and check that times are set accordingly. + # 2) Filter output created in earlier step and check that times are set accordingly. Copy Previous Outfile Run Rebot --test Exc* --test Incl-1 ${OUTFILE COPY} - Check Times ${SUITE.tests[0]} 20061227 12:00:00.000 20061227 12:00:01.000 1000 # Incl-1 - Check Times ${SUITE.tests[1]} 20061227 12:00:07.000 20061227 12:00:07.001 0001 # Excl-1 - Check Times ${SUITE.tests[2]} 20061227 12:00:07.001 20061227 12:00:07.003 0002 # Excl-12 - Check Times ${SUITE.tests[3]} 20061227 12:00:07.003 20061227 12:00:07.007 0004 # Excl-123 - Check Times ${SUITE} ${NONE} ${NONE} 1007 # Suite + Times Should Be ${SUITE.tests[0]} 2006-12-27 12:00:00.000 2006-12-27 12:00:01.000 1.000 # Incl-1 + Times Should Be ${SUITE.tests[1]} 2006-12-27 12:00:07.000 2006-12-27 12:00:07.001 0.001 # Excl-1 + Times Should Be ${SUITE.tests[2]} 2006-12-27 12:00:07.001 2006-12-27 12:00:07.003 0.002 # Excl-12 + Times Should Be ${SUITE.tests[3]} 2006-12-27 12:00:07.003 2006-12-27 12:00:07.007 0.004 # Excl-123 + Times Should Be ${SUITE} ${NONE} ${NONE} 1.007 # Suite Should Be Equal As Integers ${SUITE.test_count} 4 *** Keywords *** @@ -106,9 +136,9 @@ Create Input File Remove Temps Remove Directory ${MYOUTDIR} recursive - Remove FIle ${INPUT FILE} + Remove File ${INPUT FILE} -Run and check Tests +Run and Check Tests [Arguments] ${params} @{tests} Run Rebot ${params} ${INPUT FILE} Stderr Should Be Empty @@ -118,10 +148,9 @@ Run and check Tests Check Stats Should Be True ${SUITE.statistics.failed} == 0 - Should Be Equal ${SUITE.starttime} ${NONE} - Should Be Equal ${SUITE.endtime} ${NONE} - Elapsed Time Should Be Valid ${SUITE.elapsedtime} - Should Be True ${SUITE.elapsedtime} <= ${ORIGELAPSED} + Should Be Equal ${SUITE.start_time} ${NONE} + Should Be Equal ${SUITE.end_time} ${NONE} + Elapsed Time Should Be Valid ${SUITE.elapsed_time} maximum=${ORIG_ELAPSED.total_seconds()} Run and Check Suites [Arguments] ${params} @{suites} @@ -129,20 +158,12 @@ Run and Check Suites Should Contain Suites ${SUITE.suites[0]} @{suites} Check Stats -Run And Check Suites and Tests - [Arguments] ${params} ${subsuite} @{tests} - Run Suites ${params} - Should Contain Suites ${SUITE.suites[0]} ${subsuite} - Should Contain Tests ${SUITE} @{tests} - Should Be True ${SUITE.statistics.passed} == len(@{tests}) - Check Stats - Run Suites [Arguments] ${options} Run Rebot ${options} ${INPUT FILE} Stderr Should Be Empty Failing Rebot - [Arguments] ${error} ${options} ${sources} + [Arguments] ${error} ${options} ${sources}=${INPUT FILE} Run Rebot Without Processing Output ${options} ${sources} Stderr Should Be Equal To [ ERROR ] ${error}${USAGE TIP}\n diff --git a/atest/robot/rebot/json_output_and_input.robot b/atest/robot/rebot/json_output_and_input.robot new file mode 100644 index 00000000000..8fc26e2124f --- /dev/null +++ b/atest/robot/rebot/json_output_and_input.robot @@ -0,0 +1,66 @@ +*** Settings *** +Suite Setup Create XML and JSON outputs +Resource rebot_resource.robot + +*** Variables *** +${XML} %{TEMPDIR}/rebot.xml +${JSON} %{TEMPDIR}/rebot.json + +*** Test Cases *** +JSON output contains same suite information as XML output + Outputs Should Contain Same Data ${JSON} ${XML} + +JSON output structure + [Documentation] JSON schema validation would be good, but it's too slow with big output files. + ... The test after this one validates a smaller suite against a schema. + ${data} = Evaluate json.load(open($JSON, encoding='UTF-8')) + Lists Should Be Equal ${data} ${{['generator', 'generated', 'rpa', 'suite', 'statistics', 'errors']}} + Should Match ${data}[generator] Rebot ?.* (* on *) + Should Match ${data}[generated] 20??-??-??T??:??:??.?????? + Should Be Equal ${data}[rpa] ${False} + Should Be Equal ${data}[suite][name] Misc + Should Be Equal ${data}[suite][suites][1][name] Everything + Should Be Equal ${data}[statistics][total][skip] ${3} + Should Be Equal ${data}[statistics][tags][4][label] f1 + Should Be Equal ${data}[statistics][suites][-1][id] s1-s17 + Should Be Equal ${data}[errors][0][level] ERROR + +JSON output schema validation + [Tags] require-jsonschema + Run Rebot Without Processing Output --suite Everything --output %{TEMPDIR}/everything.json ${JSON} + Validate JSON Output %{TEMPDIR}/everything.json + +JSON input + Run Rebot ${EMPTY} ${JSON} + Outputs Should Contain Same Data ${JSON} ${OUTFILE} + +JSON input combined + Run Rebot ${EMPTY} ${XML} ${XML} + Copy Previous Outfile # Expected result + Run Rebot ${EMPTY} ${JSON} ${XML} + Outputs Should Contain Same Data ${OUTFILE} ${OUTFILE COPY} + Run Rebot ${EMPTY} ${JSON} ${JSON} + Outputs Should Contain Same Data ${OUTFILE} ${OUTFILE COPY} + +Invalid JSON input + Create File ${JSON} bad + Run Rebot Without Processing Output ${EMPTY} ${JSON} + ${json} = Normalize Path ${JSON} + VAR ${error} + ... Reading JSON source '${json}' failed: + ... Loading JSON data failed: + ... Invalid JSON data: * + Stderr Should Match [[] ERROR ] ${error}${USAGE TIP}\n + +Non-existing JSON input + Run Rebot Without Processing Output ${EMPTY} non_existing.json + ${json} = Normalize Path ${DATADIR}/non_existing.json + VAR ${error} + ... Reading JSON source '${json}' failed: + ... No such file or directory + Stderr Should Match [[] ERROR ] ${error}${USAGE TIP}\n + +*** Keywords *** +Create XML and JSON outputs + Create Output With Robot ${XML} ${EMPTY} misc + Run Rebot Without Processing Output --output ${JSON} ${XML} diff --git a/atest/robot/rebot/merge.robot b/atest/robot/rebot/merge.robot index 90b0a2acb1b..b2539d6214a 100644 --- a/atest/robot/rebot/merge.robot +++ b/atest/robot/rebot/merge.robot @@ -15,11 +15,11 @@ ${MERGE 2} %{TEMPDIR}/merge-2.xml ... Suite1 First Suite1 Second ... Test With Double Underscore Test With Prefix Third In Suite1 ... Suite2 First Suite3 First -@{ALL SUITES} Fourth Subsuites Subsuites2 +@{ALL SUITES} Fourth Subsuites Custom name for 📂 'subsuites2' ... Suite With Double Underscore Suite With Prefix ... Tsuite1 Tsuite2 Tsuite3 @{SUB SUITES 1} Sub1 Sub2 -@{SUB SUITES 2} Sub.suite.4 Subsuite3 +@{SUB SUITES 2} Sub.suite.4 Custom name for 📜 'subsuite3.robot' @{RERUN TESTS} Suite4 First SubSuite1 First @{RERUN SUITES} Fourth Subsuites @@ -33,6 +33,14 @@ Merge suite setup and teardown [Setup] Should Be Equal ${PREV_TEST_STATUS} PASS Suite setup and teardown should have been merged +Merge suite documentation and metadata + [Setup] Should Be Equal ${PREV_TEST_STATUS} PASS + Suite documentation and metadata should have been merged + +Suite elapsed time should be updated + [Setup] Should Be Equal ${PREV_TEST_STATUS} PASS + Should Be True $SUITE.elapsed_time > $ORIGINAL_ELAPSED + Merge re-executed and re-re-executed tests Re-run tests Re-re-run tests @@ -66,9 +74,9 @@ Using other options ... --merge. Most importantly verify that options handled ... by ExecutionResult (--flattenkeyword) work correctly. Re-run tests - Run merge --nomerge --log log.html --merge --flattenkeyword name:BuiltIn.Log --name Custom + Run merge --nomerge --log log.html --merge --flattenkeyword name:BuiltIn.Fail --name Custom Test merge should have been successful suite name=Custom - Log should have been created with all Log keywords flattened + Log should have been created with Fail keywords flattened Merge ignores skip Create Output With Robot ${ORIGINAL} ${EMPTY} rebot/merge_statuses.robot @@ -78,14 +86,20 @@ Merge ignores skip ... *HTML* Test has been re-executed and results merged. ... Latter result had SKIP status and was ignored. Message: Should Contain Tests ${SUITE} - ... Pass=PASS:${prefix}\nTest skipped using '--skip' command line option. - ... Fail=FAIL:${prefix}\nTest skipped using '--skip' command line option.


      Original message:\nNot <b>HTML</b> fail + ... Pass=PASS:${prefix}\nTest skipped using 'NOT skip' tag pattern. + ... Fail=FAIL:${prefix}\nTest skipped using 'NOT skip' tag pattern.
      Original message:\nNot <b>HTML</b> fail ... Skip=SKIP:${prefix}\nHTML skip
      Original message:\nHTML skip *** Keywords *** Run original tests - Create Output With Robot ${ORIGINAL} --variable FAIL:YES --variable LEVEL:WARN ${SUITES} + ${options} = Catenate + ... --variable FAIL:YES + ... --variable LEVEL:WARN + ... --doc "Doc for original run" + ... --metadata Original:True + Create Output With Robot ${ORIGINAL} ${options} ${SUITES} Verify original tests + VAR ${ORIGINAL ELAPSED} ${SUITE.elapsed_time} scope=SUITE Verify original tests Should Be Equal ${SUITE.name} Suites @@ -98,12 +112,15 @@ Verify original tests Re-run tests [Arguments] ${options}= ${options} = Catenate + ... --doc "Doc for re-run" + ... --metadata ReRun:True ... --variable SUITE_SETUP:NoOperation # Affects misc/suites/__init__.robot ... --variable SUITE_TEARDOWN:NONE # -- ;; -- ... --variable SETUP_MSG:Rerun! # Affects misc/suites/fourth.robot ... --variable TEARDOWN_MSG:New! # -- ;; -- ... --variable SETUP:NONE # Affects misc/suites/subsuites/sub1.robot ... --variable TEARDOWN:NONE # -- ;; -- + ... --variable SLEEP:0.5 # -- ;; -- ... --rerunfailed ${ORIGINAL} ${options} Create Output With Robot ${MERGE 1} ${options} ${SUITES} Should Be Equal ${SUITE.name} Suites @@ -164,15 +181,20 @@ Test merge should have been successful ... ${SUITE.suites[7]} Suite setup and teardown should have been merged - Should Be Equal ${SUITE.setup.name} BuiltIn.No Operation + Should Be Equal ${SUITE.setup.full_name} BuiltIn.No Operation Should Be Equal ${SUITE.teardown.name} ${NONE} Should Be Equal ${SUITE.suites[1].name} Fourth - Check Log Message ${SUITE.suites[1].setup.msgs[0]} Rerun! - Check Log Message ${SUITE.suites[1].teardown.msgs[0]} New! + Check Log Message ${SUITE.suites[1].setup[0]} Rerun! + Check Log Message ${SUITE.suites[1].teardown[0]} New! Should Be Equal ${SUITE.suites[2].suites[0].name} Sub1 Should Be Equal ${SUITE.suites[2].suites[0].setup.name} ${NONE} Should Be Equal ${SUITE.suites[2].suites[0].teardown.name} ${NONE} +Suite documentation and metadata should have been merged + Should Be Equal ${SUITE.doc} Doc for re-run + Should Be Equal ${SUITE.metadata}[ReRun] True + Should Be Equal ${SUITE.metadata}[Original] True + Test add should have been successful Should Be Equal ${SUITE.name} Suites Should Contain Suites ${SUITE} @{ALL SUITES} @@ -227,7 +249,7 @@ Warnings should have been merged Check Log Message ${ERRORS[0]} Original message WARN Check Log Message ${ERRORS[1]} Override WARN ${tc} = Check Test Case SubSuite1 First - Check Log Message ${tc.kws[0].msgs[0]} Override WARN + Check Log Message ${tc[0, 0]} Override WARN Merge should have failed Stderr Should Be Equal To @@ -237,15 +259,15 @@ Merge should have failed Timestamps should be cleared [Arguments] @{suites} FOR ${suite} IN @{suites} - Should Be Equal ${suite.starttime} ${None} - Should Be Equal ${suite.endtime} ${None} + Should Be Equal ${suite.start_time} ${None} + Should Be Equal ${suite.end_time} ${None} END Timestamps should be set [Arguments] @{suites} FOR ${suite} IN @{suites} - Timestamp Should Be Valid ${suite.starttime} - Timestamp Should Be Valid ${suite.endtime} + Timestamp Should Be Valid ${suite.start_time} + Timestamp Should Be Valid ${suite.end_time} END Create expected merge message header @@ -300,7 +322,6 @@ Create expected multi-merge message ... ${message 1} ...
      ${message 2} -Log should have been created with all Log keywords flattened +Log should have been created with Fail keywords flattened ${log} = Get File ${OUTDIR}/log.html - Should Not Contain ${log} "*

      Logs the given message with the given level.\\x3c/p>" - Should Contain ${log} "*

      Logs the given message with the given level.\\x3c/p>\\n

      Content flattened.\\x3c/b>\\x3c/i>\\x3c/p>" + Should Contain ${log} "*Content flattened." diff --git a/atest/robot/rebot/start_and_endtime_from_cli.robot b/atest/robot/rebot/start_and_endtime_from_cli.robot index 6f2f424f7a3..b22cdc84d2b 100644 --- a/atest/robot/rebot/start_and_endtime_from_cli.robot +++ b/atest/robot/rebot/start_and_endtime_from_cli.robot @@ -9,67 +9,67 @@ ${INPUT2} %{TEMPDIR}${/}rebot-test-b.xml ${COMBINED} %{TEMPDIR}${/}combined.xml *** Test Cases *** -Combine With Both Starttime and endtime should Set Correct Elapsed Time +Combine with both start time and end time Log Many ${INPUT1} ${INPUT2} - Run Rebot --starttime 2007:09:25:21:51 --endtime 2007:09:26:01:12:30.200 ${INPUT1} ${INPUT2} - Should Be Equal ${SUITE.starttime} 20070925 21:51:00.000 - Should Be Equal ${SUITE.endtime} 20070926 01:12:30.200 - Should Be True ${SUITE.elapsedtime} == (3*60*60 + 21*60 + 30) * 1000 + 200 + Run Rebot --starttime 2007:09:25:21:51 --endtime 2007-09-26T01:12:30.200 ${INPUT1} ${INPUT2} + Should Be Equal ${SUITE.start_time} ${datetime(2007, 9, 25, 21, 51)} + Should Be Equal ${SUITE.end_time} ${datetime(2007, 9, 26, 1, 12, 30, 200000)} + Should Be Equal ${SUITE.elapsed_time} ${timedelta(seconds=3*60*60 + 21*60 + 30.2)} -Combine With Only Starttime Should Only Affect Starttime +Combine with only start time Run Rebot --starttime 20070925-2151 ${INPUT1} ${INPUT2} - Should Be Equal ${SUITE.starttime} 20070925 21:51:00.000 - Should Be Equal ${SUITE.endtime} ${ORIG_END} - Should Be Equal ${SUITE.elapsedtime} ${ORIG_ELAPSED} + Should Be Equal ${SUITE.start_time} ${datetime(2007, 9, 25, 21, 51)} + Should Be Equal ${SUITE.end_time} ${{datetime.datetime(2007, 9, 25, 21, 51) + $ORIG_ELAPSED}} + Should Be Equal ${SUITE.elapsed_time} ${ORIG_ELAPSED} -Combine With Only Endtime Should Only Affect Endtime +Combine with only end time Run Rebot --endtime 2010_01.01:12-33 ${INPUT1} ${INPUT2} - Should Be Equal ${SUITE.starttime} ${ORIG_START} - Should Be Equal ${SUITE.endtime} 20100101 12:33:00.000 - Should Be Equal ${SUITE.elapsedtime} ${ORIG_ELAPSED} + Should Be Equal ${SUITE.start_time} ${{datetime.datetime(2010, 1, 1, 12, 33) - $ORIG_ELAPSED}} + Should Be Equal ${SUITE.end_time} ${datetime(2010, 1, 1, 12, 33)} + Should Be Equal ${SUITE.elapsed_time} ${ORIG_ELAPSED} -Recombining Should Work +Recombining ${options} = Catenate ... --starttime 2007:09:25:21:51 ... --endtime 2007:09:26:01:12:30:200 ... --output ${COMBINED} Run Rebot Without Processing Output ${options} ${INPUT1} ${INPUT2} Run Rebot ${EMPTY} ${INPUT1} ${INPUT2} ${COMBINED} - Should Be True '${SUITE.elapsedtime}' > '03:21:30.200' + Should Be True $SUITE.elapsed_time > datetime.timedelta(hours=3, minutes=21, seconds=30.2) -It should Be possible to Omit Time Altogether +Omit time part altogether Run Rebot --starttime 2007-10-01 --endtime 20071006 ${INPUT1} ${INPUT2} - Should Be Equal ${SUITE.starttime} 20071001 00:00:00.000 - Should Be Equal ${SUITE.endtime} 20071006 00:00:00.000 - Should Be True ${SUITE.elapsedtime} == 120*60*60 * 1000 + Should Be Equal ${SUITE.start_time} ${datetime(2007, 10, 1)} + Should Be Equal ${SUITE.end_time} ${datetime(2007, 10, 6)} + Should Be Equal ${SUITE.elapsed_time} ${timedelta(days=5)} -Use Starttime With Single Output - Run Rebot --starttime 20070925-2151 ${INPUT1} - Should Be Equal ${SUITE.starttime} 20070925 21:51:00.000 - Should Be Equal ${SUITE.endtime} ${SINGLE_SUITE_ORIG_END} - Should Be True ${SUITE.elapsedtime} > ${SINGLE SUITE ORIG ELAPSED} +Start time and end time with single output + Run Rebot --starttime 20070925-2151 --endtime 20070925-2252 ${INPUT1} + Should Be Equal ${SUITE.start_time} ${datetime(2007, 9, 25, 21, 51)} + Should Be Equal ${SUITE.end_time} ${datetime(2007, 9, 25, 22, 52)} + Should Be Equal ${SUITE.elapsed_time} ${timedelta(hours=1, minutes=1)} -Use Endtime With Single Output - Run Rebot --endtime 20070925-2151 ${INPUT1} - Should Be Equal ${SUITE.starttime} ${SINGLE_SUITE_ORIG_START} - Should Be Equal ${SUITE.endtime} 20070925 21:51:00.000 - Should Be True ${SUITE.elapsedtime} < ${SINGLE SUITE ORIG ELAPSED} +Start time with single output + Run Rebot --starttime 20070925-2151 ${INPUT1} + Should Be Equal ${SUITE.start_time} ${datetime(2007, 9, 25, 21, 51)} + Should Be Equal ${SUITE.end_time} ${SINGLE_SUITE_ORIG_END} + Should Be True $SUITE.elapsed_time > $SINGLE_SUITE_ORIG_ELAPSED -Use Starttime And Endtime With Single Output - Run Rebot --starttime 20070925-2151 --endtime 20070925-2252 ${INPUT1} - Should Be Equal ${SUITE.starttime} 20070925 21:51:00.000 - Should Be Equal ${SUITE.endtime} 20070925 22:52:00.000 - Should Be Equal ${SUITE.elapsedtime} ${3660000} +End time with single output + Run Rebot --endtime '2023-09-07 19:31:01.234' ${INPUT1} + Should Be Equal ${SUITE.start_time} ${SINGLE_SUITE_ORIG_START} + Should Be Equal ${SUITE.end_time} ${datetime(2023, 9, 7, 19, 31, 1, 234000)} + Should Be True $SUITE.elapsed_time < $SINGLE_SUITE_ORIG_ELAPSED *** Keywords *** Create Input Files Create Output With Robot ${INPUT1} ${EMPTY} misc/normal.robot Create Output With Robot ${INPUT2} ${EMPTY} misc/suites/tsuite1.robot Run Rebot ${EMPTY} ${INPUT1} ${INPUT2} - Set Suite Variable $ORIG_START ${SUITE.starttime} - Set Suite Variable $ORIG_END ${SUITE.endtime} - Set Suite Variable $ORIG_ELAPSED ${SUITE.elapsedtime} + Set Suite Variable $ORIG_START ${SUITE.start_time} + Set Suite Variable $ORIG_END ${SUITE.end_time} + Set Suite Variable $ORIG_ELAPSED ${SUITE.elapsed_time} Run Rebot ${EMPTY} ${INPUT1} - Set Suite Variable $SINGLE_SUITE_ORIG_START ${SUITE.starttime} - Set Suite Variable $SINGLE_SUITE_ORIG_END ${SUITE.endtime} - Set Suite Variable $SINGLE_SUITE_ORIG_ELAPSED ${SUITE.elapsedtime} + Set Suite Variable $SINGLE_SUITE_ORIG_START ${SUITE.start_time} + Set Suite Variable $SINGLE_SUITE_ORIG_END ${SUITE.end_time} + Set Suite Variable $SINGLE_SUITE_ORIG_ELAPSED ${SUITE.elapsed_time} diff --git a/atest/robot/rebot/xunit.robot b/atest/robot/rebot/xunit.robot index c3b2293a391..81567c6960e 100644 --- a/atest/robot/rebot/xunit.robot +++ b/atest/robot/rebot/xunit.robot @@ -135,7 +135,7 @@ Remove Temps Suite Stats Should Be [Arguments] ${tests} ${failures} ${skipped}=0 - ... ${time}=?.??? ${timestamp}=20??-??-??T??:??:??.???000 + ... ${time}=?.??? ${timestamp}=20??-??-??T??:??:??.?????? ... ${xpath}=. ${suite} = Get Element ${OUTDIR}/xunit.xml xpath=${xpath} Element Attribute Should Be ${suite} tests ${tests} diff --git a/atest/robot/rpa/run_rpa_tasks.robot b/atest/robot/rpa/run_rpa_tasks.robot index cd64a3a7221..b2d9b8a762e 100644 --- a/atest/robot/rpa/run_rpa_tasks.robot +++ b/atest/robot/rpa/run_rpa_tasks.robot @@ -5,7 +5,7 @@ Test Template Run and validate RPA tasks Resource atest_resource.robot *** Variables *** -@{ALL TASKS} Task Another task Task Failing Passing Test +@{ALL TASKS} Defaults Override Task Another task Task Failing Passing Test ... Defaults Override Task timeout exceeded Invalid task timeout *** Test Cases *** @@ -16,30 +16,30 @@ Task header in multiple files ${EMPTY} rpa/tasks1.robot rpa/tasks2.robot Task Failing Passing Task header in directory - ${EMPTY} rpa/tasks Task Another task + ${EMPTY} rpa/tasks Task Another task Defaults Override Test header with --rpa --rpa rpa/tests.robot Test Task header with --norpa [Template] Run and validate test cases - --norpa rpa/tasks Task Another task + --norpa rpa/tasks Task Another task Defaults Override Conflicting headers cause error [Template] Run and validate conflict - rpa/tests.robot rpa/tasks rpa/tasks/stuff.robot tasks tests - rpa/ rpa/tests.robot tests tasks - ... [[] ERROR ] Error in file '*[/\\]task_setup_teardown_template_timeout.robot' on line 6: + rpa/tests.robot rpa/tasks Rpa.Tests Rpa.Tasks tests tasks + rpa/ Rpa.Task Aliases Rpa.Tests tasks tests + ... [[] ERROR ] Error in file '*[/\\]task_aliases.robot' on line 7: ... Non-existing setting 'Tesk Setup'. Did you mean:\n ... ${SPACE*3}Test Setup\n ... ${SPACE*3}Task Setup\n Conflicting headers with --rpa are fine - --RPA rpa/tasks rpa/tests.robot Task Another task Test + --RPA rpa/tasks rpa/tests.robot Task Another task Defaults Override Test Conflicting headers with --norpa are fine [Template] Run and validate test cases - --NorPA -v TIMEOUT:Test rpa/ @{ALL TASKS} + --NorPA -v TIMEOUT:Test -v RPA:False rpa/ @{ALL TASKS} Conflicting headers in same file cause error [Documentation] Using --rpa or --norpa doesn't affect the behavior. @@ -66,11 +66,15 @@ Conflicting headers in same file cause error when executing directory --task task rpa/tasks Task --rpa --task Test --test "An* T???" rpa/ Another task Test +Suite containing tests is ok if only tasks are selected + --task task rpa/tasks rpa/tests.robot Task + --suite stuff rpa/tasks rpa/tests.robot Task Another task + Error message is correct if no task match --task or other options [Template] Run and validate no task found - --task nonex matching name 'nonex' - --include xxx --exclude yyy matching tag 'xxx' and not matching tag 'yyy' - --suite nonex --task task matching name 'task' in suite 'nonex' + --rpa --task nonex no tasks matching name 'nonex' + --norpa --include xxx --exclude yyy no tests matching tag 'xxx' and not matching tag 'yyy' + --suite nonex --task task no tests or tasks matching name 'task' in suite 'nonex' Error message is correct if task name is empty or task contains no keywords [Template] NONE @@ -92,20 +96,19 @@ Run and validate test cases Should contain tests ${SUITE} @{tasks} Run and validate conflict - [Arguments] ${paths} ${conflicting} ${this} ${that} @{extra errors} - Run tests without processing output ${EMPTY} ${paths} - ${conflicting} = Normalize path ${DATADIR}/${conflicting} + [Arguments] ${paths} ${suite1} ${suite2} ${mode1} ${mode2} @{extra errors} + Run tests without processing output --name Rpa ${paths} ${extra} = Catenate @{extra errors} ${error} = Catenate - ... [[] ERROR ] Parsing '${conflicting}' failed: Conflicting execution modes. - ... File has ${this} but files parsed earlier have ${that}. - ... Fix headers or use '--rpa' or '--norpa' options to set the execution mode explicitly. + ... [[] ERROR ] Conflicting execution modes: + ... Suite '${suite1}' has ${mode1} but suite '${suite2}' has ${mode2}. + ... Resolve the conflict or use '--rpa' or '--norpa' options to set the execution mode explicitly. Stderr Should Match ${extra}${error}${USAGE TIP}\n Run and validate no task found [Arguments] ${options} ${message} - Run tests without processing output --rpa ${options} rpa/tasks - Stderr Should Be Equal To [ ERROR ] Suite 'Tasks' contains no tasks ${message}.${USAGE TIP}\n + Run tests without processing output ${options} rpa/tasks rpa/tests.robot + Stderr Should Be Equal To [ ERROR ] Suite 'Tasks & Tests' contains ${message}.${USAGE TIP}\n Outputs should contain correct mode information [Arguments] ${rpa} diff --git a/atest/robot/rpa/task_aliases.robot b/atest/robot/rpa/task_aliases.robot new file mode 100644 index 00000000000..533eab1baa1 --- /dev/null +++ b/atest/robot/rpa/task_aliases.robot @@ -0,0 +1,68 @@ +*** Settings *** +Suite Setup Run Tests --loglevel DEBUG rpa/task_aliases.robot +Resource atest_resource.robot + +*** Test Cases *** +Defaults + ${tc} = Check Test Tags ${TESTNAME} task tags + Check timeout message ${tc.setup[0]} 1 minute 10 seconds + Check log message ${tc.setup[1]} Setup has an alias! + Check timeout message ${tc[0, 0]} 1 minute 10 seconds + Check log message ${tc[0, 1]} Using default settings + Check log message ${tc.teardown[0]} Also teardown has an alias!! + Should be equal ${tc.timeout} 1 minute 10 seconds + +Override + ${tc} = Check Test Tags ${TESTNAME} task tags own + Check log message ${tc.setup[0]} Overriding setup + Check log message ${tc[0, 0]} Overriding settings + Check log message ${tc.teardown[0]} Overriding teardown as well + Should be equal ${tc.timeout} ${NONE} + +Task timeout exceeded + ${tc} = Check Test Case ${TESTNAME} + Check timeout message ${tc[0, 0]} 99 milliseconds + Check log message ${tc[0, 1]} Task timeout 99 milliseconds exceeded. FAIL + +Invalid task timeout + Check Test Case ${TESTNAME} + +Task aliases are included in setting recommendations + Error In File + ... 0 rpa/task_aliases.robot 7 + ... SEPARATOR=\n + ... Non-existing setting 'Tesk Setup'. Did you mean: + ... ${SPACE*4}Test Setup + ... ${SPACE*4}Task Setup + +Task settings are not allowed in resource file + [Template] Validate invalid setting error + 1 2 Task Setup + 2 3 Task Teardown + 3 4 Task Template + 4 5 Task Timeout + +In init file + Run Tests --loglevel DEBUG rpa/tasks + ${tc} = Check Test Tags Defaults file tag task tags + Check timeout message ${tc.setup[0]} 1 minute 10 seconds + Check log message ${tc.setup[1]} Setup has an alias! + Check timeout message ${tc[0, 0]} 1 minute 10 seconds + Check log message ${tc.teardown[0]} Also teardown has an alias!! + Should be equal ${tc.timeout} 1 minute 10 seconds + ${tc} = Check Test Tags Override file tag task tags own + Check log message ${tc.setup[0]} Overriding setup + Check log message ${tc.teardown[0]} Overriding teardown as well + Should be equal ${tc.timeout} ${NONE} + Should be empty ${ERRORS} + +*** Keywords *** +Check timeout message + [Arguments] ${msg} ${timeout} + Check log message ${msg} Task timeout ${timeout} active. * seconds left. DEBUG pattern=True + +Validate invalid setting error + [Arguments] ${index} ${lineno} ${setting} + Error In File + ... ${index} rpa/resource_with_invalid_task_settings.robot ${lineno} + ... Setting '${setting}' is not allowed in resource file. diff --git a/atest/robot/rpa/task_setup_teardown_template_timeout.robot b/atest/robot/rpa/task_setup_teardown_template_timeout.robot deleted file mode 100644 index 1df6f414510..00000000000 --- a/atest/robot/rpa/task_setup_teardown_template_timeout.robot +++ /dev/null @@ -1,54 +0,0 @@ -*** Settings *** -Suite Setup Run Tests --loglevel DEBUG rpa/task_setup_teardown_template_timeout.robot -Resource atest_resource.robot - -*** Test Cases *** -Defaults - ${tc} = Check Test Case ${TESTNAME} - Check timeout message ${tc.setup.msgs[0]} 1 minute 10 seconds - Check log message ${tc.setup.msgs[1]} Setup has an alias! - Check timeout message ${tc.kws[0].msgs[0]} 1 minute 10 seconds - Check log message ${tc.kws[0].msgs[1]} Using default settings - Check log message ${tc.teardown.msgs[0]} Also teardown has an alias!! - Should be equal ${tc.timeout} 1 minute 10 seconds - -Override - ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.setup.msgs[0]} Overriding setup - Check log message ${tc.kws[0].msgs[0]} Overriding settings - Check log message ${tc.teardown.msgs[0]} Overriding teardown as well - Should be equal ${tc.timeout} ${NONE} - -Task timeout exceeded - ${tc} = Check Test Case ${TESTNAME} - Check timeout message ${tc.kws[0].msgs[0]} 99 milliseconds - Check log message ${tc.kws[0].msgs[1]} Task timeout 99 milliseconds exceeded. FAIL - -Invalid task timeout - Check Test Case ${TESTNAME} - -Task aliases are included in setting recommendations - Error In File - ... 0 rpa/task_setup_teardown_template_timeout.robot 6 - ... SEPARATOR=\n - ... Non-existing setting 'Tesk Setup'. Did you mean: - ... ${SPACE*4}Test Setup - ... ${SPACE*4}Task Setup - -Task settings are not allowed in resource file - [Template] Validate invalid setting error - 1 2 Task Setup - 2 3 Task Teardown - 3 4 Task Template - 4 5 Task Timeout - -*** Keywords *** -Check timeout message - [Arguments] ${msg} ${timeout} - Check log message ${msg} Task timeout ${timeout} active. * seconds left. DEBUG pattern=True - -Validate invalid setting error - [Arguments] ${index} ${lineno} ${setting} - Error In File - ... ${index} rpa/resource_with_invalid_task_settings.robot ${lineno} - ... Non-existing setting '${setting}'. diff --git a/atest/robot/running/GetNestingLevel.py b/atest/robot/running/GetNestingLevel.py new file mode 100644 index 00000000000..1f091c2a720 --- /dev/null +++ b/atest/robot/running/GetNestingLevel.py @@ -0,0 +1,21 @@ +from robot.api import SuiteVisitor + + +class Nesting(SuiteVisitor): + + def __init__(self): + self.level = 0 + self.max = 0 + + def start_keyword(self, kw): + self.level += 1 + self.max = max(self.level, self.max) + + def end_keyword(self, kw): + self.level -= 1 + + +def get_nesting_level(test): + nesting = Nesting() + test.visit(nesting) + return nesting.max diff --git a/atest/robot/running/continue_on_failure.robot b/atest/robot/running/continue_on_failure.robot index bcffd3559c4..784d162727f 100644 --- a/atest/robot/running/continue_on_failure.robot +++ b/atest/robot/running/continue_on_failure.robot @@ -6,93 +6,93 @@ Resource atest_resource.robot Continue in test ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[1].msgs[0]} This should be executed + Check Log Message ${tc[1, 0]} This should be executed Continue in user keyword ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[1].msgs[0]} This should be executed in Test Case + Check Log Message ${tc[0, 1, 0]} This should be executed in Test Case Continue in test with several continuable failures ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[1].msgs[0]} This should be executed - Check Log Message ${tc.kws[3].msgs[0]} This should also be executed - Check Log Message ${tc.kws[5].msgs[0]} This too should also be executed + Check Log Message ${tc[1, 0]} This should be executed + Check Log Message ${tc[3, 0]} This should also be executed + Check Log Message ${tc[5, 0]} This too should also be executed Continue in user keyword with several continuable failures ${tc}= Check Test Case ${TESTNAME} - Verify all failures in user keyword ${tc.kws[0]} Test Case - Verify all failures in user keyword ${tc.kws[1]} Test Case, Again + Verify all failures in user keyword ${tc[0]} Test Case + Verify all failures in user keyword ${tc[1]} Test Case, Again Continuable and regular failure ${tc}= Check Test Case ${TESTNAME} - Length Should Be ${tc.kws} 4 - Should Be Equal ${tc.kws[-1].status} NOT RUN + Length Should Be ${tc.body} 4 + Should Be Equal ${tc[-1].status} NOT RUN Continue in nested user keyword ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[1].msgs[0]} This should be executed in Top Level UK (with ∏ön ÄßÇïï €§) - Verify all failures in user keyword ${tc.kws[0].kws[2]} Nested UK + Check Log Message ${tc[0, 1, 0]} This should be executed in Top Level UK (with ∏ön ÄßÇïï €§) + Verify all failures in user keyword ${tc[0, 2]} Nested UK Continuable and regular failure in UK Check Test Case ${TESTNAME} Several continuable failures and regular failure in nested UK ${tc}= Check Test Case ${TESTNAME} - Verify all failures in user keyword ${tc.kws[0].kws[2]} Nested UK - Verify all failures in user keyword ${tc.kws[1].kws[1].kws[2]} Nested UK + Verify all failures in user keyword ${tc[0, 2]} Nested UK + Verify all failures in user keyword ${tc[1, 1, 2]} Nested UK Continue when setting variables ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} \${ret} = None - Check Log Message ${tc.kws[0].msgs[1]} ContinuableApocalypseException: Can be continued FAIL - Check Log Message ${tc.kws[2].msgs[0]} \${r1} = None - Check Log Message ${tc.kws[2].msgs[1]} \${r2} = None - Check Log Message ${tc.kws[2].msgs[2]} \${r3} = None - Check Log Message ${tc.kws[2].msgs[3]} ContinuableApocalypseException: Can be continued FAIL - Check Log Message ${tc.kws[4].msgs[0]} \@{list} = [ ] - Check Log Message ${tc.kws[4].msgs[1]} ContinuableApocalypseException: Can be continued FAIL - Check Log Message ${tc.kws[6].msgs[0]} No jokes FAIL - Length Should Be ${tc.kws[6].msgs} 1 + Check Log Message ${tc[0, 0]} \${ret} = None + Check Log Message ${tc[0, 1]} ContinuableApocalypseException: Can be continued FAIL + Check Log Message ${tc[2, 0]} \${r1} = None + Check Log Message ${tc[2, 1]} \${r2} = None + Check Log Message ${tc[2, 2]} \${r3} = None + Check Log Message ${tc[2, 3]} ContinuableApocalypseException: Can be continued FAIL + Check Log Message ${tc[4, 0]} \@{list} = [ ] + Check Log Message ${tc[4, 1]} ContinuableApocalypseException: Can be continued FAIL + Check Log Message ${tc[6, 0]} No jokes FAIL + Length Should Be ${tc[6].body} 1 Continuable failure in user keyword returning value Check Test Case ${TESTNAME} Continue in test setup ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.setup.kws[1].msgs[0]} This should be executed in Test Setup - Should Be Empty ${tc.kws} + Check Log Message ${tc.setup[1, 0]} This should be executed in Test Setup + Should Be Empty ${tc.body} Continue in test teardown ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.kws[1].msgs[0]} This should be executed in Test Teardown + Check Log Message ${tc.teardown[1, 0]} This should be executed in Test Teardown Continue many times in test setup and teardown ${tc}= Check Test Case ${TESTNAME} - Verify all failures in user keyword ${tc.setup} Test Setup - Should Be Empty ${tc.kws} + Verify all failures in user keyword ${tc.setup} Test Setup + Should Be Empty ${tc.body} Verify all failures in user keyword ${tc.teardown} Test Teardown Continue in suite teardown ${suite}= Get Test Suite Continue On Failure - Check Log Message ${suite.teardown.kws[1].msgs[0]} This should be executed in Suite Teardown + Check Log Message ${suite.teardown[1, 0]} This should be executed in Suite Teardown Continue in suite setup ${suite}= Get Test Suite Continue On Failure In Suite Setup - Check Log Message ${suite.setup.kws[1].msgs[0]} This should be executed in Suite Setup (with ∏ön ÄßÇïï €§) + Check Log Message ${suite.setup[1, 0]} This should be executed in Suite Setup (with ∏ön ÄßÇïï €§) Continue in for loop ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} ContinuableApocalypseException: 0 FAIL - Check Log Message ${tc.kws[0].kws[0].kws[1].msgs[0]} This should be executed inside for loop - Check Log Message ${tc.kws[0].kws[1].kws[0].msgs[0]} ContinuableApocalypseException: 1 FAIL - Check Log Message ${tc.kws[0].kws[1].kws[1].msgs[0]} This should be executed inside for loop - Check Log Message ${tc.kws[0].kws[2].kws[0].msgs[0]} ContinuableApocalypseException: 2 FAIL - Check Log Message ${tc.kws[0].kws[2].kws[1].msgs[0]} This should be executed inside for loop - Check Log Message ${tc.kws[0].kws[3].kws[0].msgs[0]} ContinuableApocalypseException: 3 FAIL - Check Log Message ${tc.kws[0].kws[3].kws[1].msgs[0]} This should be executed inside for loop - Check Log Message ${tc.kws[0].kws[4].kws[0].msgs[0]} ContinuableApocalypseException: 4 FAIL - Check Log Message ${tc.kws[0].kws[4].kws[1].msgs[0]} This should be executed inside for loop - Check Log Message ${tc.kws[1].msgs[0]} This should be executed after for loop + Check Log Message ${tc[0, 0, 0, 0]} ContinuableApocalypseException: 0 FAIL + Check Log Message ${tc[0, 0, 1, 0]} This should be executed inside for loop + Check Log Message ${tc[0, 1, 0, 0]} ContinuableApocalypseException: 1 FAIL + Check Log Message ${tc[0, 1, 1, 0]} This should be executed inside for loop + Check Log Message ${tc[0, 2, 0, 0]} ContinuableApocalypseException: 2 FAIL + Check Log Message ${tc[0, 2, 1, 0]} This should be executed inside for loop + Check Log Message ${tc[0, 3, 0, 0]} ContinuableApocalypseException: 3 FAIL + Check Log Message ${tc[0, 3, 1, 0]} This should be executed inside for loop + Check Log Message ${tc[0, 4, 0, 0]} ContinuableApocalypseException: 4 FAIL + Check Log Message ${tc[0, 4, 1, 0]} This should be executed inside for loop + Check Log Message ${tc[1, 0]} This should be executed after for loop Continuable and regular failure in for loop Check Test Case ${TESTNAME} @@ -102,9 +102,9 @@ robot.api.ContinuableFailure *** Keywords *** Verify all failures in user keyword [Arguments] ${kw} ${where} - Check Log Message ${kw.kws[0].msgs[0]} ContinuableApocalypseException: 1 FAIL - Check Log Message ${kw.kws[1].msgs[0]} This should be executed in ${where} (with ∏ön ÄßÇïï €§) - Check Log Message ${kw.kws[2].msgs[0]} ContinuableApocalypseException: 2 FAIL - Check Log Message ${kw.kws[3].msgs[0]} This should also be executed in ${where} - Check Log Message ${kw.kws[4].msgs[0]} ContinuableApocalypseException: 3 FAIL - Check Log Message ${kw.kws[5].msgs[0]} This too should also be executed in ${where} + Check Log Message ${kw[0, 0]} ContinuableApocalypseException: 1 FAIL + Check Log Message ${kw[1, 0]} This should be executed in ${where} (with ∏ön ÄßÇïï €§) + Check Log Message ${kw[2, 0]} ContinuableApocalypseException: 2 FAIL + Check Log Message ${kw[3, 0]} This should also be executed in ${where} + Check Log Message ${kw[4, 0]} ContinuableApocalypseException: 3 FAIL + Check Log Message ${kw[5, 0]} This too should also be executed in ${where} diff --git a/atest/robot/running/continue_on_failure_tag.robot b/atest/robot/running/continue_on_failure_tag.robot index 336ed2d7a1a..17443e98f2d 100644 --- a/atest/robot/running/continue_on_failure_tag.robot +++ b/atest/robot/running/continue_on_failure_tag.robot @@ -3,25 +3,25 @@ Suite Setup Run Tests ${EMPTY} running/continue_on_failure_tag.robot Resource atest_resource.robot *** Test Cases *** -Continue in test with tag +Continue in test with continue tag Check Test Case ${TESTNAME} Continue in test with Set Tags Check Test Case ${TESTNAME} -Continue in user keyword with tag +Continue in user keyword with continue tag Check Test Case ${TESTNAME} -Continue in test with tag and UK without tag +Continue in test with continue tag and UK without tag Check Test Case ${TESTNAME} -Continue in test with tag and nested UK with and without tag +Continue in test with continue tag and nested UK with and without tag Check Test Case ${TESTNAME} -Continue in test with tag and two nested UK with tag +Continue in test with continue tag and two nested UK with continue tag Check Test Case ${TESTNAME} -Continue in FOR loop with tag +Continue in FOR loop with continue tag Check Test Case ${TESTNAME} Continue in FOR loop with Set Tags @@ -30,13 +30,13 @@ Continue in FOR loop with Set Tags No continue in FOR loop without tag Check Test Case ${TESTNAME} -Continue in FOR loop in UK with tag +Continue in FOR loop in UK with continue tag Check Test Case ${TESTNAME} Continue in FOR loop in UK without tag Check Test Case ${TESTNAME} -Continue in IF with tag +Continue in IF with continue tag Check Test Case ${TESTNAME} Continue in IF with set and remove tag @@ -45,22 +45,28 @@ Continue in IF with set and remove tag No continue in IF without tag Check Test Case ${TESTNAME} -Continue in IF in UK with tag +Continue in IF in UK with continue tag Check Test Case ${TESTNAME} No continue in IF in UK without tag Check Test Case ${TESTNAME} -Continue in Run Keywords with tag +Continue in Run Keywords with continue tag Check Test Case ${TESTNAME} -Recursive continue in test with tag and two nested UK without tag +Recursive continue in test with continue tag and two nested UK without tag Check Test Case ${TESTNAME} Recursive continue in test with Set Tags and two nested UK without tag Check Test Case ${TESTNAME} -Recursive continue in test with tag and two nested UK with and without tag +Recursive continue in test with continue tag and two nested UK with and without tag + Check Test Case ${TESTNAME} + +Recursive continue in test with continue tag and UK with stop tag + Check Test Case ${TESTNAME} + +Recursive continue in test with continue tag and UK with recursive stop tag Check Test Case ${TESTNAME} Recursive continue in user keyword @@ -68,3 +74,69 @@ Recursive continue in user keyword Recursive continue in nested keyword Check Test Case ${TESTNAME} + +stop-on-failure in keyword in Teardown + Check Test Case ${TESTNAME} + +stop-on-failure with continuable failure in keyword in Teardown + Check Test Case ${TESTNAME} + +stop-on-failure with run-kw-and-continue failure in keyword in Teardown + Check Test Case ${TESTNAME} + +stop-on-failure with run-kw-and-continue failure in keyword + Check Test Case ${TESTNAME} + +Test teardown using run keywords with stop tag in test case + Check Test Case ${TESTNAME} + +Test teardown using user keyword with recursive stop tag in test case + Check Test Case ${TESTNAME} + +Test teardown using user keyword with stop tag in test case + Check Test Case ${TESTNAME} + +Test Teardown with stop tag in user keyword + Check Test Case ${TESTNAME} + +Test Teardown with recursive stop tag in user keyword + Check Test Case ${TESTNAME} + +Test Teardown with recursive stop tag and UK with continue tag + Check Test Case ${TESTNAME} + +Test Teardown with recursive stop tag and UK with recursive continue tag + Check Test Case ${TESTNAME} + +stop-on-failure with Template + Check Test Case ${TESTNAME} + +recursive-stop-on-failure with Template + Check Test Case ${TESTNAME} + +stop-on-failure with Template and Teardown + Check Test Case ${TESTNAME} + +stop-on-failure does not stop continuable failure in test + Check Test Case ${TESTNAME} + +Test recursive-continue-recursive-stop + Check Test Case ${TESTNAME} + +Test recursive-stop-recursive-continue + Check Test Case ${TESTNAME} + +Test recursive-stop-recursive-continue-recursive-stop + Check Test Case ${TESTNAME} + +Test test setup with continue-on-failure + Check Test Case ${TESTNAME} + +Test test setup with recursive-continue-on-failure + Check Test Case ${TESTNAME} + +recursive-stop-on-failure with continue-on-failure + Check Test Case ${TESTNAME} + +recursive-continue-on-failure with stop-on-failure + Check Test Case ${TESTNAME} diff --git a/atest/robot/running/detect_recursion.robot b/atest/robot/running/detect_recursion.robot new file mode 100644 index 00000000000..cd50dc5d443 --- /dev/null +++ b/atest/robot/running/detect_recursion.robot @@ -0,0 +1,41 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/detect_recursion.robot +Library GetNestingLevel.py +Resource atest_resource.robot + +*** Test Cases *** +Infinite recursion + Check Test Case ${TESTNAME} + +Infinite cyclic recursion + Check Test Case ${TESTNAME} + +Infinite recursion with Run Keyword + Check Test Case ${TESTNAME} + +Infinitely recursive for loop + Check Test Case ${TESTNAME} + +Recursion below the recursion limit is ok + [Documentation] Also verifies that recursion limit blown earlier doesn't affect subsequent tests + Check Test Case ${TESTNAME} + +Recursion limit is over 140 started keywords + ${tc} = Check Test Case Infinite recursion + ${level} = Get Nesting Level ${tc} + Should Be True 140 < ${level} < 160 + +Recursion limit can be raised with `sys.setrecursionlimit` + [Setup] Should Be True sys.getrecursionlimit() == 1000 + # Raise limit with executed tests using sitecustomize.py. + Create File %{TEMPDIR}/sitecustomize.py import sys; sys.setrecursionlimit(1500) + Set Environment Variable PYTHONPATH %{TEMPDIR} + # Also raise limit here to be able to process created outputs. + Evaluate sys.setrecursionlimit(1500) + Run Tests -t "Infinite recursion" running/detect_recursion.robot + ${tc} = Check Test Case Infinite recursion + ${level} = Get Nesting Level ${tc} + Should Be True 220 < ${level} < 240 + [Teardown] Run Keywords + ... Remove File %{TEMPDIR}/sitecustomize.py AND + ... Evaluate sys.setrecursionlimit(1000) diff --git a/atest/robot/running/duplicate_suite_name.robot b/atest/robot/running/duplicate_suite_name.robot index 3eedb5d31bc..6386a65e05e 100644 --- a/atest/robot/running/duplicate_suite_name.robot +++ b/atest/robot/running/duplicate_suite_name.robot @@ -1,8 +1,8 @@ -*** Setting *** +*** Settings *** Suite Setup Run Tests --exclude exclude running/duplicate_suite_name Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Suites with same name shoul be executed Should Contain Suites ${SUITE} ... Test diff --git a/atest/robot/running/duplicate_test_name.robot b/atest/robot/running/duplicate_test_name.robot index 56f686b4e8a..68133471a24 100644 --- a/atest/robot/running/duplicate_test_name.robot +++ b/atest/robot/running/duplicate_test_name.robot @@ -1,26 +1,37 @@ -*** Setting *** +*** Settings *** Suite Setup Run Tests --exclude exclude running/duplicate_test_name.robot Resource atest_resource.robot -*** Test Case *** -Tests with same name should be executed +*** Test Cases *** +Tests with same name are executed Should Contain Tests ${SUITE} - ... Same Test Multiple Times - ... Same Test Multiple Times - ... Same Test Multiple Times - ... Same Test With Different Case And Spaces - ... SameTestwith Different CASE and s p a c e s - ... Same Test In Data But Only One Executed + ... Duplicates + ... Duplicates + ... Duplicates + ... Duplicates with different case and spaces + ... Duplicates with different CASE ands p a c e s + ... Duplicates but only one executed + ... Test 1 Test 2 Test 3 + ... Duplicates after resolving variables + ... Duplicates after resolving variables -There should be warning when multiple tests with same name are executed - Check Multiple Tests Log Message ${ERRORS[0]} Same Test Multiple Times - Check Multiple Tests Log Message ${ERRORS[1]} Same Test Multiple Times - Check Multiple Tests Log Message ${ERRORS[2]} SameTestwith Different CASE and s p a c e s +There is warning when multiple tests with same name are executed + Check Multiple Tests Log Message ${ERRORS[0]} Duplicates + Check Multiple Tests Log Message ${ERRORS[1]} Duplicates + Check Multiple Tests Log Message ${ERRORS[2]} Duplicates with different CASE ands p a c e s -There should be no warning when there are multiple tests with same name in data but only one is executed - ${tc} = Check Test Case Same Test In Data But Only One Executed - Check Log Message ${tc.kws[0].msgs[0]} This is executed! - Length Should Be ${ERRORS} 3 +There is warning if names are same after resolving variables + Check Multiple Tests Log Message ${ERRORS[3]} Duplicates after resolving variables + +There is no warning when there are multiple tests with same name but only one is executed + Check Test Case Duplicates but only one executed + Length Should Be ${ERRORS} 4 + +Original name can be same if there is variable and its value changes + Check Test Case Test 1 + Check Test Case Test 2 + Check Test Case Test 3 + Length Should Be ${ERRORS} 4 *** Keywords *** Check Multiple Tests Log Message diff --git a/atest/robot/running/exit_on_failure_tag.robot b/atest/robot/running/exit_on_failure_tag.robot new file mode 100644 index 00000000000..f95649083ca --- /dev/null +++ b/atest/robot/running/exit_on_failure_tag.robot @@ -0,0 +1,17 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/exit_on_failure_tag.robot +Resource atest_resource.robot + +*** Test Cases *** +Passing test with the tag has not special effect + Check Test Case ${TESTNAME} + +Failing test without the tag has no special effect + Check Test Case ${TESTNAME} + +Failing test with the tag initiates exit-on-failure + Check Test Case ${TESTNAME} + +Subsequent tests are not run + Check Test Case ${TESTNAME} 1 + Check Test Case ${TESTNAME} 2 diff --git a/atest/robot/running/failures_in_teardown.robot b/atest/robot/running/failures_in_teardown.robot index a38425dee86..175af344269 100644 --- a/atest/robot/running/failures_in_teardown.robot +++ b/atest/robot/running/failures_in_teardown.robot @@ -6,63 +6,83 @@ Resource atest_resource.robot *** Test Cases *** One Failure ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.kws[1].msgs[0]} This should be executed + Check Log Message ${tc.teardown[1, 0]} This should be executed Multiple Failures ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.kws[2].msgs[0]} This should also be executed + Check Log Message ${tc.teardown[2, 0]} This should also be executed Failure When Setting Variables ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.kws[0].msgs[0]} \${ret} = None - Check Log Message ${tc.teardown.kws[0].msgs[1]} Return values is None FAIL + Check Log Message ${tc.teardown[0, 0]} \${ret} = None + Check Log Message ${tc.teardown[0, 1]} Return values is None FAIL Failure In For Loop Check Test Case ${TESTNAME} Execution Continues After Test Timeout ${tc} = Check Test Case ${TESTNAME} - Should Be True ${tc.elapsedtime} >= 300 + Elapsed Time Should Be Valid ${tc.elapsed_time} minimum=0.3 Execution Stops After Keyword Timeout ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.teardown.kws} 2 - Should Be Equal ${tc.teardown.kws[-1].status} NOT RUN + Length Should Be ${tc.teardown.body} 2 + Should Be Equal ${tc.teardown[-1].status} NOT RUN -Execution Continues After Keyword Timeout Occurs In Executed Keyword +Execution continues if executed keyword fails for keyword timeout ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.teardown.body} 2 - Length Should Be ${tc.teardown.body[0].body} 2 - Should Be Equal ${tc.teardown.body[0].body[0].status} FAIL - Should Be Equal ${tc.teardown.body[0].body[1].status} NOT RUN - Should Be Equal ${tc.teardown.body[0].status} FAIL - Should Be Equal ${tc.teardown.body[1].status} FAIL + Length Should Be ${tc.teardown.body} 2 + Should Be Equal ${tc.teardown.body[0].status} FAIL + Should Be Equal ${tc.teardown.body[1].status} FAIL + Length Should Be ${tc.teardown.body[0].body} 2 + Should Be Equal ${tc.teardown[0, 0].status} FAIL + Check Log Message ${tc.teardown}[0, 0, 0] Keyword timeout 42 milliseconds exceeded. FAIL + Should Be Equal ${tc.teardown[0, 1].status} NOT RUN + Length Should Be ${tc.teardown.body[1].body} 1 + Check Log Message ${tc.teardown}[1, 0] This should be executed FAIL + +Execution stops after keyword timeout if keyword uses WUKS + ${tc} = Check Test Case ${TESTNAME} + Length Should Be ${tc.teardown.body} 2 + Should Be Equal ${tc.teardown.body[0].status} FAIL + Should Be Equal ${tc.teardown.body[1].status} NOT RUN + Length Should Be ${tc.teardown.body[0].body} 2 + Should Be Equal ${tc.teardown[0, 0].status} FAIL + Should Be Equal ${tc.teardown[0, 1].status} FAIL + Length Should Be ${tc.teardown[0, 0].body} 2 + Should Be Equal ${tc.teardown[0, 0, 0].status} PASS + Should Be Equal ${tc.teardown[0, 0, 1].status} FAIL + Check Log Message ${tc.teardown}[0, 0, 1, 0] Failing! FAIL + Length Should Be ${tc.teardown[0, 1].body} 2 + Should Be Equal ${tc.teardown[0, 1, 0].status} FAIL + Check Log Message ${tc.teardown}[0, 1, 0, 0] Keyword timeout 100 milliseconds exceeded. FAIL + Should Be Equal ${tc.teardown[0, 1, 1].status} NOT RUN Execution Continues If Variable Does Not Exist ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.teardown.kws} 3 + Length Should Be ${tc.teardown.body} 3 Execution Continues After Keyword Errors ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.teardown.kws} 3 + Length Should Be ${tc.teardown.body} 3 Execution Stops After Syntax Error ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.teardown.kws} 2 - Should Be Equal ${tc.teardown.kws[-1].status} NOT RUN + Length Should Be ${tc.teardown.body} 2 + Should Be Equal ${tc.teardown[-1].status} NOT RUN Fatal Error ${tc} = Check Test Case ${TESTNAME} 1 - Length Should Be ${tc.teardown.kws} 2 - Should Be Equal ${tc.teardown.kws[-1].status} NOT RUN - Check Test Case ${TESTNAME} 2 + Length Should Be ${tc.teardown.body} 2 + Should Be Equal ${tc.teardown[-1].status} NOT RUN + Check Test Case ${TESTNAME} 2 Suite Teardown Is Executed Fully ${td} = Set Variable ${SUITE.teardown} - Check Log Message ${td.kws[0].msgs[0]} Suite Message 1 FAIL - Check Log Message ${td.kws[1].msgs[0]} Suite Message 2 (with ∏ön ÄßÇïï €§) FAIL - Check Log Message ${td.kws[2].msgs[0]} Variable '\${it is ok not to exist}' not found. FAIL - Check Log Message ${td.kws[3].msgs[0]} This should be executed + Check Log Message ${td[0, 0]} Suite Message 1 FAIL + Check Log Message ${td[1, 0]} Suite Message 2 (with ∏ön ÄßÇïï €§) FAIL + Check Log Message ${td[2, 0]} Variable '\${it is ok not to exist}' not found. FAIL + Check Log Message ${td[3, 0]} This should be executed ${msg} = Catenate SEPARATOR=\n\n ... Suite teardown failed:\nSeveral failures occurred: ... 1) Suite Message 1 @@ -73,5 +93,5 @@ Suite Teardown Is Executed Fully Suite Teardown Should Stop At Fatal Error Run Tests ${EMPTY} running/fatal_error_in_suite_teardown.robot ${ts} = Get Test Suite fatal error in suite teardown - Length Should Be ${ts.teardown.kws} 2 - Should Be Equal ${ts.teardown.kws[-1].status} NOT RUN + Length Should Be ${ts.teardown.body} 2 + Should Be Equal ${ts.teardown[-1].status} NOT RUN diff --git a/atest/robot/running/fatal_exception.robot b/atest/robot/running/fatal_exception.robot index 7166f538ad2..6c3898b42df 100644 --- a/atest/robot/running/fatal_exception.robot +++ b/atest/robot/running/fatal_exception.robot @@ -5,7 +5,7 @@ Resource atest_resource.robot Exit From Python Keyword Run Tests ${EMPTY} running/fatal_exception/01__python_library_kw.robot ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.msgs[0]} This should be executed + Check Log Message ${tc.teardown[0]} This should be executed Check Test Case Test That Should Not Be Run 1 robot.api.FatalError @@ -42,7 +42,7 @@ Multiple Suite Aware Exiting From Suite Setup Run Tests ${EMPTY} running/fatal_exception_suite_setup/ Check Test Case Test That Should Not Be Run 1 ${ts1} = Get Test Suite Suite Setup - Should End With ${ts1.teardown.msgs[0].message} Tearing down 1 + Should End With ${ts1.teardown[0].message} Tearing down 1 Check Test Case Test That Should Not Be Run 2.1 Check Test Case Test That Should Not Be Run 2.2 ${ts2} = Get Test Suite Irrelevant diff --git a/atest/robot/running/flatten.robot b/atest/robot/running/flatten.robot new file mode 100644 index 00000000000..dd3ab863fd9 --- /dev/null +++ b/atest/robot/running/flatten.robot @@ -0,0 +1,51 @@ +*** Settings *** +Suite Setup Run Tests --loglevel trace --listener flatten_listener.Listener running/flatten.robot +Resource atest_resource.robot + +*** Test Cases *** +A single user keyword + ${tc}= User keyword content should be flattened 1 + Check Log Message ${tc[0, 0]} From the main kw + +Nested UK + ${tc}= User keyword content should be flattened 2 + Check Log Message ${tc[0, 0]} arg + Check Log Message ${tc[0, 1]} from nested kw + +Loops and stuff + ${tc}= User keyword content should be flattened 13 + Check Log Message ${tc[0, 0]} inside for 0 + Check Log Message ${tc[0, 1]} inside for 1 + Check Log Message ${tc[0, 2]} inside for 2 + Check Log Message ${tc[0, 3]} inside while 0 + Check Log Message ${tc[0, 4]} \${LIMIT} = 1 + Check Log Message ${tc[0, 5]} inside while 1 + Check Log Message ${tc[0, 6]} \${LIMIT} = 2 + Check Log Message ${tc[0, 7]} inside while 2 + Check Log Message ${tc[0, 8]} \${LIMIT} = 3 + Check Log Message ${tc[0, 9]} inside if + Check Log Message ${tc[0, 10]} fail inside try FAIL + Check Log Message ${tc[0, 11]} Traceback (most recent call last):* DEBUG pattern=True + Check Log Message ${tc[0, 12]} inside except + +Recursion + User keyword content should be flattened 8 + +Listener methods start and end keyword are called + Stderr Should Be Empty + +Log levels + Run Tests ${EMPTY} running/flatten.robot + ${tc}= User keyword content should be flattened 4 + Check Log Message ${tc[0, 0]} INFO 1 + Check Log Message ${tc[0, 1]} Log level changed from INFO to DEBUG. DEBUG + Check Log Message ${tc[0, 2]} INFO 2 + Check Log Message ${tc[0, 3]} DEBUG 2 level=DEBUG + +*** Keywords *** +User keyword content should be flattened + [Arguments] ${expected_message_count}=0 + ${tc}= Check Test Case ${TESTNAME} + Length Should Be ${tc[0].body} ${expected_message_count} + Length Should Be ${tc[0].messages} ${expected_message_count} + RETURN ${tc} diff --git a/atest/robot/running/for/break_and_continue.robot b/atest/robot/running/for/break_and_continue.robot index 262fdc5bf8d..e79998042f0 100644 --- a/atest/robot/running/for/break_and_continue.robot +++ b/atest/robot/running/for/break_and_continue.robot @@ -4,60 +4,56 @@ Resource for.resource Test Template Test and all keywords should have passed *** Test Cases *** -With CONTINUE +CONTINUE allow not run=True -With CONTINUE inside IF - [Template] None - ${tc}= Check test case ${TEST NAME} - Should be FOR loop ${tc.body[0]} 5 FAIL IN RANGE +CONTINUE inside IF + allow not run=True allowed failure=Oh no, got 4 -With CONTINUE inside TRY +CONTINUE inside TRY allow not run=True -With CONTINUE inside EXCEPT and TRY-ELSE - allow not run=True +CONTINUE inside EXCEPT and TRY-ELSE + allow not run=True allowed failure=4 == 4 -With BREAK +BREAK allow not run=True -With BREAK inside IF +BREAK inside IF allow not run=True -With BREAK inside TRY +BREAK inside TRY allow not run=True -With BREAK inside EXCEPT - allow not run=True +BREAK inside EXCEPT + allow not run=True allowed failure=This is excepted! -With BREAK inside TRY-ELSE +BREAK inside TRY-ELSE allow not run=True -With CONTINUE in UK +CONTINUE in UK allow not run=True -With CONTINUE inside IF in UK - [Template] None - ${tc}= Check test case ${TEST NAME} - Should be FOR loop ${tc.body[0].body[0]} 5 FAIL IN RANGE +CONTINUE inside IF in UK + allow not run=True allowed failure=Oh no, got 4 -With CONTINUE inside TRY in UK +CONTINUE inside TRY in UK allow not run=True -With CONTINUE inside EXCEPT and TRY-ELSE in UK - allow not run=True +CONTINUE inside EXCEPT and TRY-ELSE in UK + allow not run=True allowed failure=4 == 4 -With BREAK in UK +BREAK in UK allow not run=True -With BREAK inside IF in UK +BREAK inside IF in UK allow not run=True -With BREAK inside TRY in UK +BREAK inside TRY in UK allow not run=True -With BREAK inside EXCEPT in UK - allow not run=True +BREAK inside EXCEPT in UK + allow not run=True allowed failure=This is excepted! -With BREAK inside TRY-ELSE in UK +BREAK inside TRY-ELSE in UK allow not run=True diff --git a/atest/robot/running/for/continue_for_loop.robot b/atest/robot/running/for/continue_for_loop.robot index 5f50a6bd23e..59ab08e67b4 100644 --- a/atest/robot/running/for/continue_for_loop.robot +++ b/atest/robot/running/for/continue_for_loop.robot @@ -26,8 +26,8 @@ Continue For Loop In User Keyword Without For Loop Should Fail Continue For Loop Keyword Should Log Info ${tc} = Check Test Case Simple Continue For Loop - Should Be Equal ${tc.kws[0].kws[0].kws[0].name} BuiltIn.Continue For Loop - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Continuing for loop from the next iteration. + Should Be Equal ${tc[0, 0, 0].full_name} BuiltIn.Continue For Loop + Check Log Message ${tc[0, 0, 0, 0]} Continuing for loop from the next iteration. Continue For Loop In Test Teardown Test And All Keywords Should Have Passed diff --git a/atest/robot/running/for/exit_for_loop.robot b/atest/robot/running/for/exit_for_loop.robot index 00d3062c9de..aff02d26484 100644 --- a/atest/robot/running/for/exit_for_loop.robot +++ b/atest/robot/running/for/exit_for_loop.robot @@ -29,8 +29,8 @@ Exit For Loop In User Keyword Without For Loop Should Fail Exit For Loop Keyword Should Log Info ${tc} = Check Test Case Simple Exit For Loop - Should Be Equal ${tc.kws[0].kws[0].kws[0].name} BuiltIn.Exit For Loop - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Exiting for loop altogether. + Should Be Equal ${tc[0, 0, 0].full_name} BuiltIn.Exit For Loop + Check Log Message ${tc[0, 0, 0, 0]} Exiting for loop altogether. Exit For Loop In Test Teardown Test And All Keywords Should Have Passed diff --git a/atest/robot/running/for/for.resource b/atest/robot/running/for/for.resource index 258045e7995..9b29093eda6 100644 --- a/atest/robot/running/for/for.resource +++ b/atest/robot/running/for/for.resource @@ -5,33 +5,40 @@ Resource atest_resource.robot Check test and get loop [Arguments] ${test name} ${loop index}=0 ${tc} = Check Test Case ${test name} - [Return] ${tc.kws}[${loop index}] + RETURN ${tc.body}[${loop index}] Check test and failed loop - [Arguments] ${test name} ${type}=FOR ${loop index}=0 + [Arguments] ${test name} ${type}=FOR ${loop index}=0 &{config} ${loop} = Check test and get loop ${test name} ${loop index} - Run Keyword Should Be ${type} loop ${loop} 0 FAIL + Length Should Be ${loop.body} 2 + Should Be Equal ${loop[0].type} ITERATION + Should Be Equal ${loop[1].type} MESSAGE + Run Keyword Should Be ${type} loop ${loop} 1 FAIL &{config} Should be FOR loop [Arguments] ${loop} ${iterations} ${status}=PASS ${flavor}=IN - Should Be Equal ${loop.type} FOR - Should Be Equal ${loop.flavor} ${flavor} - Length Should Be ${loop.kws} ${iterations} - Should Be Equal ${loop.status} ${status} + ... ${start}=${None} ${mode}=${None} ${fill}=${None} + Should Be Equal ${loop.type} FOR + Should Be Equal ${loop.flavor} ${flavor} + Should Be Equal ${loop.start} ${start} + Should Be Equal ${loop.mode} ${mode} + Should Be Equal ${loop.fill} ${fill} + Length Should Be ${loop.non_messages} ${iterations} + Should Be Equal ${loop.status} ${status} Should be IN RANGE loop [Arguments] ${loop} ${iterations} ${status}=PASS - Should Be FOR Loop ${loop} ${iterations} ${status} flavor=IN RANGE + Should Be FOR Loop ${loop} ${iterations} ${status} IN RANGE Should be IN ZIP loop - [Arguments] ${loop} ${iterations} ${status}=PASS - Should Be FOR Loop ${loop} ${iterations} ${status} flavor=IN ZIP + [Arguments] ${loop} ${iterations} ${status}=PASS ${mode}=${None} ${fill}=${None} + Should Be FOR Loop ${loop} ${iterations} ${status} IN ZIP mode=${mode} fill=${fill} Should be IN ENUMERATE loop - [Arguments] ${loop} ${iterations} ${status}=PASS - Should Be FOR Loop ${loop} ${iterations} ${status} flavor=IN ENUMERATE + [Arguments] ${loop} ${iterations} ${status}=PASS ${start}=${None} + Should Be FOR Loop ${loop} ${iterations} ${status} IN ENUMERATE start=${start} Should be FOR iteration - [Arguments] ${iteration} &{variables} + [Arguments] ${iteration} &{assign} Should Be Equal ${iteration.type} ITERATION - Should Be Equal ${iteration.variables} ${variables} + Should Be Equal ${iteration.assign} ${assign} diff --git a/atest/robot/running/for/for.robot b/atest/robot/running/for/for.robot index 4551f2f371f..93e7769b44b 100644 --- a/atest/robot/running/for/for.robot +++ b/atest/robot/running/for/for.robot @@ -1,28 +1,28 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} running/for/for.robot +Suite Setup Run Tests --log log-tests-also-string-reprs.html running/for/for.robot +Suite Teardown File Should Exist ${OUTDIR}/log-tests-also-string-reprs.html Resource for.resource *** Test Cases *** Simple loop - ${tc} = Check test case ${TEST NAME} - ${loop} = Set variable ${tc.body[1]} - Check log message ${tc.body[0].msgs[0]} Not yet in FOR - Should be FOR loop ${loop} 2 - Should be FOR iteration ${loop.body[0]} \${var}=one - Check log message ${loop.body[0].body[0].msgs[0]} var: one - Should be FOR iteration ${loop.body[1]} \${var}=two - Check log message ${loop.body[1].body[0].msgs[0]} var: two - Check log message ${tc.body[2].body[0]} Not in FOR anymore + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} Not yet in FOR + Should be FOR loop ${tc[1]} 2 + Should be FOR iteration ${tc[1, 0]} \${var}=one + Check Log Message ${tc[1, 0, 0, 0]} var: one + Should be FOR iteration ${tc[1, 1]} \${var}=two + Check Log Message ${tc[1, 1, 0, 0]} var: two + Check Log Message ${tc[2, 0]} Not in FOR anymore Variables in values ${loop} = Check test and get loop ${TEST NAME} - Should be FOR loop ${loop} 6 - "Variables in values" helper ${loop.kws[0]} 1 - "Variables in values" helper ${loop.kws[1]} 2 - "Variables in values" helper ${loop.kws[2]} 3 - "Variables in values" helper ${loop.kws[3]} 4 - "Variables in values" helper ${loop.kws[4]} 5 - "Variables in values" helper ${loop.kws[5]} 6 + Should be FOR loop ${loop} 6 + "Variables in values" helper ${loop[0]} 1 + "Variables in values" helper ${loop[1]} 2 + "Variables in values" helper ${loop[2]} 3 + "Variables in values" helper ${loop[3]} 4 + "Variables in values" helper ${loop[4]} 5 + "Variables in values" helper ${loop[5]} 6 Indentation is not required ${loop} = Check test and get loop ${TEST NAME} 1 @@ -30,203 +30,203 @@ Indentation is not required Values on multiple rows ${loop} = Check test and get loop ${TEST NAME} - Should be FOR loop ${loop} 10 - Check log message ${loop.kws[0].kws[0].msgs[0]} 1 + Should be FOR loop ${loop} 10 + Check Log Message ${loop[0, 0, 0]} 1 FOR ${i} IN RANGE 10 - Check log message ${loop.kws[${i}].kws[0].msgs[0]} ${{str($i + 1)}} + Check Log Message ${loop[${i}, 0, 0]} ${{str($i + 1)}} END # Sanity check - Check log message ${loop.kws[0].kws[0].msgs[0]} 1 - Check log message ${loop.kws[4].kws[0].msgs[0]} 5 - Check log message ${loop.kws[9].kws[0].msgs[0]} 10 + Check Log Message ${loop[0, 0, 0]} 1 + Check Log Message ${loop[4, 0, 0]} 5 + Check Log Message ${loop[9, 0, 0]} 10 Keyword arguments on multiple rows ${loop} = Check test and get loop ${TEST NAME} - Should be FOR loop ${loop} 2 - Check log message ${loop.kws[0].kws[1].msgs[0]} 1 2 3 4 5 6 7 one - Check log message ${loop.kws[1].kws[1].msgs[0]} 1 2 3 4 5 6 7 two + Should be FOR loop ${loop} 2 + Check Log Message ${loop[0, 1, 0]} 1 2 3 4 5 6 7 one + Check Log Message ${loop[1, 1, 0]} 1 2 3 4 5 6 7 two Multiple loops in a test - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.kws[0]} 2 - Check log message ${tc.kws[0].kws[0].kws[0].msgs[0]} In first loop with "foo" - Check log message ${tc.kws[0].kws[1].kws[0].msgs[0]} In first loop with "bar" - Should be FOR loop ${tc.kws[1]} 1 - Check kw "My UK 2" ${tc.kws[1].kws[0].kws[0]} Hello, world! - Check log message ${tc.kws[2].msgs[0]} Outside loop - Should be FOR loop ${tc.kws[3]} 2 - Check log message ${tc.kws[3].kws[0].kws[0].msgs[0]} Third loop - Check log message ${tc.kws[3].kws[0].kws[2].msgs[0]} Value: a - Check log message ${tc.kws[3].kws[1].kws[0].msgs[0]} Third loop - Check log message ${tc.kws[3].kws[1].kws[2].msgs[0]} Value: b - Check log message ${tc.kws[4].msgs[0]} The End + ${tc} = Check Test Case ${TEST NAME} + Should be FOR loop ${tc[0]} 2 + Check Log Message ${tc[0, 0, 0, 0]} In first loop with "foo" + Check Log Message ${tc[0, 1, 0, 0]} In first loop with "bar" + Should be FOR loop ${tc[1]} 1 + Check kw "My UK 2" ${tc[1, 0, 0]} Hello, world! + Check Log Message ${tc[2, 0]} Outside loop + Should be FOR loop ${tc[3]} 2 + Check Log Message ${tc[3, 0, 0, 0]} Third loop + Check Log Message ${tc[3, 0, 2, 0]} Value: a + Check Log Message ${tc[3, 1, 0, 0]} Third loop + Check Log Message ${tc[3, 1, 2, 0]} Value: b + Check Log Message ${tc[4, 0]} The End Nested loop syntax - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.kws[0]} 3 - Should be FOR loop ${tc.kws[0].kws[0].kws[1]} 3 - Check log message ${tc.kws[0].kws[0].kws[0].msgs[0]} 1 in - Check log message ${tc.kws[0].kws[0].kws[1].kws[0].kws[0].msgs[0]} values 1 a - Check log message ${tc.kws[0].kws[0].kws[1].kws[1].kws[0].msgs[0]} values 1 b - Check log message ${tc.kws[0].kws[0].kws[1].kws[2].kws[0].msgs[0]} values 1 c - Check log message ${tc.kws[0].kws[0].kws[2].msgs[0]} 1 out - Check log message ${tc.kws[0].kws[1].kws[0].msgs[0]} 2 in - Check log message ${tc.kws[0].kws[1].kws[1].kws[0].kws[0].msgs[0]} values 2 a - Check log message ${tc.kws[0].kws[1].kws[1].kws[1].kws[0].msgs[0]} values 2 b - Check log message ${tc.kws[0].kws[1].kws[1].kws[2].kws[0].msgs[0]} values 2 c - Check log message ${tc.kws[0].kws[1].kws[2].msgs[0]} 2 out - Check log message ${tc.kws[0].kws[2].kws[0].msgs[0]} 3 in - Check log message ${tc.kws[0].kws[2].kws[1].kws[0].kws[0].msgs[0]} values 3 a - Check log message ${tc.kws[0].kws[2].kws[1].kws[1].kws[0].msgs[0]} values 3 b - Check log message ${tc.kws[0].kws[2].kws[1].kws[2].kws[0].msgs[0]} values 3 c - Check log message ${tc.kws[0].kws[2].kws[2].msgs[0]} 3 out - Check log message ${tc.kws[1].msgs[0]} The End + ${tc} = Check Test Case ${TEST NAME} + Should be FOR loop ${tc[0]} 3 + Should be FOR loop ${tc[0, 0, 1]} 3 + Check Log Message ${tc[0, 0, 0, 0]} 1 in + Check Log Message ${tc[0, 0, 1, 0, 0, 0]} values 1 a + Check Log Message ${tc[0, 0, 1, 1, 0, 0]} values 1 b + Check Log Message ${tc[0, 0, 1, 2, 0, 0]} values 1 c + Check Log Message ${tc[0, 0, 2, 0]} 1 out + Check Log Message ${tc[0, 1, 0, 0]} 2 in + Check Log Message ${tc[0, 1, 1, 0, 0, 0]} values 2 a + Check Log Message ${tc[0, 1, 1, 1, 0, 0]} values 2 b + Check Log Message ${tc[0, 1, 1, 2, 0, 0]} values 2 c + Check Log Message ${tc[0, 1, 2, 0]} 2 out + Check Log Message ${tc[0, 2, 0, 0]} 3 in + Check Log Message ${tc[0, 2, 1, 0, 0, 0]} values 3 a + Check Log Message ${tc[0, 2, 1, 1, 0, 0]} values 3 b + Check Log Message ${tc[0, 2, 1, 2, 0, 0]} values 3 c + Check Log Message ${tc[0, 2, 2, 0]} 3 out + Check Log Message ${tc[1, 0]} The End Multiple loops in a loop - Check test case ${TEST NAME} + Check Test Case ${TEST NAME} Deeply nested loops - Check test case ${TEST NAME} + Check Test Case ${TEST NAME} Settings after FOR - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.kws[0]} 1 - Check log message ${tc.teardown.msgs[0]} Teardown was found and eXecuted. + ${tc} = Check Test Case ${TEST NAME} + Should be FOR loop ${tc[0]} 1 + Check Log Message ${tc.teardown[0]} Teardown was found and eXecuted. Looping over empty list variable is OK - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.kws[0]} 1 NOT RUN - Should be FOR iteration ${tc.body[0].body[0]} \${var}= - Check keyword data ${tc.body[0].body[0].body[0]} BuiltIn.Fail args=Not executed status=NOT RUN + ${tc} = Check Test Case ${TEST NAME} + Should be FOR loop ${tc[0]} 1 NOT RUN + Should be FOR iteration ${tc[0, 0]} \${var}= + Check keyword data ${tc[0, 0, 0]} BuiltIn.Fail args=Not executed status=NOT RUN Other iterables - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.kws[2]} 10 + ${tc} = Check Test Case ${TEST NAME} + Should be FOR loop ${tc[2]} 10 Failure inside FOR ${loop} = Check test and get loop ${TEST NAME} 1 - Should be FOR loop ${loop} 1 FAIL - Check log message ${loop.kws[0].kws[0].msgs[0]} Hello before failing kw - Should be equal ${loop.kws[0].kws[0].status} PASS - Check log message ${loop.kws[0].kws[1].msgs[0]} Here we fail! FAIL - Should be equal ${loop.kws[0].kws[1].status} FAIL - Should be equal ${loop.kws[0].kws[2].status} NOT RUN - Should be equal ${loop.kws[0].status} FAIL - Length should be ${loop.kws[0].kws} 3 + Should be FOR loop ${loop} 1 FAIL + Check Log Message ${loop[0, 0, 0]} Hello before failing kw + Should Be Equal ${loop[0, 0].status} PASS + Check Log Message ${loop[0, 1, 0]} Here we fail! FAIL + Should Be Equal ${loop[0, 1].status} FAIL + Should Be Equal ${loop[0, 2].status} NOT RUN + Should Be Equal ${loop[0].status} FAIL + Length Should Be ${loop[0].body} 3 ${loop} = Check test and get loop ${TEST NAME} 2 - Should be FOR loop ${loop} 4 FAIL - Check log message ${loop.kws[0].kws[0].msgs[0]} Before Check - Check log message ${loop.kws[0].kws[2].msgs[0]} After Check - Length should be ${loop.kws[0].kws} 3 - Should be equal ${loop.kws[0].status} PASS - Should be equal ${loop.kws[1].status} PASS - Should be equal ${loop.kws[2].status} PASS - Check log message ${loop.kws[3].kws[0].msgs[0]} Before Check - Check log message ${loop.kws[3].kws[1].msgs[0]} Failure with 4 FAIL - Should be equal ${loop.kws[3].kws[2].status} NOT RUN - Length should be ${loop.kws[3].kws} 3 - Should be equal ${loop.kws[3].status} FAIL + Should be FOR loop ${loop} 4 FAIL + Check Log Message ${loop[0, 0, 0]} Before Check + Check Log Message ${loop[0, 2, 0]} After Check + Length Should Be ${loop[0].body} 3 + Should Be Equal ${loop[0].status} PASS + Should Be Equal ${loop[1].status} PASS + Should Be Equal ${loop[2].status} PASS + Check Log Message ${loop[3, 0, 0]} Before Check + Check Log Message ${loop[3, 1, 0]} Failure with <4> FAIL + Should Be Equal ${loop[3, 2].status} NOT RUN + Length Should Be ${loop[3].body} 3 + Should Be Equal ${loop[3].status} FAIL Loop with user keywords ${loop} = Check test and get loop ${TEST NAME} Should be FOR loop ${loop} 2 - Check kw "My UK" ${loop.kws[0].kws[0]} - Check kw "My UK 2" ${loop.kws[0].kws[1]} foo - Check kw "My UK" ${loop.kws[1].kws[0]} - Check kw "My UK 2" ${loop.kws[1].kws[1]} bar + Check kw "My UK" ${loop[0, 0]} + Check kw "My UK 2" ${loop[0, 1]} foo + Check kw "My UK" ${loop[1, 0]} + Check kw "My UK 2" ${loop[1, 1]} bar Loop with failures in user keywords - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.kws[0]} 2 FAIL + ${tc} = Check Test Case ${TEST NAME} + Should be FOR loop ${tc[0]} 2 FAIL Loop in user keyword - ${tc} = Check test case ${TEST NAME} - Check kw "For In UK" ${tc.kws[0]} - Check kw "For In UK with Args" ${tc.kws[1]} 4 one + ${tc} = Check Test Case ${TEST NAME} + Check kw "For In UK" ${tc[0]} + Check kw "For In UK with Args" ${tc[1]} 4 one Keyword with loop calling other keywords with loops - ${tc} = Check test case ${TEST NAME} - Check kw "Nested For In UK" ${tc.kws[0]} foo + ${tc} = Check Test Case ${TEST NAME} + Check kw "Nested For In UK" ${tc[0]} foo Test with loop calling keywords with loops ${loop} = Check test and get loop ${TEST NAME} 1 - Should be FOR loop ${loop} 1 FAIL - Check kw "For In UK" ${loop.kws[0].kws[0]} - Check kw "For In UK with Args" ${loop.kws[0].kws[1]} 2 one - Check kw "Nested For In UK" ${loop.kws[0].kws[2]} one + Should be FOR loop ${loop} 1 FAIL + Check kw "For In UK" ${loop[0, 0]} + Check kw "For In UK with Args" ${loop[0, 1]} 2 one + Check kw "Nested For In UK" ${loop[0, 2]} one Loop variables is available after loop - Check test case ${TEST NAME} + Check Test Case ${TEST NAME} Assign inside loop ${loop} = Check test and get loop ${TEST NAME} Should be FOR loop ${loop} 2 - Check log message ${loop.kws[0].kws[0].msgs[0]} \${v1} = v1 - Check log message ${loop.kws[0].kws[1].msgs[0]} \${v2} = v2 - Check log message ${loop.kws[0].kws[1].msgs[1]} \${v3} = vY - Check log message ${loop.kws[0].kws[2].msgs[0]} \@{list} = [ v1 | v2 | vY | Y ] - Check log message ${loop.kws[1].kws[0].msgs[0]} \${v1} = v1 - Check log message ${loop.kws[1].kws[1].msgs[0]} \${v2} = v2 - Check log message ${loop.kws[1].kws[1].msgs[1]} \${v3} = vZ - Check log message ${loop.kws[1].kws[2].msgs[0]} \@{list} = [ v1 | v2 | vZ | Z ] + Check Log Message ${loop[0, 0, 0]} \${v1} = v1 + Check Log Message ${loop[0, 1, 0]} \${v2} = v2 + Check Log Message ${loop[0, 1, 1]} \${v3} = vY + Check Log Message ${loop[0, 2, 0]} \@{list} = [ v1 | v2 | vY | Y ] + Check Log Message ${loop[1, 0, 0]} \${v1} = v1 + Check Log Message ${loop[1, 1, 0]} \${v2} = v2 + Check Log Message ${loop[1, 1, 1]} \${v3} = vZ + Check Log Message ${loop[1, 2, 0]} \@{list} = [ v1 | v2 | vZ | Z ] Invalid assign inside loop - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.kws[0]} 1 FAIL + ${tc} = Check Test Case ${TEST NAME} + Should be FOR loop ${tc[0]} 1 FAIL Loop with non-existing keyword - Check test case ${TEST NAME} + Check Test Case ${TEST NAME} Loop with non-existing variable - Check test case ${TEST NAME} + Check Test Case ${TEST NAME} Loop value with non-existing variable - Check test case ${TEST NAME} + Check Test Case ${TEST NAME} Multiple loop variables ${tc} = Check Test Case ${TEST NAME} - ${loop} = Set Variable ${tc.body[0]} - Should be FOR loop ${loop} 4 - Should be FOR iteration ${loop.body[0]} \${x}=1 \${y}=a - Check log message ${loop.body[0].body[0].msgs[0]} 1a - Should be FOR iteration ${loop.body[1]} \${x}=2 \${y}=b - Check log message ${loop.body[1].body[0].msgs[0]} 2b - Should be FOR iteration ${loop.body[2]} \${x}=3 \${y}=c - Check log message ${loop.body[2].body[0].msgs[0]} 3c - Should be FOR iteration ${loop.body[3]} \${x}=4 \${y}=d - Check log message ${loop.body[3].body[0].msgs[0]} 4d - ${loop} = Set Variable ${tc.body[2]} - Should be FOR loop ${loop} 2 - Should be FOR iteration ${loop.body[0]} \${a}=1 \${b}=2 \${c}=3 \${d}=4 \${e}=5 - Should be FOR iteration ${loop.body[1]} \${a}=1 \${b}=2 \${c}=3 \${d}=4 \${e}=5 + ${loop} = Set Variable ${tc[0]} + Should be FOR loop ${loop} 4 + Should be FOR iteration ${loop[0]} \${x}=1 \${y}=a + Check Log Message ${loop[0, 0, 0]} 1a + Should be FOR iteration ${loop[1]} \${x}=2 \${y}=b + Check Log Message ${loop[1, 0, 0]} 2b + Should be FOR iteration ${loop[2]} \${x}=3 \${y}=c + Check Log Message ${loop[2, 0, 0]} 3c + Should be FOR iteration ${loop[3]} \${x}=4 \${y}=d + Check Log Message ${loop[3, 0, 0]} 4d + ${loop} = Set Variable ${tc[2]} + Should be FOR loop ${loop} 2 + Should be FOR iteration ${loop[0]} \${a}=1 \${b}=2 \${c}=3 \${d}=4 \${e}=5 + Should be FOR iteration ${loop[1]} \${a}=1 \${b}=2 \${c}=3 \${d}=4 \${e}=5 Wrong number of loop variables Check test and failed loop ${TEST NAME} 1 Check test and failed loop ${TEST NAME} 2 Cut long iteration variable values - ${tc} = Check test case ${TEST NAME} - ${loop} = Set Variable ${tc.body[6]} + ${tc} = Check Test Case ${TEST NAME} + ${loop} = Set Variable ${tc[6]} ${exp10} = Set Variable 0123456789 ${exp100} = Evaluate "${exp10}" * 10 ${exp200} = Evaluate "${exp10}" * 20 ${exp200+} = Set Variable ${exp200}... - Should be FOR loop ${loop} 6 - Should be FOR iteration ${loop.body[0]} \${var}=${exp10} - Should be FOR iteration ${loop.body[1]} \${var}=${exp100} - Should be FOR iteration ${loop.body[2]} \${var}=${exp200} - Should be FOR iteration ${loop.body[3]} \${var}=${exp200+} - Should be FOR iteration ${loop.body[4]} \${var}=${exp200+} - Should be FOR iteration ${loop.body[5]} \${var}=${exp200+} - ${loop} = Set Variable ${tc.body[7]} - Should be FOR loop ${loop} 2 - Should be FOR iteration ${loop.body[0]} \${var1}=${exp10} \${var2}=${exp100} \${var3}=${exp200} - Should be FOR iteration ${loop.body[1]} \${var1}=${exp200+} \${var2}=${exp200+} \${var3}=${exp200+} + Should be FOR loop ${loop} 6 + Should be FOR iteration ${loop[0]} \${var}=${exp10} + Should be FOR iteration ${loop[1]} \${var}=${exp100} + Should be FOR iteration ${loop[2]} \${var}=${exp200} + Should be FOR iteration ${loop[3]} \${var}=${exp200+} + Should be FOR iteration ${loop[4]} \${var}=${exp200+} + Should be FOR iteration ${loop[5]} \${var}=${exp200+} + ${loop} = Set Variable ${tc[7]} + Should be FOR loop ${loop} 2 + Should be FOR iteration ${loop[0]} \${var1}=${exp10} \${var2}=${exp100} \${var3}=${exp200} + Should be FOR iteration ${loop[1]} \${var1}=${exp200+} \${var2}=${exp200+} \${var3}=${exp200+} Characters that are illegal in XML - ${tc} = Check test case ${TEST NAME} - Should be FOR iteration ${tc.body[0].body[0]} \${var}=illegal: - Should be FOR iteration ${tc.body[0].body[1]} \${var}=more: + ${tc} = Check Test Case ${TEST NAME} + Should be FOR iteration ${tc[0, 0]} \${var}=illegal: + Should be FOR iteration ${tc[0, 1]} \${var}=more: Old :FOR syntax is not supported Check Test Case ${TESTNAME} @@ -235,12 +235,12 @@ Escaping with backslash is not supported Check Test Case ${TESTNAME} FOR is case and space sensitive - Check test case ${TEST NAME} 1 - Check test case ${TEST NAME} 2 + Check Test Case ${TEST NAME} 1 + Check Test Case ${TEST NAME} 2 Invalid END usage - Check test case ${TEST NAME} 1 - Check test case ${TEST NAME} 2 + Check Test Case ${TEST NAME} 1 + Check Test Case ${TEST NAME} 2 Empty body Check test and failed loop ${TEST NAME} @@ -252,11 +252,10 @@ Invalid END Check test and failed loop ${TEST NAME} No loop values - ${tc} = Check test case ${TEST NAME} - Should be FOR loop ${tc.body[0]} 0 FAIL + Check test and failed loop ${TEST NAME} No loop variables - Check Test Case ${TESTNAME} + Check test and failed loop ${TEST NAME} Invalid loop variable Check test and failed loop ${TEST NAME} 1 @@ -267,13 +266,13 @@ Invalid loop variable Check test and failed loop ${TEST NAME} 6 Invalid separator - Check test case ${TEST NAME} + Check Test Case ${TEST NAME} Separator is case- and space-sensitive - Check test case ${TEST NAME} 1 - Check test case ${TEST NAME} 2 - Check test case ${TEST NAME} 3 - Check test case ${TEST NAME} 4 + Check Test Case ${TEST NAME} 1 + Check Test Case ${TEST NAME} 2 + Check Test Case ${TEST NAME} 3 + Check Test Case ${TEST NAME} 4 FOR without any paramenters Check Test Case ${TESTNAME} @@ -284,10 +283,10 @@ Syntax error in nested loop Unexecuted ${tc} = Check Test Case ${TESTNAME} - Should be FOR loop ${tc.body[1].body[0].body[0]} 1 NOT RUN - Should be FOR iteration ${tc.body[1].body[0].body[0].body[0]} \${x}= \${y}= - Should be FOR loop ${tc.body[5]} 1 NOT RUN - Should be FOR iteration ${tc.body[5].body[0]} \${x}= \${y}= + Should be FOR loop ${tc[1, 0, 0]} 1 NOT RUN + Should be FOR iteration ${tc[1, 0, 0, 0]} \${x}= \${y}= + Should be FOR loop ${tc[5]} 1 NOT RUN + Should be FOR iteration ${tc[5, 0]} \${x}= \${y}= Header at the end of file Check Test Case ${TESTNAME} @@ -295,49 +294,49 @@ Header at the end of file *** Keywords *** "Variables in values" helper [Arguments] ${kw} ${num} - Check log message ${kw.kws[0].msgs[0]} ${num} - Check log message ${kw.kws[1].msgs[0]} Hello from for loop - Should be equal ${kw.kws[2].name} BuiltIn.No Operation + Check Log Message ${kw[0, 0]} ${num} + Check Log Message ${kw[1, 0]} Hello from for loop + Should Be Equal ${kw[2].full_name} BuiltIn.No Operation Check kw "My UK" [Arguments] ${kw} - Should be equal ${kw.name} My UK - Should be equal ${kw.kws[0].name} BuiltIn.No Operation - Check log message ${kw.kws[1].msgs[0]} We are in My UK + Should Be Equal ${kw.full_name} My UK + Should Be Equal ${kw[0].full_name} BuiltIn.No Operation + Check Log Message ${kw[1, 0]} We are in My UK Check kw "My UK 2" [Arguments] ${kw} ${arg} - Should be equal ${kw.name} My UK 2 - Check kw "My UK" ${kw.kws[0]} - Check log message ${kw.kws[1].msgs[0]} My UK 2 got argument "${arg}" - Check kw "My UK" ${kw.kws[2]} + Should Be Equal ${kw.full_name} My UK 2 + Check kw "My UK" ${kw[0]} + Check Log Message ${kw[1, 0]} My UK 2 got argument "${arg}" + Check kw "My UK" ${kw[2]} Check kw "For In UK" [Arguments] ${kw} - Should be equal ${kw.name} For In UK - Check log message ${kw.kws[0].msgs[0]} Not for yet - Should be FOR loop ${kw.kws[1]} 2 - Check log message ${kw.kws[1].kws[0].kws[0].msgs[0]} This is for with 1 - Check kw "My UK" ${kw.kws[1].kws[0].kws[1]} - Check log message ${kw.kws[1].kws[1].kws[0].msgs[0]} This is for with 2 - Check kw "My UK" ${kw.kws[1].kws[1].kws[1]} - Check log message ${kw.kws[2].msgs[0]} Not for anymore + Should Be Equal ${kw.full_name} For In UK + Check Log Message ${kw[0, 0]} Not for yet + Should be FOR loop ${kw[1]} 2 + Check Log Message ${kw[1, 0, 0, 0]} This is for with 1 + Check kw "My UK" ${kw[1, 0, 1]} + Check Log Message ${kw[1, 1, 0, 0]} This is for with 2 + Check kw "My UK" ${kw[1, 1, 1]} + Check Log Message ${kw[2, 0]} Not for anymore Check kw "For In UK With Args" [Arguments] ${kw} ${arg_count} ${first_arg} - Should be equal ${kw.name} For In UK With Args - Should be FOR loop ${kw.kws[0]} ${arg_count} - Check kw "My UK 2" ${kw.kws[0].kws[0].kws[0]} ${first_arg} - Should be FOR loop ${kw.kws[2]} 1 - Check log message ${kw.kws[2].kws[0].kws[0].msgs[0]} This for loop is executed only once + Should Be Equal ${kw.full_name} For In UK With Args + Should be FOR loop ${kw[0]} ${arg_count} + Check kw "My UK 2" ${kw[0, 0, 0]} ${first_arg} + Should be FOR loop ${kw[2]} 1 + Check Log Message ${kw[2, 0, 0, 0]} This for loop is executed only once Check kw "Nested For In UK" [Arguments] ${kw} ${first_arg} - Should be FOR loop ${kw.kws[0]} 1 FAIL - Check kw "For In UK" ${kw.kws[0].kws[0].kws[0]} - ${nested2} = Set Variable ${kw.kws[0].kws[0].kws[1]} - Should be equal ${nested2.name} Nested For In UK 2 - Should be FOR loop ${nested2.kws[0]} 2 - Check kw "For In UK" ${nested2.kws[0].kws[0].kws[0]} - Check log message ${nested2.kws[0].kws[0].kws[1].msgs[0]} Got arg: ${first_arg} - Check log message ${nested2.kws[1].msgs[0]} This ought to be enough FAIL + Should be FOR loop ${kw[0]} 1 FAIL + Check kw "For In UK" ${kw[0, 0, 0]} + ${nested2} = Set Variable ${kw[0, 0, 1]} + Should Be Equal ${nested2.full_name} Nested For In UK 2 + Should be FOR loop ${nested2[0]} 2 + Check kw "For In UK" ${nested2[0, 0, 0]} + Check Log Message ${nested2[0, 0, 1, 0]} Got arg: ${first_arg} + Check Log Message ${nested2[1, 0]} This ought to be enough FAIL diff --git a/atest/robot/running/for/for_dict_iteration.robot b/atest/robot/running/for/for_dict_iteration.robot index ceb0c5caf45..a8b840726fc 100644 --- a/atest/robot/running/for/for_dict_iteration.robot +++ b/atest/robot/running/for/for_dict_iteration.robot @@ -43,7 +43,7 @@ FOR IN ENUMERATE loop with three variables FOR IN ENUMERATE loop with start ${loop} = Check test and get loop ${TESTNAME} - Should be IN ENUMERATE loop ${loop} 3 + Should be IN ENUMERATE loop ${loop} 3 start=42 FOR IN ENUMERATE loop with more than three variables is invalid Check test and failed loop ${TESTNAME} IN ENUMERATE @@ -72,14 +72,14 @@ Equal sign in variable ... FOR loop iteration over values that are all in 'name=value' format like 'a=1' is deprecated. ... In the future this syntax will mean iterating over names and values separately like when iterating over '\&{dict} variables. ... Escape at least one of the values like 'a\\=1' to use normal FOR loop iteration and to disable this warning. - Check Log Message ${tc.body[0].msgs[0]} ${message} WARN - Check Log Message ${ERRORS}[0] ${message} WARN + Check Log Message ${tc[0, 0]} ${message} WARN + Check Log Message ${ERRORS}[0] ${message} WARN ${message} = Catenate ... FOR loop iteration over values that are all in 'name=value' format like 'x==1' is deprecated. ... In the future this syntax will mean iterating over names and values separately like when iterating over '\&{dict} variables. ... Escape at least one of the values like 'x\\==1' to use normal FOR loop iteration and to disable this warning. - Check Log Message ${tc.body[2].msgs[0]} ${message} WARN - Check Log Message ${ERRORS}[1] ${message} WARN + Check Log Message ${tc[2, 0]} ${message} WARN + Check Log Message ${ERRORS}[1] ${message} WARN Non-string keys Check Test Case ${TESTNAME} diff --git a/atest/robot/running/for/for_in_enumerate.robot b/atest/robot/running/for/for_in_enumerate.robot index a47d2a809d0..67ddc3c3134 100644 --- a/atest/robot/running/for/for_in_enumerate.robot +++ b/atest/robot/running/for/for_in_enumerate.robot @@ -21,7 +21,7 @@ Values from list variable Start ${loop} = Check test and get loop ${TEST NAME} - Should be IN ENUMERATE loop ${loop} 5 + Should be IN ENUMERATE loop ${loop} 5 start=1 Should be FOR iteration ${loop.body[0]} \${index}=1 \${item}=1 Should be FOR iteration ${loop.body[1]} \${index}=2 \${item}=2 Should be FOR iteration ${loop.body[2]} \${index}=3 \${item}=3 @@ -33,12 +33,14 @@ Escape start Should be IN ENUMERATE loop ${loop} 2 Invalid start - ${loop} = Check test and get loop ${TEST NAME} - Should be IN ENUMERATE loop ${loop} 0 status=FAIL + Check test and failed loop ${TEST NAME} IN ENUMERATE start=invalid Invalid variable in start + Check test and failed loop ${TEST NAME} IN ENUMERATE start=\${invalid} + +Start multiple times ${loop} = Check test and get loop ${TEST NAME} - Should be IN ENUMERATE loop ${loop} 0 status=FAIL + Should be IN ENUMERATE loop ${loop} 1 start=2 Index and two items ${loop} = Check test and get loop ${TEST NAME} 1 @@ -66,4 +68,4 @@ No values Check test and failed loop ${TEST NAME} IN ENUMERATE No values with start - Check test and failed loop ${TEST NAME} IN ENUMERATE + Check test and failed loop ${TEST NAME} IN ENUMERATE start=0 diff --git a/atest/robot/running/for/for_in_range.robot b/atest/robot/running/for/for_in_range.robot index 9c3f2c12a7a..0defe65d78d 100644 --- a/atest/robot/running/for/for_in_range.robot +++ b/atest/robot/running/for/for_in_range.robot @@ -5,65 +5,65 @@ Resource for.resource *** Test Cases *** Only stop ${loop} = Check test and get loop ${TEST NAME} - Should be IN RANGE loop ${loop} 100 - Should be FOR iteration ${loop.body[0]} \${i}=0 - Check log message ${loop.body[0].body[1].msgs[0]} i: 0 - Should be FOR iteration ${loop.body[1]} \${i}=1 - Check log message ${loop.body[1].body[1].msgs[0]} i: 1 - Should be FOR iteration ${loop.body[42]} \${i}=42 - Check log message ${loop.body[42].body[1].msgs[0]} i: 42 - Should be FOR iteration ${loop.body[-1]} \${i}=99 - Check log message ${loop.body[-1].body[1].msgs[0]} i: 99 + Should be IN RANGE loop ${loop} 100 + Should be FOR iteration ${loop[0]} \${i}=0 + Check log message ${loop[0, 1, 0]} i: 0 + Should be FOR iteration ${loop[1]} \${i}=1 + Check log message ${loop[1, 1, 0]} i: 1 + Should be FOR iteration ${loop[42]} \${i}=42 + Check log message ${loop[42, 1, 0]} i: 42 + Should be FOR iteration ${loop[-1]} \${i}=99 + Check log message ${loop[-1, 1, 0]} i: 99 Start and stop - ${loop} = Check test and get loop ${TEST NAME} - Should be IN RANGE loop ${loop} 4 + ${loop} = Check test and get loop ${TEST NAME} + Should be IN RANGE loop ${loop} 4 Start, stop and step - ${loop} = Check test and get loop ${TEST NAME} - Should be IN RANGE loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${item}=10 - Should be FOR iteration ${loop.body[1]} \${item}=7 - Should be FOR iteration ${loop.body[2]} \${item}=4 + ${loop} = Check test and get loop ${TEST NAME} + Should be IN RANGE loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${item}=10 + Should be FOR iteration ${loop[1]} \${item}=7 + Should be FOR iteration ${loop[2]} \${item}=4 Float stop - ${loop} = Check test and get loop ${TEST NAME} 1 - Should be IN RANGE loop ${loop} 4 - Should be FOR iteration ${loop.body[0]} \${item}=0.0 - Should be FOR iteration ${loop.body[1]} \${item}=1.0 - Should be FOR iteration ${loop.body[2]} \${item}=2.0 - Should be FOR iteration ${loop.body[3]} \${item}=3.0 - ${loop} = Check test and get loop ${TEST NAME} 2 - Should be IN RANGE loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${item}=0.0 - Should be FOR iteration ${loop.body[1]} \${item}=1.0 - Should be FOR iteration ${loop.body[2]} \${item}=2.0 + ${loop} = Check test and get loop ${TEST NAME} 1 + Should be IN RANGE loop ${loop} 4 + Should be FOR iteration ${loop[0]} \${item}=0.0 + Should be FOR iteration ${loop[1]} \${item}=1.0 + Should be FOR iteration ${loop[2]} \${item}=2.0 + Should be FOR iteration ${loop[3]} \${item}=3.0 + ${loop} = Check test and get loop ${TEST NAME} 2 + Should be IN RANGE loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${item}=0.0 + Should be FOR iteration ${loop[1]} \${item}=1.0 + Should be FOR iteration ${loop[2]} \${item}=2.0 Float start and stop - ${loop} = Check test and get loop ${TEST NAME} 1 - Should be IN RANGE loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${item}=-1.5 - Should be FOR iteration ${loop.body[1]} \${item}=-0.5 - Should be FOR iteration ${loop.body[2]} \${item}=0.5 - ${loop} = Check test and get loop ${TEST NAME} 2 0 - Should be IN RANGE loop ${loop} 4 - Should be FOR iteration ${loop.body[0]} \${item}=-1.5 - Should be FOR iteration ${loop.body[1]} \${item}=-0.5 - Should be FOR iteration ${loop.body[2]} \${item}=0.5 - Should be FOR iteration ${loop.body[3]} \${item}=1.5 + ${loop} = Check test and get loop ${TEST NAME} 1 + Should be IN RANGE loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${item}=-1.5 + Should be FOR iteration ${loop[1]} \${item}=-0.5 + Should be FOR iteration ${loop[2]} \${item}=0.5 + ${loop} = Check test and get loop ${TEST NAME} 2 0 + Should be IN RANGE loop ${loop} 4 + Should be FOR iteration ${loop[0]} \${item}=-1.5 + Should be FOR iteration ${loop[1]} \${item}=-0.5 + Should be FOR iteration ${loop[2]} \${item}=0.5 + Should be FOR iteration ${loop[3]} \${item}=1.5 Float start, stop and step - ${loop} = Check test and get loop ${TEST NAME} - Should be IN RANGE loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${item}=10.99 - Should be FOR iteration ${loop.body[1]} \${item}=7.95 - Should be FOR iteration ${loop.body[2]} \${item}=4.91 + ${loop} = Check test and get loop ${TEST NAME} + Should be IN RANGE loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${item}=10.99 + Should be FOR iteration ${loop[1]} \${item}=7.95 + Should be FOR iteration ${loop[2]} \${item}=4.91 Variables in arguments - ${loop} = Check test and get loop ${TEST NAME} 0 - Should be IN RANGE loop ${loop} 2 - ${loop} = Check test and get loop ${TEST NAME} 2 - Should be IN RANGE loop ${loop} 1 + ${loop} = Check test and get loop ${TEST NAME} 0 + Should be IN RANGE loop ${loop} 2 + ${loop} = Check test and get loop ${TEST NAME} 2 + Should be IN RANGE loop ${loop} 1 Calculations Check test case ${TEST NAME} @@ -72,15 +72,15 @@ Calculations with floats Check test case ${TEST NAME} Multiple variables - ${loop} = Check test and get loop ${TEST NAME} 0 - Should be IN RANGE loop ${loop} 1 - Should be FOR iteration ${loop.body[0]} \${a}=0 \${b}=1 \${c}=2 \${d}=3 \${e}=4 - ${loop} = Check test and get loop ${TEST NAME} 2 - Should be IN RANGE loop ${loop} 4 - Should be FOR iteration ${loop.body[0]} \${i}=-1 \${j}=0 \${k}=1 - Should be FOR iteration ${loop.body[1]} \${i}=2 \${j}=3 \${k}=4 - Should be FOR iteration ${loop.body[2]} \${i}=5 \${j}=6 \${k}=7 - Should be FOR iteration ${loop.body[3]} \${i}=8 \${j}=9 \${k}=10 + ${loop} = Check test and get loop ${TEST NAME} 0 + Should be IN RANGE loop ${loop} 1 + Should be FOR iteration ${loop[0]} \${a}=0 \${b}=1 \${c}=2 \${d}=3 \${e}=4 + ${loop} = Check test and get loop ${TEST NAME} 2 + Should be IN RANGE loop ${loop} 4 + Should be FOR iteration ${loop[0]} \${i}=-1 \${j}=0 \${k}=1 + Should be FOR iteration ${loop[1]} \${i}=2 \${j}=3 \${k}=4 + Should be FOR iteration ${loop[2]} \${i}=5 \${j}=6 \${k}=7 + Should be FOR iteration ${loop[3]} \${i}=8 \${j}=9 \${k}=10 Too many arguments Check test and failed loop ${TEST NAME} IN RANGE diff --git a/atest/robot/running/for/for_in_zip.robot b/atest/robot/running/for/for_in_zip.robot index b512c9a9a21..987e080ff40 100644 --- a/atest/robot/running/for/for_in_zip.robot +++ b/atest/robot/running/for/for_in_zip.robot @@ -5,70 +5,122 @@ Resource for.resource *** Test Cases *** Two variables and lists ${loop} = Check test and get loop ${TEST NAME} - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=a \${y}=x - Should be FOR iteration ${loop.body[1]} \${x}=b \${y}=y - Should be FOR iteration ${loop.body[2]} \${x}=c \${y}=z + Should be IN ZIP loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${x}=a \${y}=x + Should be FOR iteration ${loop[1]} \${x}=b \${y}=y + Should be FOR iteration ${loop[2]} \${x}=c \${y}=z -Uneven lists +Uneven lists cause deprecation warning by default ${loop} = Check test and get loop ${TEST NAME} - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=a \${y}=1 - Should be FOR iteration ${loop.body[1]} \${x}=b \${y}=2 - Should be FOR iteration ${loop.body[2]} \${x}=c \${y}=3 + Should be IN ZIP loop ${loop} 3 + Check Log Message ${loop[0]} + ... FOR IN ZIP default mode will be changed from SHORTEST to STRICT in Robot Framework 8.0. Use 'mode=SHORTEST' to keep using the SHORTEST mode. If the mode is not changed, execution will fail like this in the future: FOR IN ZIP items must have equal lengths in the STRICT mode, but lengths are 3 and 5. WARN + Should be FOR iteration ${loop[1]} \${x}=a \${y}=1 + Should be FOR iteration ${loop[2]} \${x}=b \${y}=2 + Should be FOR iteration ${loop[3]} \${x}=c \${y}=3 Three variables and lists ${loop} = Check test and get loop ${TEST NAME} - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=a \${y}=x \${z}=1 - Should be FOR iteration ${loop.body[1]} \${x}=b \${y}=y \${z}=2 - Should be FOR iteration ${loop.body[2]} \${x}=c \${y}=z \${z}=3 + Should be IN ZIP loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${x}=a \${y}=x \${z}=1 + Should be FOR iteration ${loop[1]} \${x}=b \${y}=y \${z}=2 + Should be FOR iteration ${loop[2]} \${x}=c \${y}=z \${z}=3 Six variables and lists ${loop} = Check test and get loop ${TEST NAME} - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=a \${y}=x \${z}=1 \${å}=1 \${ä}=x \${ö}=a - Should be FOR iteration ${loop.body[1]} \${x}=b \${y}=y \${z}=2 \${å}=2 \${ä}=y \${ö}=b - Should be FOR iteration ${loop.body[2]} \${x}=c \${y}=z \${z}=3 \${å}=3 \${ä}=z \${ö}=c + Should be IN ZIP loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${x}=a \${y}=x \${z}=1 \${å}=1 \${ä}=x \${ö}=a + Should be FOR iteration ${loop[1]} \${x}=b \${y}=y \${z}=2 \${å}=2 \${ä}=y \${ö}=b + Should be FOR iteration ${loop[2]} \${x}=c \${y}=z \${z}=3 \${å}=3 \${ä}=z \${ö}=c One variable and list ${loop} = Check test and get loop ${TEST NAME} - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=a - Should be FOR iteration ${loop.body[1]} \${x}=b - Should be FOR iteration ${loop.body[2]} \${x}=c + Should be IN ZIP loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${x}=a + Should be FOR iteration ${loop[1]} \${x}=b + Should be FOR iteration ${loop[2]} \${x}=c One variable and two lists ${loop} = Check test and get loop ${TEST NAME} - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=('a', 'x') - Should be FOR iteration ${loop.body[1]} \${x}=('b', 'y') - Should be FOR iteration ${loop.body[2]} \${x}=('c', 'z') + Should be IN ZIP loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${x}=('a', 'x') + Should be FOR iteration ${loop[1]} \${x}=('b', 'y') + Should be FOR iteration ${loop[2]} \${x}=('c', 'z') One variable and six lists ${loop} = Check test and get loop ${TEST NAME} - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=('a', 'x', '1', '1', 'x', 'a') - Should be FOR iteration ${loop.body[1]} \${x}=('b', 'y', '2', '2', 'y', 'b') - Should be FOR iteration ${loop.body[2]} \${x}=('c', 'z', '3', '3', 'z', 'c') + Should be IN ZIP loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${x}=('a', 'x', 1, 1, 'x', 'a') + Should be FOR iteration ${loop[1]} \${x}=('b', 'y', 2, 2, 'y', 'b') + Should be FOR iteration ${loop[2]} \${x}=('c', 'z', 3, 3, 'z', 'c') Other iterables Check Test Case ${TEST NAME} List variable containing iterables - ${loop} = Check test and get loop ${TEST NAME} 2 - Should be IN ZIP loop ${loop} 3 - Should be FOR iteration ${loop.body[0]} \${x}=a \${y}=x \${z}=f - Should be FOR iteration ${loop.body[1]} \${x}=b \${y}=y \${z}=o - Should be FOR iteration ${loop.body[2]} \${x}=c \${y}=z \${z}=o + ${loop} = Check test and get loop ${TEST NAME} 1 + Should be IN ZIP loop ${loop} 3 + Should be FOR iteration ${loop[0]} \${x}=a \${y}=x \${z}=f + Should be FOR iteration ${loop[1]} \${x}=b \${y}=y \${z}=o + Should be FOR iteration ${loop[2]} \${x}=c \${y}=z \${z}=o List variable with iterables can be empty ${tc} = Check Test Case ${TEST NAME} - Should be IN ZIP loop ${tc.body[0]} 1 NOT RUN - Should be FOR iteration ${tc.body[0].body[0]} \${x}= - Should be IN ZIP loop ${tc.body[1]} 1 NOT RUN - Should be FOR iteration ${tc.body[1].body[0]} \${x}= \${y}= \${z}= - Check Log Message ${tc.body[2].msgs[0]} Executed! + Should be IN ZIP loop ${tc[0]} 1 NOT RUN + Should be FOR iteration ${tc[0, 0]} \${x}= + Should be IN ZIP loop ${tc[1]} 1 NOT RUN + Should be FOR iteration ${tc[1, 0]} \${x}= \${y}= \${z}= + Check Log Message ${tc[2, 0]} Executed! + +Strict mode + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 3 PASS mode=STRICT + Should be IN ZIP loop ${tc[2]} 1 FAIL mode=strict + +Strict mode requires items to have length + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 1 FAIL mode=STRICT + +Shortest mode + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 3 PASS mode=SHORTEST fill=ignored + Should be IN ZIP loop ${tc[3]} 3 PASS mode=\${{'shortest'}} + +Shortest mode supports infinite iterators + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 3 PASS mode=SHORTEST + +Longest mode + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 3 PASS mode=LONGEST + Should be IN ZIP loop ${tc[3]} 5 PASS mode=LoNgEsT + +Longest mode with custom fill value + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 5 PASS mode=longest fill=? + Should be IN ZIP loop ${tc[3]} 3 PASS mode=longest fill=\${0} + +Invalid mode + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 1 FAIL mode=bad + +Invalid mode from variable + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 1 FAIL mode=\${{'bad'}} + +Config more than once + ${tc} = Check Test Case ${TEST NAME} 1 + Should be IN ZIP loop ${tc[0]} 1 FAIL mode=shortest + ${tc} = Check Test Case ${TEST NAME} 2 + Should be IN ZIP loop ${tc[0]} 1 FAIL fill=z + +Non-existing variable in mode + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 1 FAIL mode=\${bad} fill=\${ignored} + +Non-existing variable in fill value + ${tc} = Check Test Case ${TEST NAME} + Should be IN ZIP loop ${tc[0]} 1 FAIL mode=longest fill=\${bad} Not iterable value Check test and failed loop ${TEST NAME} IN ZIP diff --git a/atest/robot/running/group/group.robot b/atest/robot/running/group/group.robot new file mode 100644 index 00000000000..f579f090cf5 --- /dev/null +++ b/atest/robot/running/group/group.robot @@ -0,0 +1,42 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/group/group.robot +Resource atest_resource.robot + +*** Test Cases *** +Basics + ${tc}= Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP name=1st group children=2 + Check Body Item Data ${tc[0, 0]} type=KEYWORD name=Log args=Inside group + Check Body Item Data ${tc[0, 1]} type=KEYWORD name=Log args=Still inside + Check Body Item Data ${tc[1]} type=GROUP name=second children=1 + Check Body Item Data ${tc[1, 0]} type=KEYWORD name=Log args=Inside second group + Check Body Item Data ${tc[2]} type=KEYWORD name=Log args=After + +Failing + ${tc}= Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP name=Fails children=2 status=FAIL message=Failing inside GROUP! + Check Body Item Data ${tc[0, 0]} type=KEYWORD name=Fail children=1 status=FAIL message=Failing inside GROUP! + Check Body Item Data ${tc[0, 1]} type=KEYWORD name=Fail children=0 status=NOT RUN + Check Body Item Data ${tc[1]} type=GROUP name=Not run children=1 status=NOT RUN + Check Body Item Data ${tc[1, 0]} type=KEYWORD name=Fail children=0 status=NOT RUN + +Anonymous + ${tc}= Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP name=${EMPTY} children=1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD name=Log args=Inside unnamed group + +Variable in name + ${tc}= Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP name=Test is named: ${TEST NAME} children=1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD name=Log args=\${TEST_NAME} + Check Log Message ${tc[0, 0, 0]} ${TEST NAME} + Check Body Item Data ${tc[1]} type=GROUP name=42 children=1 + Check Body Item Data ${tc[1, 0]} type=KEYWORD name=Log args=Should be 42 + +In user keyword + ${tc}= Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=KEYWORD name=Keyword children=4 + Check Body Item Data ${tc[0, 0]} type=KEYWORD name=Log args=Before + Check Body Item Data ${tc[0, 1]} type=GROUP name=First children=2 + Check Body Item Data ${tc[0, 2]} type=GROUP name=Second children=1 + Check Body Item Data ${tc[0, 3]} type=KEYWORD name=Log args=After diff --git a/atest/robot/running/group/invalid_group.robot b/atest/robot/running/group/invalid_group.robot new file mode 100644 index 00000000000..f6d415cdaf9 --- /dev/null +++ b/atest/robot/running/group/invalid_group.robot @@ -0,0 +1,44 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/group/invalid_group.robot +Resource atest_resource.robot + +*** Test Cases *** +END missing + ${tc} = Check Test Case ${TESTNAME} + Length Should Be ${tc.body} 1 + Check Body Item Data ${tc[0]} GROUP status=FAIL children=2 message=GROUP must have closing END. + Check Body Item Data ${tc[0, 0]} KEYWORD status=NOT RUN children=0 name=Fail args=Not run + Check Body Item Data ${tc[0, 1]} MESSAGE level=FAIL message=GROUP must have closing END. + +Empty + ${tc} Check Test Case ${TESTNAME} + Length Should Be ${tc.body} 2 + Check Body Item Data ${tc[0]} GROUP status=FAIL children=1 message=GROUP cannot be empty. + Check Body Item Data ${tc[0, 0]} MESSAGE level=FAIL message=GROUP cannot be empty. + Check Body Item Data ${tc[1]} KEYWORD status=NOT RUN children=0 name=Log args=Outside + +Multiple parameters + ${tc} Check Test Case ${TESTNAME} + Length Should Be ${tc.body} 2 + Check Body Item Data ${tc[0]} GROUP status=FAIL children=2 message=GROUP accepts only one argument as name, got 3 arguments 'Too', 'many' and 'values'. + Check Body Item Data ${tc[0, 0]} KEYWORD status=NOT RUN children=0 name=Fail args=Not run + Check Body Item Data ${tc[0, 1]} MESSAGE level=FAIL message=GROUP accepts only one argument as name, got 3 arguments 'Too', 'many' and 'values'. + Check Body Item Data ${tc[1]} KEYWORD status=NOT RUN children=0 name=Log args=Last Keyword + +Non-existing variable in name + ${tc} Check Test Case ${TESTNAME} + Length Should Be ${tc.body} 2 + Check Body Item Data ${tc[0]} GROUP status=FAIL children=2 message=Variable '\${non_existing_var}' not found. name=\${non_existing_var} in name + Check Body Item Data ${tc[0, 0]} KEYWORD status=NOT RUN children=0 name=Fail args=Not run + Check Body Item Data ${tc[0, 1]} MESSAGE level=FAIL message=Variable '\${non_existing_var}' not found. + Check Body Item Data ${tc[1]} KEYWORD status=NOT RUN children=0 name=Log args=Last Keyword + +Invalid data is not reported after failures + ${tc} Check Test Case ${TESTNAME} + Length Should Be ${tc.body} 4 + Check Body Item Data ${tc[0]} KEYWORD status=FAIL children=1 name=Fail args=Something bad happened! message=Something bad happened! + Check Body Item Data ${tc[1]} GROUP status=NOT RUN children=1 name=\${non_existing_non_executed_variable_is_ok} + Check Body Item Data ${tc[1, 0]} KEYWORD status=NOT RUN children=0 name=Fail args=Not run + Check Body Item Data ${tc[2]} GROUP status=NOT RUN children=0 name=Empty non-executed GROUP is ok + Check Body Item Data ${tc[3]} GROUP status=NOT RUN children=1 name=Even missing END is ok + Check Body Item Data ${tc[3, 0]} KEYWORD status=NOT RUN children=0 name=Fail args=Not run diff --git a/atest/robot/running/group/nesting_group.robot b/atest/robot/running/group/nesting_group.robot new file mode 100644 index 00000000000..1d612e0c189 --- /dev/null +++ b/atest/robot/running/group/nesting_group.robot @@ -0,0 +1,51 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/group/nesting_group.robot +Resource atest_resource.robot + +*** Test Cases *** +Nested + ${tc} Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP name= + Check Body Item Data ${tc[0, 0]} type=KEYWORD name=Set Variable + Check Body Item Data ${tc[0, 1]} type=GROUP name=This Is A Named Group + Check Body Item Data ${tc[0, 1, 0]} type=KEYWORD name=Should Be Equal + +With other control structures + ${tc} Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=IF/ELSE ROOT + Check Body Item Data ${tc[0, 0]} type=IF condition=True children=2 + Check Body Item Data ${tc[0, 0, 0]} type=GROUP name=Hello children=1 + Check Body Item Data ${tc[0, 0, 0, 0]} type=VAR name=\${i} + Check Body Item Data ${tc[0, 0, 1]} type=GROUP name=With WHILE children=2 + Check Body Item Data ${tc[0, 0, 1, 0]} type=WHILE condition=$i < 2 children=2 + Check Body Item Data ${tc[0, 0, 1, 0, 0]} type=ITERATION + Check Body Item Data ${tc[0, 0, 1, 0, 0, 0]} type=GROUP name=Group1 Inside WHILE (0) children=1 + Check Body Item Data ${tc[0, 0, 1, 0, 0, 0, 0]} type=KEYWORD name=Log args=\${i} + Check Body Item Data ${tc[0, 0, 1, 0, 0, 1]} type=GROUP name=Group2 Inside WHILE children=1 + Check Body Item Data ${tc[0, 0, 1, 0, 0, 1, 0]} type=VAR name=\${i} value=\${i + 1} + Check Body Item Data ${tc[0, 0, 1, 0, 1]} type=ITERATION + Check Body Item Data ${tc[0, 0, 1, 0, 1, 0]} type=GROUP name=Group1 Inside WHILE (1) children=1 + Check Body Item Data ${tc[0, 0, 1, 0, 1, 0, 0]} type=KEYWORD name=Log args=\${i} + Check Body Item Data ${tc[0, 0, 1, 0, 1, 1]} type=GROUP name=Group2 Inside WHILE children=1 + Check Body Item Data ${tc[0, 0, 1, 0, 1, 1, 0]} type=VAR name=\${i} value=\${i + 1} + Check Body Item Data ${tc[0, 0, 1, 1]} type=IF/ELSE ROOT + Check Body Item Data ${tc[0, 0, 1, 1, 0]} type=IF status=NOT RUN condition=$i != 2 children=1 + Check Body Item Data ${tc[0, 0, 1, 1, 0, 0]} type=KEYWORD status=NOT RUN name=Fail args=Shall be logged but NOT RUN + +In non-executed branch + ${tc} Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=VAR name=\${var} value=value + Check Body Item Data ${tc[1]} type=IF/ELSE ROOT + Check Body Item Data ${tc[1, 0]} type=IF condition=True children=1 + Check Body Item Data ${tc[1, 0, 0]} type=GROUP name=GROUP in IF children=2 + Check Body Item Data ${tc[1, 0, 0, 0]} type=KEYWORD name=Should Be Equal + Check Body Item Data ${tc[1, 0, 0, 1]} type=IF/ELSE ROOT + Check Body Item Data ${tc[1, 0, 0, 1, 0]} type=IF status=PASS children=1 condition=True + Check Body Item Data ${tc[1, 0, 0, 1, 0, 0]} type=KEYWORD status=PASS name=Log args=IF in GROUP + Check Body Item Data ${tc[1, 0, 0, 1, 1]} type=ELSE status=NOT RUN + Check Body Item Data ${tc[1, 0, 0, 1, 1, 0]} type=GROUP status=NOT RUN children=1 name=GROUP in ELSE + Check Body Item Data ${tc[1, 0, 0, 1, 1, 0, 0]} type=KEYWORD status=NOT RUN name=Fail args=Shall be logged but NOT RUN + Check Body Item Data ${tc[1, 1]} type=ELSE IF status=NOT RUN + Check Body Item Data ${tc[1, 1, 0]} type=GROUP status=NOT RUN children=1 name=\${non_existing_variable_is_fine_here} + Check Body Item Data ${tc[1, 2]} type=ELSE status=NOT RUN + Check Body Item Data ${tc[1, 2, 0]} type=GROUP status=NOT RUN children=0 name=Even empty GROUP is allowed diff --git a/atest/robot/running/group/templates.robot b/atest/robot/running/group/templates.robot new file mode 100644 index 00000000000..b42966b2524 --- /dev/null +++ b/atest/robot/running/group/templates.robot @@ -0,0 +1,69 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/group/templates.robot +Resource atest_resource.robot + +*** Test Cases *** +Pass + ${tc} = Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP status=PASS children=1 name=1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 1.1 + Check Body Item Data ${tc[1]} type=GROUP status=PASS children=2 name=2 + Check Body Item Data ${tc[1, 0]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 2.1 + Check Body Item Data ${tc[1, 1]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 2.2 + +Pass and fail + ${tc} = Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP status=PASS children=1 name=1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 1.1 + Check Body Item Data ${tc[1]} type=GROUP status=FAIL children=2 name=2 message=2.1 + Check Body Item Data ${tc[1, 0]} type=KEYWORD status=FAIL children=1 name=Run Keyword args=Fail, 2.1 message=2.1 + Check Body Item Data ${tc[1, 1]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 2.2 + Check Body Item Data ${tc[2]} type=GROUP status=PASS children=1 name=3 + Check Body Item Data ${tc[2, 0]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 3.1 + +Fail multiple times + ${tc} = Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP status=FAIL children=1 name=1 message=1.1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD status=FAIL children=1 name=Run Keyword args=Fail, 1.1 message=1.1 + Check Body Item Data ${tc[1]} type=GROUP status=FAIL children=3 name=2 message=Several failures occurred:\n\n1) 2.1\n\n2) 2.3 + Check Body Item Data ${tc[1, 0]} type=KEYWORD status=FAIL children=1 name=Run Keyword args=Fail, 2.1 message=2.1 + Check Body Item Data ${tc[1, 1]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 2.2 + Check Body Item Data ${tc[1, 2]} type=KEYWORD status=FAIL children=1 name=Run Keyword args=Fail, 2.3 message=2.3 + Check Body Item Data ${tc[2]} type=GROUP status=PASS children=1 name=3 + Check Body Item Data ${tc[2, 0]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 3.1 + Check Body Item Data ${tc[3]} type=GROUP status=FAIL children=1 name=4 message=4.1 + Check Body Item Data ${tc[3, 0]} type=KEYWORD status=FAIL children=1 name=Run Keyword args=Fail, 4.1 message=4.1 + +Pass and skip + ${tc} = Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP status=SKIP children=1 name=1 message=1.1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 1.1 message=1.1 + Check Body Item Data ${tc[1]} type=GROUP status=PASS children=1 name=2 + Check Body Item Data ${tc[1, 0]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 2.1 + Check Body Item Data ${tc[2]} type=GROUP status=PASS children=2 name=3 + Check Body Item Data ${tc[2, 0]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 3.1 message=3.1 + Check Body Item Data ${tc[2, 1]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 3.2 + +Pass, fail and skip + ${tc} = Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP status=FAIL children=3 name=1 message=1.1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD status=FAIL children=1 name=Run Keyword args=Fail, 1.1 message=1.1 + Check Body Item Data ${tc[0, 1]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 1.2 message=1.2 + Check Body Item Data ${tc[0, 2]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 1.3 + Check Body Item Data ${tc[1]} type=GROUP status=SKIP children=1 name=2 message=2.1 + Check Body Item Data ${tc[1, 0]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 2.1 message=2.1 + Check Body Item Data ${tc[2]} type=GROUP status=PASS children=1 name=3 + Check Body Item Data ${tc[2, 0]} type=KEYWORD status=PASS children=1 name=Run Keyword args=Log, 3.1 + +Skip all + ${tc} = Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP status=SKIP children=2 name=1 message=All iterations skipped. + Check Body Item Data ${tc[0, 0]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 1.1 message=1.1 + Check Body Item Data ${tc[0, 1]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 1.2 message=1.2 + Check Body Item Data ${tc[1]} type=GROUP status=SKIP children=1 name=2 message=2.1 + Check Body Item Data ${tc[1, 0]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 2.1 message=2.1 + +Just one that is skipped + ${tc} = Check Test Case ${TESTNAME} + Check Body Item Data ${tc[0]} type=GROUP status=SKIP children=1 name=1 message=1.1 + Check Body Item Data ${tc[0, 0]} type=KEYWORD status=SKIP children=1 name=Run Keyword args=Skip, 1.1 message=1.1 diff --git a/atest/robot/running/html_error_message.robot b/atest/robot/running/html_error_message.robot index 007d5a3cd04..9ff087a0d82 100644 --- a/atest/robot/running/html_error_message.robot +++ b/atest/robot/running/html_error_message.robot @@ -9,15 +9,15 @@ ${FAILURE} Robot Framework *** Test Cases *** Set Test Message ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\n${MESSAGE} html=True + Check Log Message ${tc[0, 0]} Set test message to:\n${MESSAGE} html=True HTML failure ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} ${FAILURE} FAIL html=True + Check Log Message ${tc[0, 0]} ${FAILURE} FAIL html=True HTML failure with non-generic exception ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} ValueError: Invalid value FAIL html=True + Check Log Message ${tc[0, 0]} ValueError: Invalid value FAIL html=True HTML failure in setup Check Test Case ${TESTNAME} @@ -30,8 +30,8 @@ Normal failure in body and HTML failure in teardown HTML failure in body and normal failure teardown ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Should be HTML FAIL html=True - Check Log Message ${tc.teardown.msgs[0]} Should NOT be HTML FAIL html=False + Check Log Message ${tc[0, 0]} Should be HTML FAIL html=True + Check Log Message ${tc.teardown[0]} Should NOT be HTML FAIL html=False HTML failure in body and in teardown Check Test Case ${TESTNAME} diff --git a/atest/robot/running/if/complex_if.robot b/atest/robot/running/if/complex_if.robot index 49afc29aaca..1e4662b1f12 100644 --- a/atest/robot/running/if/complex_if.robot +++ b/atest/robot/running/if/complex_if.robot @@ -14,7 +14,7 @@ If inside for loop Setting after if ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.msgs[0]} Teardown was found and executed. + Check Log Message ${tc.teardown[0]} Teardown was found and executed. For loop inside if Check Test Case ${TESTNAME} @@ -24,23 +24,23 @@ For loop inside for loop Direct Boolean condition ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].status} PASS - Should Be Equal ${tc.body[0].body[0].status} PASS - Should Be Equal ${tc.body[0].body[0].body[0].status} PASS + Should Be Equal ${tc[0].status} PASS + Should Be Equal ${tc[0, 0].status} PASS + Should Be Equal ${tc[0, 0, 0].status} PASS Direct Boolean condition false ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].status} PASS - Should Be Equal ${tc.body[0].body[0].status} NOT RUN - Should Be Equal ${tc.body[0].body[0].body[0].status} NOT RUN + Should Be Equal ${tc[0].status} PASS + Should Be Equal ${tc[0, 0].status} NOT RUN + Should Be Equal ${tc[0, 0, 0].status} NOT RUN Nesting insanity Check Test Case ${TESTNAME} Recursive If ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].kws[0].status} PASS - Should Be Equal ${tc.kws[0].kws[0].kws[0].kws[0].status} PASS + Should Be Equal ${tc[0, 0].status} PASS + Should Be Equal ${tc[0, 0, 0, 0].status} PASS If creating variable Check Test Case ${TESTNAME} diff --git a/atest/robot/running/if/if_else.robot b/atest/robot/running/if/if_else.robot index e4b489659bf..6331aeb4dfc 100644 --- a/atest/robot/running/if/if_else.robot +++ b/atest/robot/running/if/if_else.robot @@ -38,3 +38,10 @@ If failing in keyword If failing in else keyword Check Test Case ${TESTNAME} + +Expression evaluation time is included in elapsed time + ${tc} = Check Test Case ${TESTNAME} + Elapsed Time Should Be Valid ${tc[0].elapsed_time} minimum=0.2 + Elapsed Time Should Be Valid ${tc[0, 0].elapsed_time} minimum=0.1 + Elapsed Time Should Be Valid ${tc[0, 1].elapsed_time} minimum=0.1 + Elapsed Time Should Be Valid ${tc[0, 2].elapsed_time} maximum=1.0 diff --git a/atest/robot/running/if/inline_if_else.robot b/atest/robot/running/if/inline_if_else.robot index 216fb0124a6..d3a5a346db5 100644 --- a/atest/robot/running/if/inline_if_else.robot +++ b/atest/robot/running/if/inline_if_else.robot @@ -22,10 +22,10 @@ Not executed after failure Not executed after failure with assignment [Template] NONE ${tc} = Check Test Case ${TEST NAME} - Check IF/ELSE Status NOT RUN NOT RUN root=${tc.body[1]} run=False - Check IF/ELSE Status NOT RUN NOT RUN root=${tc.body[2]} run=False - Check Keyword Data ${tc.body[1].body[0].body[0]} Not run assign=\${x} status=NOT RUN - Check Keyword Data ${tc.body[2].body[0].body[0]} Not run assign=\${x}, \@{y} status=NOT RUN + Check IF/ELSE Status NOT RUN NOT RUN root=${tc[1]} run=False + Check IF/ELSE Status NOT RUN NOT RUN root=${tc[2]} run=False + Check Keyword Data ${tc[1, 0, 0]} Not run assign=\${x} status=NOT RUN + Check Keyword Data ${tc[2, 0, 0]} Not run assign=\${x}, \@{y} status=NOT RUN ELSE IF not executed NOT RUN NOT RUN PASS index=0 @@ -48,6 +48,11 @@ Assign NOT RUN PASS NOT RUN index=1 NOT RUN NOT RUN PASS index=2 +Assign with item + PASS NOT RUN NOT RUN index=0 + NOT RUN PASS NOT RUN index=1 + NOT RUN NOT RUN PASS index=2 + Multi assign PASS NOT RUN index=0 FAIL NOT RUN index=4 @@ -59,6 +64,9 @@ List assign Dict assign NOT RUN PASS +Assign based on another variable + PASS NOT RUN index=1 + Assign without ELSE PASS NOT RUN index=0 NOT RUN PASS NOT RUN index=2 @@ -71,20 +79,20 @@ Assign when no branch is run Inside FOR [Template] NONE ${tc} = Check Test Case ${TEST NAME} - Check IF/ELSE Status NOT RUN PASS root=${tc.body[0].body[0].body[0]} - Check IF/ELSE Status NOT RUN PASS root=${tc.body[0].body[1].body[0]} - Check IF/ELSE Status FAIL NOT RUN root=${tc.body[0].body[2].body[0]} + Check IF/ELSE Status NOT RUN PASS root=${tc[0, 0, 0]} + Check IF/ELSE Status NOT RUN PASS root=${tc[0, 1, 0]} + Check IF/ELSE Status FAIL NOT RUN root=${tc[0, 2, 0]} Inside normal IF [Template] NONE ${tc} = Check Test Case ${TEST NAME} - Check IF/ELSE Status NOT RUN PASS root=${tc.body[0].body[0].body[1]} - Check IF/ELSE Status NOT RUN NOT RUN root=${tc.body[0].body[1].body[0]} run=False + Check IF/ELSE Status NOT RUN PASS root=${tc[0, 0, 1]} + Check IF/ELSE Status NOT RUN NOT RUN root=${tc[0, 1, 0]} run=False In keyword [Template] NONE ${tc} = Check Test Case ${TEST NAME} - Check IF/ELSE Status PASS NOT RUN root=${tc.body[0].body[0]} - Check IF/ELSE Status NOT RUN PASS NOT RUN root=${tc.body[0].body[1]} + Check IF/ELSE Status PASS NOT RUN root=${tc[0, 0]} + Check IF/ELSE Status NOT RUN PASS NOT RUN root=${tc[0, 1]} Check IF/ELSE Status NOT RUN NOT RUN NOT RUN FAIL - ... NOT RUN NOT RUN NOT RUN root=${tc.body[0].body[2]} + ... NOT RUN NOT RUN NOT RUN root=${tc[0, 2]} diff --git a/atest/robot/running/if/invalid_if.robot b/atest/robot/running/if/invalid_if.robot index a720be8347d..714a7b4eb80 100644 --- a/atest/robot/running/if/invalid_if.robot +++ b/atest/robot/running/if/invalid_if.robot @@ -16,12 +16,24 @@ IF with invalid condition IF with invalid condition with ELSE FAIL NOT RUN -IF condition with non-existing variable +IF condition with non-existing ${variable} + FAIL NOT RUN + +IF condition with non-existing $variable FAIL NOT RUN ELSE IF with invalid condition NOT RUN NOT RUN FAIL NOT RUN NOT RUN +Recommend $var syntax if invalid condition contains ${var} + FAIL index=1 + +$var recommendation with multiple variables + FAIL index=1 + +Remove quotes around variable in $var recommendation + FAIL index=2 + IF without END FAIL @@ -38,7 +50,7 @@ ELSE IF without condition ELSE IF with multiple conditions [Template] NONE ${tc} = Branch statuses should be FAIL NOT RUN NOT RUN - Should Be Equal ${tc.body[0].body[1].condition} \${False}, ooops, \${True} + Should Be Equal ${tc[0, 1].condition} \${False}, ooops, \${True} ELSE with condition FAIL NOT RUN @@ -58,19 +70,59 @@ ELSE after ELSE ELSE IF after ELSE FAIL NOT RUN NOT RUN +Dangling ELSE + [Template] Check Test Case + ${TEST NAME} + +Dangling ELSE inside FOR + [Template] Check Test Case + ${TEST NAME} + +Dangling ELSE inside WHILE + [Template] Check Test Case + ${TEST NAME} + +Dangling ELSE IF + [Template] Check Test Case + ${TEST NAME} + +Dangling ELSE IF inside FOR + [Template] Check Test Case + ${TEST NAME} + +Dangling ELSE IF inside WHILE + [Template] Check Test Case + ${TEST NAME} + +Dangling ELSE IF inside TRY + [Template] Check Test Case + ${TEST NAME} + Invalid IF inside FOR FAIL Multiple errors FAIL NOT RUN NOT RUN NOT RUN NOT RUN +Invalid data causes syntax error + [Template] Check Test Case + ${TEST NAME} + +Invalid condition causes normal error + [Template] Check Test Case + ${TEST NAME} + +Non-existing variable in condition causes normal error + [Template] Check Test Case + ${TEST NAME} + *** Keywords *** Branch statuses should be - [Arguments] @{statuses} + [Arguments] @{statuses} ${index}=0 ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].status} FAIL - FOR ${branch} ${status} IN ZIP ${tc.body[0].body} ${statuses} + ${if} = Set Variable ${tc.body}[${index}] + Should Be Equal ${if.status} FAIL + FOR ${branch} ${status} IN ZIP ${if.body} ${statuses} mode=STRICT Should Be Equal ${branch.status} ${status} END - Should Be Equal ${{len($tc.body[0].body)}} ${{len($statuses)}} RETURN ${tc} diff --git a/atest/robot/running/if/invalid_inline_if.robot b/atest/robot/running/if/invalid_inline_if.robot index 4609f4f9d88..5a7ba2c0ac0 100644 --- a/atest/robot/running/if/invalid_inline_if.robot +++ b/atest/robot/running/if/invalid_inline_if.robot @@ -65,10 +65,11 @@ Unnecessary END Invalid END after inline header [Template] NONE ${tc} = Check Test Case ${TEST NAME} - Check IF/ELSE Status PASS root=${tc.body[0]} - Check Log Message ${tc.body[0].body[0].body[0].body[0]} Executed inside inline IF - Check Log Message ${tc.body[1].body[0]} Executed outside IF - Check Keyword Data ${tc.body[2]} Reserved.End status=FAIL + Check IF/ELSE Status PASS root=${tc[0]} + Check Log Message ${tc[0, 0, 0, 0]} Executed inside inline IF + Check Log Message ${tc[1, 0]} Executed outside IF + Should Be Equal ${tc[2].type} ERROR + Should Be Equal ${tc[2].status} FAIL Assign in IF branch FAIL @@ -103,7 +104,12 @@ Assign when ELSE IF branch is empty Assign when ELSE branch is empty FAIL NOT RUN -Assign with RETURN +Control structures are allowed [Template] NONE ${tc} = Check Test Case ${TESTNAME} - Check IF/ELSE Status FAIL NOT RUN root=${tc.body[0].body[0]} + Check IF/ELSE Status NOT RUN PASS root=${tc[0, 0]} + +Control structures are not allowed with assignment + [Template] NONE + ${tc} = Check Test Case ${TESTNAME} + Check IF/ELSE Status FAIL NOT RUN root=${tc[0, 0]} diff --git a/atest/robot/running/invalid_break_and_continue.robot b/atest/robot/running/invalid_break_and_continue.robot index 6aeafe8493d..6730a116b6a 100644 --- a/atest/robot/running/invalid_break_and_continue.robot +++ b/atest/robot/running/invalid_break_and_continue.robot @@ -26,11 +26,11 @@ CONTINUE in TRY-ELSE CONTINUE with argument in FOR ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.body[0].body[0].body[1].body[0]} CONTINUE does not accept arguments, got 'should not work'. FAIL + Check Log Message ${tc[0, 0, 1, 0]} CONTINUE does not accept arguments, got 'should not work'. FAIL CONTINUE with argument in WHILE ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.body[0].body[0].body[1].body[0]} CONTINUE does not accept arguments, got 'should', 'not' and 'work'. FAIL + Check Log Message ${tc[0, 0, 1, 0]} CONTINUE does not accept arguments, got 'should', 'not' and 'work'. FAIL BREAK in test case Check Test Case ${TESTNAME} @@ -55,8 +55,8 @@ BREAK in TRY-ELSE BREAK with argument in FOR ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.body[0].body[0].body[1].body[0]} BREAK does not accept arguments, got 'should not work'. FAIL + Check Log Message ${tc[0, 0, 1, 0]} BREAK does not accept arguments, got 'should not work'. FAIL BREAK with argument in WHILE ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.body[0].body[0].body[1].body[0]} BREAK does not accept arguments, got 'should', 'not' and 'work'. FAIL + Check Log Message ${tc[0, 0, 1, 0]} BREAK does not accept arguments, got 'should', 'not' and 'work'. FAIL diff --git a/atest/robot/running/long_error_messages.robot b/atest/robot/running/long_error_messages.robot index 3f1187be2f2..abef7c57b16 100644 --- a/atest/robot/running/long_error_messages.robot +++ b/atest/robot/running/long_error_messages.robot @@ -42,21 +42,21 @@ Has Been Cut Should Contain ${test.message} ${EXPLANATION} Should Match Non Empty Regexp ${test.message} ${eol_dots} Should Match Non Empty Regexp ${test.message} ${bol_dots} - Error Message In Log Should Not Have Been Cut ${test.kws} - [Return] ${test} + Error Message In Log Should Not Have Been Cut ${test} + RETURN ${test} Error Message In Log Should Not Have Been Cut - [Arguments] ${kws} - @{keywords} = Set Variable ${kws} - FOR ${kw} IN @{keywords} - Run Keyword If ${kw.msgs} - ... Should Not Contain ${kw.msgs[-1].message} ${EXPLANATION} - Error Message In Log Should Not Have Been Cut ${kw.kws} + [Arguments] ${item} + FOR ${child} IN @{item.non_messages} + FOR ${msg} IN @{child.messages} + Should Not Contain ${msg.message} ${EXPLANATION} + END + Error Message In Log Should Not Have Been Cut ${child} END Should Match Non Empty Regexp [Arguments] ${message} ${pattern} - Run Keyword If $pattern + IF $pattern ... Should Match Regexp ${message} ${pattern} Has Not Been Cut diff --git a/atest/robot/running/non_ascii_bytes.robot b/atest/robot/running/non_ascii_bytes.robot index 18b726cd5c2..b84792d1a6e 100644 --- a/atest/robot/running/non_ascii_bytes.robot +++ b/atest/robot/running/non_ascii_bytes.robot @@ -8,26 +8,26 @@ Variables ${DATADIR}/running/expbytevalues.py *** Test Cases *** In Message ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} ${exp_log_msg} + Check Log Message ${tc[0, 0]} ${exp_log_msg} In Multiline Message ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} ${exp_log_multiline_msg} + Check Log Message ${tc[0, 0]} ${exp_log_multiline_msg} In Return Value [Documentation] Return value is not altered by the framework and thus it ... contains the exact same bytes that the keyword returned. ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} \${retval} = ${exp_return_msg} + Check Log Message ${tc[0, 0]} \${retval} = ${exp_return_msg} In Exception ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} ${exp_error_msg} FAIL + Check Log Message ${tc[0, 0]} ${exp_error_msg} FAIL In Exception In Setup ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.setup.msgs[0]} ${exp_error_msg} FAIL + Check Log Message ${tc.setup[0]} ${exp_error_msg} FAIL In Exception In Teardown ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.msgs[0]} ${exp_error_msg} FAIL + Check Log Message ${tc.teardown[0]} ${exp_error_msg} FAIL diff --git a/atest/robot/running/pass_execution.robot b/atest/robot/running/pass_execution.robot index 2fa03944982..4bea02d7167 100644 --- a/atest/robot/running/pass_execution.robot +++ b/atest/robot/running/pass_execution.robot @@ -1,9 +1,9 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} running/pass_execution.robot -Resource atest_resource.robot +Suite Setup Run Tests ${EMPTY} running/pass_execution.robot +Resource atest_resource.robot *** Variables *** -${PREFIX}= Execution passed with message:\n +${PREFIX}= Execution passed with message:\n *** Test Cases *** Message is required @@ -11,11 +11,11 @@ Message is required With message ${tc}= Check Test Tags ${TESTNAME} force1 force2 - Check Log Message ${tc.kws[0].msgs[0]} ${PREFIX}My message + Check Log Message ${tc[0, 0]} ${PREFIX}My message With HTML message ${tc}= Check Test Tags ${TESTNAME} force1 force2 - Check Log Message ${tc.kws[0].msgs[0]} ${PREFIX}Message HTML + Check Log Message ${tc[0, 0]} ${PREFIX}Message HTML Empty message is not allowed Check Test Case ${TESTNAME} @@ -40,17 +40,17 @@ Used in template keyword Used in for loop ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} ${PREFIX}Message with 'foo' + Check Log Message ${tc[0, 0, 0, 0]} ${PREFIX}Message with 'foo' Used in setup ${tc} = Check Test Case ${TESTNAME} - Keyword Should Have Been Executed ${tc.kws[0]} + Keyword Should Have Been Executed ${tc[0]} Keyword Should Have Been Executed ${tc.teardown} Used in teardown ${tc}= Check Test Case ${TESTNAME} Should Be Equal ${tc.teardown.status} PASS - Check Log Message ${tc.teardown.kws[0].msgs[0]} ${PREFIX}This message is used. + Check Log Message ${tc.teardown[0, 0]} ${PREFIX}This message is used. Before failing teardown Check Test Case ${TESTNAME} @@ -60,14 +60,14 @@ After continuable failure After continuable failure in user keyword ${tc}= Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].status} FAIL + Should Be Equal ${tc[0].status} FAIL After continuable failure in FOR loop ${tc}= Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].status} FAIL - Should Be Equal ${tc.kws[0].kws[0].status} FAIL - Should Be Equal ${tc.kws[0].kws[0].kws[0].status} FAIL - Should Be Equal ${tc.kws[0].kws[0].kws[1].status} PASS + Should Be Equal ${tc[0].status} FAIL + Should Be Equal ${tc[0, 0].status} FAIL + Should Be Equal ${tc[0, 0, 0].status} FAIL + Should Be Equal ${tc[0, 0, 1].status} PASS After continuable failure and before failing teardown Check Test Case ${TESTNAME} @@ -86,57 +86,57 @@ After continuable failure in keyword teardown Remove one tag ${tc}= Check Test Tags ${TESTNAME} force2 - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'force1'. - Check Log Message ${tc.kws[0].msgs[1]} ${PREFIX}Message + Check Log Message ${tc[0, 0]} Removed tag 'force1'. + Check Log Message ${tc[0, 1]} ${PREFIX}Message Remove multiple tags ${tc}= Check Test Tags ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Removed tags 'force1' and 'force2'. - Check Log Message ${tc.kws[0].msgs[1]} ${PREFIX}Message + Check Log Message ${tc[0, 0]} Removed tags 'force1' and 'force2'. + Check Log Message ${tc[0, 1]} ${PREFIX}Message Remove tags with pattern ${tc}= Check Test Tags ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'force?'. - Check Log Message ${tc.kws[0].msgs[1]} ${PREFIX}Message + Check Log Message ${tc[0, 0]} Removed tag 'force?'. + Check Log Message ${tc[0, 1]} ${PREFIX}Message Set one tag ${tc}= Check Test Tags ${TESTNAME} force1 force2 tag - Check Log Message ${tc.kws[0].msgs[0]} Set tag 'tag'. - Check Log Message ${tc.kws[0].msgs[1]} ${PREFIX}Message + Check Log Message ${tc[0, 0]} Set tag 'tag'. + Check Log Message ${tc[0, 1]} ${PREFIX}Message Set multiple tags ${tc}= Check Test Tags ${TESTNAME} force1 force2 tag1 tag2 - Check Log Message ${tc.kws[0].msgs[0]} Set tags 'tag1' and 'tag2'. - Check Log Message ${tc.kws[0].msgs[1]} ${PREFIX}Message + Check Log Message ${tc[0, 0]} Set tags 'tag1' and 'tag2'. + Check Log Message ${tc[0, 1]} ${PREFIX}Message Set and remove tags ${tc}= Check Test Tags ${TESTNAME} tag1 tag2 - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'force?'. - Check Log Message ${tc.kws[0].msgs[1]} Set tags 'tag1' and 'tag2'. - Check Log Message ${tc.kws[0].msgs[2]} ${PREFIX}Message + Check Log Message ${tc[0, 0]} Removed tag 'force?'. + Check Log Message ${tc[0, 1]} Set tags 'tag1' and 'tag2'. + Check Log Message ${tc[0, 2]} ${PREFIX}Message Set tags are not removed ${tc}= Check Test Tags ${TESTNAME} force1 force2 tag1 tag2 - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'tag?'. - Check Log Message ${tc.kws[0].msgs[1]} Set tags 'tag1' and 'tag2'. - Check Log Message ${tc.kws[0].msgs[2]} ${PREFIX}Message + Check Log Message ${tc[0, 0]} Removed tag 'tag?'. + Check Log Message ${tc[0, 1]} Set tags 'tag1' and 'tag2'. + Check Log Message ${tc[0, 2]} ${PREFIX}Message Set tags in teardown ${tc}= Check Test Tags ${TESTNAME} tag1 tag2 - Check Log Message ${tc.teardown.msgs[0]} Removed tag 'force?'. - Check Log Message ${tc.teardown.msgs[1]} Set tags 'tag1' and 'tag2'. - Check Log Message ${tc.teardown.msgs[2]} ${PREFIX}Message + Check Log Message ${tc.teardown[0]} Removed tag 'force?'. + Check Log Message ${tc.teardown[1]} Set tags 'tag1' and 'tag2'. + Check Log Message ${tc.teardown[2]} ${PREFIX}Message Pass Execution If when condition is true Check Test Case ${TESTNAME} Pass Execution If when condition is false ${tc} = Check Test Case ${TESTNAME} - Keyword Should Have Been Executed ${tc.kws[1]} + Keyword Should Have Been Executed ${tc[1]} Pass Execution If resolves variables only condition is true ${tc} = Check Test Case ${TESTNAME} - Keyword Should Have Been Executed ${tc.kws[1]} + Keyword Should Have Been Executed ${tc[1]} Pass Execution If with multiple variables Check Test Tags ${TESTNAME} force1 force2 my tags diff --git a/atest/robot/running/prevent_recursion.robot b/atest/robot/running/prevent_recursion.robot deleted file mode 100644 index 8641c4e476d..00000000000 --- a/atest/robot/running/prevent_recursion.robot +++ /dev/null @@ -1,21 +0,0 @@ -*** Settings *** -Suite Setup Run Tests ${EMPTY} running/prevent_recursion.robot -Resource atest_resource.robot - -*** Test Cases *** -Infinite recursion - Check Test Case ${TESTNAME} - -Infinite cyclic recursion - Check Test Case ${TESTNAME} - -Infinite recursion with Run Keyword - Check Test Case ${TESTNAME} - -Infinitely recursive for loop - Check Test Case ${TESTNAME} - -Recursion below the recursion limit is ok - [Documentation] Also verifies that recursion limit blown earlier doesn't affect subsequent tests - Check Test Case ${TESTNAME} - diff --git a/atest/robot/running/return.robot b/atest/robot/running/return.robot index 6937411cab8..a94de10b833 100644 --- a/atest/robot/running/return.robot +++ b/atest/robot/running/return.robot @@ -5,42 +5,51 @@ Resource atest_resource.robot *** Test Cases *** Simple ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].body[1].type} RETURN - Should Be Equal ${tc.body[0].body[1].status} PASS - Should Be Equal ${tc.body[0].body[2].status} NOT RUN + Should Be Equal ${tc[0, 1].type} RETURN + Should Be Equal ${tc[0, 1].values} ${{()}} + Should Be Equal ${tc[0, 1].status} PASS + Should Be Equal ${tc[0, 1].message} ${EMPTY} + Should Be Equal ${tc[0, 2].status} NOT RUN + Should Be Equal ${tc[0].message} ${EMPTY} Return value - Check Test Case ${TESTNAME} + ${tc} = Check Test Case ${TESTNAME} + Should Be Equal ${tc[0, 0].type} RETURN + Should Be Equal ${tc[0, 0].values} ${{('value',)}} Return value as variable - Check Test Case ${TESTNAME} + ${tc} = Check Test Case ${TESTNAME} + Should Be Equal ${tc[0, 0].type} RETURN + Should Be Equal ${tc[0, 0].values} ${{('\${42}',)}} Return multiple values - Check Test Case ${TESTNAME} + ${tc} = Check Test Case ${TESTNAME} + Should Be Equal ${tc[0, 0].type} RETURN + Should Be Equal ${tc[0, 0].values} ${{('first', '\${2}', 'third')}} In nested keyword Check Test Case ${TESTNAME} In IF ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].body[0].body[0].body[0].type} RETURN - Should Be Equal ${tc.body[0].body[0].body[0].body[0].status} PASS - Should Be Equal ${tc.body[0].body[0].body[0].body[1].status} NOT RUN - Should Be Equal ${tc.body[0].body[1].status} NOT RUN - Should Be Equal ${tc.body[2].body[0].body[1].body[0].type} RETURN - Should Be Equal ${tc.body[2].body[0].body[1].body[0].status} PASS - Should Be Equal ${tc.body[2].body[0].body[1].body[1].status} NOT RUN - Should Be Equal ${tc.body[2].body[1].status} NOT RUN + Should Be Equal ${tc[0, 0, 0, 0].type} RETURN + Should Be Equal ${tc[0, 0, 0, 0].status} PASS + Should Be Equal ${tc[0, 0, 0, 1].status} NOT RUN + Should Be Equal ${tc[0, 1].status} NOT RUN + Should Be Equal ${tc[2, 0, 1, 0].type} RETURN + Should Be Equal ${tc[2, 0, 1, 0].status} PASS + Should Be Equal ${tc[2, 0, 1, 1].status} NOT RUN + Should Be Equal ${tc[2, 1].status} NOT RUN In inline IF Check Test Case ${TESTNAME} In FOR ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].body[0].body[0].body[0].type} RETURN - Should Be Equal ${tc.body[0].body[0].body[0].body[0].status} PASS - Should Be Equal ${tc.body[0].body[0].body[0].body[1].status} NOT RUN - Should Be Equal ${tc.body[0].body[1].status} NOT RUN + Should Be Equal ${tc[0, 0, 0, 0].type} RETURN + Should Be Equal ${tc[0, 0, 0, 0].status} PASS + Should Be Equal ${tc[0, 0, 0, 1].status} NOT RUN + Should Be Equal ${tc[0, 1].status} NOT RUN In nested FOR/IF structure Check Test Case ${TESTNAME} diff --git a/atest/robot/running/return_from_keyword.robot b/atest/robot/running/return_from_keyword.robot index 4c9c2fa72b6..34b905cfa3c 100644 --- a/atest/robot/running/return_from_keyword.robot +++ b/atest/robot/running/return_from_keyword.robot @@ -56,5 +56,5 @@ Return From Keyword If does not evaluate bogus arguments if condition is untrue Logs Info ${tc} = Check Test Case Without Return Value - Check Log Message ${tc.kws[0].kws[0].msgs[0]} + Check Log Message ${tc[0, 0, 0]} ... Returning from the enclosing user keyword. diff --git a/atest/robot/running/setup_and_teardown_using_embedded_arguments.robot b/atest/robot/running/setup_and_teardown_using_embedded_arguments.robot new file mode 100644 index 00000000000..49d2660f2d4 --- /dev/null +++ b/atest/robot/running/setup_and_teardown_using_embedded_arguments.robot @@ -0,0 +1,14 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/setup_and_teardown_using_embedded_arguments.robot +Resource atest_resource.robot + +*** Test Cases *** +Suite setup and teardown + Should Be Equal ${SUITE.setup.status} PASS + Should Be Equal ${SUITE.teardown.status} PASS + +Test setup and teardown + Check Test Case ${TESTNAME} + +Keyword setup and teardown + Check Test Case ${TESTNAME} diff --git a/atest/robot/running/skip.robot b/atest/robot/running/skip.robot index e6f8726acf1..1af592e235f 100644 --- a/atest/robot/running/skip.robot +++ b/atest/robot/running/skip.robot @@ -44,7 +44,7 @@ Skip in Teardown After Failure In Body Teardown is executed after skip ${tc} = Check Test Case ${TEST NAME} - Check log message ${tc.teardown.msgs[0]} Teardown is executed! + Check log message ${tc.teardown[0]} Teardown is executed! Fail in Teardown After Skip In Body Check Test Case ${TEST NAME} @@ -91,6 +91,10 @@ Skip In Suite Teardown After Fail In Setup Skip In Directory Suite Teardown Check Test Case ${TEST NAME} +Tests have correct status if suite has nothing to run and directory suite setup uses skip + Check Test Case `robot:skip` with skip in directory suite setup + Check Test Case `--skip` with skip in directory suite setup + Skip with Run Keyword and Ignore Error Check Test Case ${TEST NAME} @@ -106,24 +110,58 @@ Skip with Wait Until Keyword Succeeds Skipped with --skip Check Test Case ${TEST NAME} -Skipped when test is tagged with robot:skip +Skipped with --skip when tag uses variable + Check Test Case ${TEST NAME} + +Skipped with robot:skip + Check Test Case ${TEST NAME} + +Skipped with robot:skip when tag uses variable Check Test Case ${TEST NAME} Skipped with --SkipOnFailure Check Test Case ${TEST NAME} -Skipped with --SkipOnFailure when Failure in Test Setup +Skipped with --SkipOnFailure when tag uses variable Check Test Case ${TEST NAME} -Skipped with --SkipOnFailure when Failure in Test Teardown +Skipped with --SkipOnFailure when failure in setup Check Test Case ${TEST NAME} -Skipped with --SkipOnFailure when Set Tags Used in Teardown - Check Test Case Skipped with --SkipOnFailure when Set Tags Used in Teardown +Skipped with --SkipOnFailure when failure in teardown + Check Test Case ${TEST NAME} -Skipped although test fails since test is tagged with robot:skip-on-failure +Skipped with --SkipOnFailure when Set Tags used in teardown Check Test Case ${TEST NAME} -Using Skip Does Not Affect Passing And Failing Tests - Check Test Case Passing Test - Check Test Case Failing Test +Skipped with robot:skip-on-failure + Check Test Case ${TEST NAME} + +Skipped with robot:skip-on-failure when tag uses variable + Check Test Case ${TEST NAME} + +Skipping does not affect passing and failing tests + Check Test Case Passing + Check Test Case Failing + +Suite setup and teardown are not run if all tests are unconditionally skipped or excluded + ${suite} = Get Test Suite All Skipped + Should Be True not ($suite.setup or $suite.teardown) + Should Be True not ($suite.suites[0].setup or $suite.suites[0].teardown) + Check Test Case Skip using robot:skip + Check Test Case Skip using --skip + Length Should Be ${suite.suites[0].tests} 2 + +--skip and --skip-on-failure used multiple times + Run Tests --skip skip-this --skip no-match --SkipOnFailure skip-on-failure --skip-on-failure xxx running/skip/skip.robot + Check Test Case Skipped with --skip + ... message=Test skipped using 'no-match' and 'skip-this' tags. + Check Test Case Skipped with --SkipOnFailure + ... message=Failed test skipped using 'skip-on-failure' and 'xxx' tags.\n\nOriginal failure:\nOoops, we fail! + +--skip and --skip-on-failure with patterns + Run Tests --skip skip-t*s --skip no-match --SkipOnFailure xxxORskip-on-failure running/skip/skip.robot + Check Test Case Skipped with --skip + ... message=Test skipped using 'no-match' and 'skip-t*s' tag patterns. + Check Test Case Skipped with --SkipOnFailure + ... message=Failed test skipped using 'xxx OR skip-on-failure' tag pattern.\n\nOriginal failure:\nOoops, we fail! diff --git a/atest/robot/running/skip_in_rpa_mode.robot b/atest/robot/running/skip_in_rpa_mode.robot index e5370328d05..6da7ef27bfd 100644 --- a/atest/robot/running/skip_in_rpa_mode.robot +++ b/atest/robot/running/skip_in_rpa_mode.robot @@ -1,5 +1,5 @@ *** Settings *** -Suite Setup Run Tests --rpa --skip skip-this --SkipOnFailure skip-on-failure --variable test_or_task:Task running/skip/ +Suite Setup Run Tests --rpa --skip skip-this --SkipOnFailure skip-on-failure --variable test_or_task:task running/skip/ Resource atest_resource.robot *** Test Cases *** @@ -8,4 +8,3 @@ Skipped with --skip Skipped with --SkipOnFailure Check Test Case ${TEST NAME} - diff --git a/atest/robot/running/skip_with_template.robot b/atest/robot/running/skip_with_template.robot new file mode 100644 index 00000000000..a642c665146 --- /dev/null +++ b/atest/robot/running/skip_with_template.robot @@ -0,0 +1,71 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/skip_with_template.robot +Resource atest_resource.robot + +*** Test Cases *** +SKIP + PASS -> PASS + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} SKIP Skipped + Status Should Be ${tc[1]} PASS + +FAIL + ANY -> FAIL + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} PASS + Status Should Be ${tc[1]} SKIP Skipped + Status Should Be ${tc[2]} PASS + Status Should Be ${tc[3]} FAIL Failed + Status Should Be ${tc[4]} SKIP Skipped + +Only SKIP -> SKIP + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} SKIP Skipped + Status Should Be ${tc[1]} SKIP Skipped + +IF w/ SKIP + PASS -> PASS + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} PASS + Status Should Be ${tc[1]} SKIP Skipped + Status Should Be ${tc[2]} PASS + +IF w/ FAIL + ANY -> FAIL + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} FAIL Failed + Status Should Be ${tc[1]} SKIP Skipped + Status Should Be ${tc[2]} PASS + +IF w/ only SKIP -> SKIP + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} SKIP All iterations skipped. + Status Should Be ${tc[1]} SKIP Skip 3 + Status Should Be ${tc[2]} SKIP Skip 4 + +FOR w/ SKIP + PASS -> PASS + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} PASS + Status Should Be ${tc[1]} SKIP just once + Status Should Be ${tc[2]} PASS + +FOR w/ FAIL + ANY -> FAIL + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} FAIL Several failures occurred:\n\n1) a\n\n2) b + Status Should Be ${tc[1]} SKIP just once + Status Should Be ${tc[2]} PASS + +FOR w/ only SKIP -> SKIP + ${tc} = Check Test Case ${TEST NAME} + Status Should Be ${tc[0]} SKIP All iterations skipped. + Status Should Be ${tc[1]} SKIP just once + +Messages in test body are ignored + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0]} Hello 'Messages in test body are ignored', says listener! + Check Log Message ${tc[1, 0, 0]} Library listener adds messages to body of this test. + Check Log Message ${tc[2, 0, 0]} This iteration is skipped! SKIP + Check Log Message ${tc[3, 0, 0]} This iteration passes! + Check Log Message ${tc[4]} Bye 'Messages in test body are ignored', says listener! + +*** Keywords *** +Status Should Be + [Arguments] ${item} ${status} ${message}= + Should Be Equal ${item.status} ${status} + Should Be Equal ${item.message} ${message} diff --git a/atest/robot/running/steps_after_failure.robot b/atest/robot/running/steps_after_failure.robot index 30a1de2dc96..602f40d3001 100644 --- a/atest/robot/running/steps_after_failure.robot +++ b/atest/robot/running/steps_after_failure.robot @@ -5,143 +5,159 @@ Resource atest_resource.robot *** Test Cases *** Library keyword after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[2:]} 5 - Check Log Message ${tc.teardown.msgs[0]} This is run + Should Not Be Run ${tc[2:]} 5 + Check Log Message ${tc.teardown[0]} This is run User keyword after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} + Should Not Be Run ${tc[1:]} Non-existing keyword after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} + Should Not Be Run ${tc[1:]} Invalid keyword usage after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} + Should Not Be Run ${tc[1:]} Assignment after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} 4 - Check Keyword Data ${tc.body[1]} Not run assign=\${x} status=NOT RUN - Check Keyword Data ${tc.body[2]} Not run assign=\${x} status=NOT RUN - Check Keyword Data ${tc.body[3]} Not run assign=\${x}, \${y} status=NOT RUN - Check Keyword Data ${tc.body[4]} Not run assign=\${x}, \${y} status=NOT RUN + Should Not Be Run ${tc[1:]} 4 + Check Keyword Data ${tc[1]} Not run assign=\${x} status=NOT RUN + Check Keyword Data ${tc[2]} Not run assign=\${x} status=NOT RUN + Check Keyword Data ${tc[3]} Not run assign=\${x}, \${y} status=NOT RUN + Check Keyword Data ${tc[4]} Not run assign=\${x}, \${y} status=NOT RUN IF after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} - Should Not Be Run ${tc.body[1].body[0].body} - Should Not Be Run ${tc.body[1].body[1].body} - Check Keyword Data ${tc.body[1].body[1].body[0]} + Should Not Be Run ${tc[1:]} + Should Not Be Run ${tc[1, 0].body} + Should Not Be Run ${tc[1, 1].body} + Check Keyword Data ${tc[1, 1, 0]} + ... BuiltIn.Fail assign=\${x} args=This should not be run status=NOT RUN + +GROUP after failure + ${tc} = Check Test Case ${TESTNAME} + Should Not Be Run ${tc[1:]} + Should Not Be Run ${tc[1].body} 2 + Check Keyword Data ${tc[1, 1]} ... BuiltIn.Fail assign=\${x} args=This should not be run status=NOT RUN FOR after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} - Should Not Be Run ${tc.body[1].body} - Should Not Be Run ${tc.body[1].body[0].body} 2 - Check Keyword Data ${tc.body[1].body[0].body[1]} + Should Not Be Run ${tc[1:]} + Should Not Be Run ${tc[1].body} + Should Not Be Run ${tc[1, 0].body} 2 + Check Keyword Data ${tc[1, 0, 1]} ... BuiltIn.Fail assign=\${x} args=This should not be run either status=NOT RUN TRY after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} - Should Not Be Run ${tc.body[1].body} 4 - FOR ${step} IN @{tc.body[1].body} + Should Not Be Run ${tc[1:]} + Should Not Be Run ${tc[1].body} 4 + FOR ${step} IN @{tc[1].body} Should Not Be Run ${step.body} END WHILE after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} 3 - Should Not Be Run ${tc.body[1].body} - Should Not Be Run ${tc.body[1].body[0].body} 3 - Should Not Be Run ${tc.body[2].body} - Should Not Be Run ${tc.body[2].body[0].body} 2 - Should Not Be Run ${tc.body[3].body} - Should Not Be Run ${tc.body[3].body[0].body} 1 + Should Not Be Run ${tc[1:]} 3 + Should Not Be Run ${tc[1].body} + Should Not Be Run ${tc[1, 0].body} 3 + Should Not Be Run ${tc[2].body} + Should Not Be Run ${tc[2, 0].body} 2 + Should Not Be Run ${tc[3].body} + Should Not Be Run ${tc[3, 0].body} 1 RETURN after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} - Should Not Be Run ${tc.body[0].body[1:]} 2 - Should Be Equal ${tc.body[0].body[1].type} RETURN + Should Not Be Run ${tc[1:]} + Should Not Be Run ${tc[0][1:]} 2 + Should Be Equal ${tc[0, 1].type} RETURN BREAK and CONTINUE after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} 1 - Should Not Be Run ${tc.body[0].body[0].body[1:]} 2 - Should Not Be Run ${tc.body[1].body} - Should Not Be Run ${tc.body[1].body[0].body} 2 + Should Not Be Run ${tc[1:]} 1 + Should Not Be Run ${tc[0, 0][1:]} 2 + Should Not Be Run ${tc[1].body} + Should Not Be Run ${tc[1, 0].body} 2 Nested control structure after failure ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} 2 - Should Be Equal ${tc.body[1].type} FOR - Should Not Be Run ${tc.body[1].body} 1 - Should Be Equal ${tc.body[1].body[0].type} ITERATION - Should Not Be Run ${tc.body[1].body[0].body} 2 - Should Be Equal ${tc.body[1].body[0].body[0].type} IF/ELSE ROOT - Should Not Be Run ${tc.body[1].body[0].body[0].body} 2 - Should Be Equal ${tc.body[1].body[0].body[0].body[0].type} IF - Should Not Be Run ${tc.body[1].body[0].body[0].body[0].body} 2 - Should Be Equal ${tc.body[1].body[0].body[0].body[0].body[0].type} FOR - Should Not Be Run ${tc.body[1].body[0].body[0].body[0].body[0].body} 1 - Should Be Equal ${tc.body[1].body[0].body[0].body[0].body[0].body[0].type} ITERATION - Should Not Be Run ${tc.body[1].body[0].body[0].body[0].body[0].body[0].body} 3 - Should Be Equal ${tc.body[1].body[0].body[0].body[0].body[0].body[0].body[0].type} KEYWORD - Should Be Equal ${tc.body[1].body[0].body[0].body[0].body[0].body[0].body[1].type} KEYWORD - Should Be Equal ${tc.body[1].body[0].body[0].body[0].body[0].body[0].body[2].type} KEYWORD - Should Be Equal ${tc.body[1].body[0].body[0].body[0].body[1].type} KEYWORD - Should Be Equal ${tc.body[1].body[0].body[0].body[1].type} ELSE - Should Not Be Run ${tc.body[1].body[0].body[0].body[1].body} 2 - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[0].type} WHILE - Should Not Be Run ${tc.body[1].body[0].body[0].body[1].body[0].body} 1 - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[0].body[0].type} ITERATION - Should Not Be Run ${tc.body[1].body[0].body[0].body[1].body[0].body[0].body} 2 - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[0].body[0].body[0].type} KEYWORD - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[0].body[0].body[1].type} KEYWORD - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[1].type} TRY/EXCEPT ROOT - Should Not Be Run ${tc.body[1].body[0].body[0].body[1].body[1].body} 2 - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[1].body[0].type} TRY - Should Not Be Run ${tc.body[1].body[0].body[0].body[1].body[1].body[0].body} 1 - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[1].body[0].body[0].type} KEYWORD - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[1].body[1].type} EXCEPT - Should Not Be Run ${tc.body[1].body[0].body[0].body[1].body[1].body[1].body} 1 - Should Be Equal ${tc.body[1].body[0].body[0].body[1].body[1].body[1].body[0].type} BREAK - Should Be Equal ${tc.body[1].body[0].body[1].type} KEYWORD - Should Be Equal ${tc.body[2].type} KEYWORD + Should Not Be Run ${tc[1:]} 2 + Should Be Equal ${tc[1].type} FOR + Should Not Be Run ${tc[1].body} 1 + Should Be Equal ${tc[1, 0].type} ITERATION + Should Not Be Run ${tc[1, 0].body} 2 + Should Be Equal ${tc[1, 0, 0].type} IF/ELSE ROOT + Should Not Be Run ${tc[1, 0, 0].body} 2 + Should Be Equal ${tc[1, 0, 0, 0].type} IF + Should Not Be Run ${tc[1, 0, 0, 0].body} 2 + Should Be Equal ${tc[1, 0, 0, 0, 0].type} FOR + Should Not Be Run ${tc[1, 0, 0, 0, 0].body} 1 + Should Be Equal ${tc[1, 0, 0, 0, 0, 0].type} ITERATION + Should Not Be Run ${tc[1, 0, 0, 0, 0, 0].body} 2 + Should Be Equal ${tc[1, 0, 0, 0, 0, 0, 0].type} KEYWORD + Should Be Equal ${tc[1, 0, 0, 0, 0, 0, 1].type} GROUP + Should Not Be Run ${tc[1, 0, 0, 0, 0, 0, 1].body} 2 + Should Be Equal ${tc[1, 0, 0, 0, 0, 0, 1, 0].type} KEYWORD + Should Be Equal ${tc[1, 0, 0, 0, 0, 0, 1, 1].type} KEYWORD + Should Be Equal ${tc[1, 0, 0, 0, 1].type} KEYWORD + Should Be Equal ${tc[1, 0, 0, 1].type} ELSE + Should Not Be Run ${tc[1, 0, 0, 1].body} 2 + Should Be Equal ${tc[1, 0, 0, 1, 0].type} WHILE + Should Not Be Run ${tc[1, 0, 0, 1, 0].body} 1 + Should Be Equal ${tc[1, 0, 0, 1, 0, 0].type} ITERATION + Should Not Be Run ${tc[1, 0, 0, 1, 0, 0].body} 2 + Should Be Equal ${tc[1, 0, 0, 1, 0, 0, 0].type} KEYWORD + Should Be Equal ${tc[1, 0, 0, 1, 0, 0, 1].type} KEYWORD + Should Be Equal ${tc[1, 0, 0, 1, 1].type} TRY/EXCEPT ROOT + Should Not Be Run ${tc[1, 0, 0, 1, 1].body} 2 + Should Be Equal ${tc[1, 0, 0, 1, 1, 0].type} TRY + Should Not Be Run ${tc[1, 0, 0, 1, 1, 0].body} 1 + Should Be Equal ${tc[1, 0, 0, 1, 1, 0, 0].type} KEYWORD + Should Be Equal ${tc[1, 0, 0, 1, 1, 1].type} EXCEPT + Should Not Be Run ${tc[1, 0, 0, 1, 1, 1].body} 1 + Should Be Equal ${tc[1, 0, 0, 1, 1, 1, 0].type} BREAK + Should Be Equal ${tc[1, 0, 1].type} KEYWORD + Should Be Equal ${tc[2].type} KEYWORD Failure in user keyword ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} - Should Not Be Run ${tc.body[0].body[1:]} 2 + Should Not Be Run ${tc[1:]} + Should Not Be Run ${tc[0][1:]} 2 Failure in IF branch ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[0].body[0].body[1:]} - Should Not Be Run ${tc.body[0].body[1].body} - Should Not Be Run ${tc.body[1:]} + Should Not Be Run ${tc[0, 0][1:]} + Should Not Be Run ${tc[0, 1].body} + Should Not Be Run ${tc[1:]} Failure in ELSE IF branch ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[0].body[0].body} - Should Not Be Run ${tc.body[0].body[1].body[1:]} - Should Not Be Run ${tc.body[0].body[2].body} - Should Not Be Run ${tc.body[1:]} + Should Not Be Run ${tc[0, 0].body} + Should Not Be Run ${tc[0, 1][1:]} + Should Not Be Run ${tc[0, 2].body} + Should Not Be Run ${tc[1:]} Failure in ELSE branch ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[0].body[0].body} - Should Not Be Run ${tc.body[0].body[1].body[1:]} - Should Not Be Run ${tc.body[1:]} + Should Not Be Run ${tc[0, 0].body} + Should Not Be Run ${tc[0, 1][1:]} + Should Not Be Run ${tc[1:]} + +Failure in GROUP + ${tc} = Check Test Case ${TESTNAME} + Should Not Be Run ${tc[0, 0][1:]} + Should Not Be Run ${tc[0][1:]} 2 + Should Not Be Run ${tc[0, 2].body} + Should Not Be Run ${tc[1:]} Failure in FOR iteration ${tc} = Check Test Case ${TESTNAME} - Should Not Be Run ${tc.body[1:]} - Length Should Be ${tc.body[0].body} 1 - Should Not Be Run ${tc.body[0].body[0].body[1:]} + Should Not Be Run ${tc[1:]} + Length Should Be ${tc[0].body} 1 + Should Not Be Run ${tc[0, 0][1:]} *** Keywords *** Should Not Be Run diff --git a/atest/robot/running/stopping_with_signal.robot b/atest/robot/running/stopping_with_signal.robot index a1a70c1d154..f93f2eb4348 100644 --- a/atest/robot/running/stopping_with_signal.robot +++ b/atest/robot/running/stopping_with_signal.robot @@ -59,8 +59,8 @@ One Signal Should Stop Test Execution Gracefully And Test Case And Suite Teardow Start And Send Signal with_teardown.robot One SIGINT Check Test Cases Have Failed Correctly ${tc} = Get Test Case Test - Check Log Message ${tc.teardown.msgs[0]} Logging Test Case Teardown - Check Log Message ${SUITE.teardown.kws[0].msgs[0]} Logging Suite Teardown + Check Log Message ${tc.teardown[0]} Logging Test Case Teardown + Check Log Message ${SUITE.teardown[0, 0]} Logging Suite Teardown Skip Teardowns After Stopping Gracefully Start And Send Signal with_teardown.robot One SIGINT 0s --SkipTeardownOnExit @@ -69,6 +69,32 @@ Skip Teardowns After Stopping Gracefully Teardown Should Not Be Defined ${tc} Teardown Should Not Be Defined ${SUITE} +SIGINT Signal Should Stop Async Test Execution Gracefully + Start And Send Signal async_stop.robot One SIGINT 5 + Check Test Cases Have Failed Correctly + ${tc} = Get Test Case Test + Length Should Be ${tc[1].body} 1 + Check Log Message ${tc[1, 0]} Start Sleep + Length Should Be ${SUITE.teardown.body} 0 + +Two SIGINT Signals Should Stop Async Test Execution Forcefully + Start And Send Signal async_stop.robot Two SIGINTs 5 + Check Tests Have Been Forced To Shutdown + +SIGTERM Signal Should Stop Async Test Execution Gracefully + [Tags] no-windows + Start And Send Signal async_stop.robot One SIGTERM 5 + Check Test Cases Have Failed Correctly + ${tc} = Get Test Case Test + Length Should Be ${tc[1].body} 1 + Check Log Message ${tc[1, 0]} Start Sleep + Length Should Be ${SUITE.teardown.body} 0 + +Two SIGTERM Signals Should Stop Async Test Execution Forcefully + [Tags] no-windows + Start And Send Signal async_stop.robot Two SIGTERMs 5 + Check Tests Have Been Forced To Shutdown + *** Keywords *** Start And Send Signal [Arguments] ${datasource} ${signals} ${sleep}=0s @{extra options} diff --git a/atest/robot/running/test_case_status.robot b/atest/robot/running/test_case_status.robot index 842747f7f03..55e4ae27b1a 100644 --- a/atest/robot/running/test_case_status.robot +++ b/atest/robot/running/test_case_status.robot @@ -1,11 +1,11 @@ -*** Setting *** +*** Settings *** Documentation Tests for setting test case status correctly when test passes ... and when a failure or error occurs. Also includes test cases ... for running test setup and teardown in different situations. Suite Setup Run Tests ${EMPTY} running/test_case_status.robot Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Test Passes Check Test Case ${TEST NAME} @@ -41,12 +41,10 @@ Test Setup And Teardown Pass Check Test Case ${TEST NAME} Test Teardown is Run When Setup Fails - ${test} Check Test Case ${TEST NAME} - ${td} = Set Variable ${test.teardown} - Should Not Be Equal ${td} ${None} Teardown not run No values - Length Should Be ${td.msgs} 1 - Check Log Message ${td.msgs[0]} Hello from teardown! - Length Should Be ${td.kws} 0 + ${tc} = Check Test Case ${TEST NAME} + Should Not Be Equal ${tc.teardown} ${None} Teardown not run No values + Length Should Be ${tc.teardown.body} 1 + Check Log Message ${tc.teardown[0]} Hello from teardown! Test Setup And Teardown Fails Check Test Case ${TEST NAME} diff --git a/atest/robot/running/test_template.robot b/atest/robot/running/test_template.robot index c6306bc90d2..ba2a2e22941 100644 --- a/atest/robot/running/test_template.robot +++ b/atest/robot/running/test_template.robot @@ -59,32 +59,32 @@ Invalid FOR Template With IF ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].status} PASS - Should Be Equal ${tc.body[0].body[0].type} IF - Should Be Equal ${tc.body[0].body[0].status} NOT RUN - Should Be Equal ${tc.body[0].body[1].type} ELSE IF - Should Be Equal ${tc.body[0].body[1].status} NOT RUN - Should Be Equal ${tc.body[0].body[2].type} ELSE - Should Be Equal ${tc.body[0].body[2].status} PASS + Should Be Equal ${tc[0].status} PASS + Should Be Equal ${tc[0, 0].type} IF + Should Be Equal ${tc[0, 0].status} NOT RUN + Should Be Equal ${tc[0, 1].type} ELSE IF + Should Be Equal ${tc[0, 1].status} NOT RUN + Should Be Equal ${tc[0, 2].type} ELSE + Should Be Equal ${tc[0, 2].status} PASS Template With IF Failing ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].status} FAIL - Should Be Equal ${tc.body[0].body[0].type} IF - Should Be Equal ${tc.body[0].body[0].status} FAIL - Should Be Equal ${tc.body[1].status} FAIL - Should Be Equal ${tc.body[1].body[0].type} IF - Should Be Equal ${tc.body[1].body[0].status} NOT RUN - Should Be Equal ${tc.body[1].body[1].type} ELSE IF - Should Be Equal ${tc.body[1].body[1].status} FAIL - Should Be Equal ${tc.body[1].body[2].type} ELSE - Should Be Equal ${tc.body[1].body[2].status} NOT RUN + Should Be Equal ${tc[0].status} FAIL + Should Be Equal ${tc[0, 0].type} IF + Should Be Equal ${tc[0, 0].status} FAIL + Should Be Equal ${tc[1].status} FAIL + Should Be Equal ${tc[1, 0].type} IF + Should Be Equal ${tc[1, 0].status} NOT RUN + Should Be Equal ${tc[1, 1].type} ELSE IF + Should Be Equal ${tc[1, 1].status} FAIL + Should Be Equal ${tc[1, 2].type} ELSE + Should Be Equal ${tc[1, 2].status} NOT RUN Invalid IF ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].status} FAIL - Should Be Equal ${tc.body[0].body[0].type} IF - Should Be Equal ${tc.body[0].body[0].status} FAIL + Should Be Equal ${tc[0].status} FAIL + Should Be Equal ${tc[0, 0].type} IF + Should Be Equal ${tc[0, 0].status} FAIL FOR and IF Check Test Case ${TESTNAME} @@ -116,7 +116,7 @@ Templated test with for loop continues after keyword timeout Templated test ends after syntax errors Check Test Case ${TESTNAME} -Templated test continues after variable error +Templated test continues after non-syntax errors Check Test Case ${TESTNAME} Templates and fatal errors diff --git a/atest/robot/running/test_template_with_embeded_args.robot b/atest/robot/running/test_template_with_embeded_args.robot index 680406bce21..65b3d427abe 100644 --- a/atest/robot/running/test_template_with_embeded_args.robot +++ b/atest/robot/running/test_template_with_embeded_args.robot @@ -5,39 +5,39 @@ Resource atest_resource.robot *** Test Cases *** Matching arguments ${tc} = Check Test Case ${TESTNAME} - Keyword should be ${tc.kws[0]} The result of 1 + 1 should be 2 - Keyword should be ${tc.kws[1]} The result of 1 + 2 should be 3 - Keyword should be ${tc.kws[2]} The result of 1 + 3 should be 5 + Keyword should be ${tc[0]} The result of 1 + 1 should be 2 + Keyword should be ${tc[1]} The result of 1 + 2 should be 3 + Keyword should be ${tc[2]} The result of 1 + 3 should be 5 Argument names do not need to be same as in definition ${tc} = Check Test Case ${TESTNAME} - Keyword should be ${tc.kws[0]} The result of 1 + 1 should be 2 - Keyword should be ${tc.kws[1]} The result of 1 + 2 should be 3 - Keyword should be ${tc.kws[2]} The result of 1 + 3 should be 5 + Keyword should be ${tc[0]} The result of 1 + 1 should be 2 + Keyword should be ${tc[1]} The result of 1 + 2 should be 3 + Keyword should be ${tc[2]} The result of 1 + 3 should be 5 Some arguments can be hard-coded ${tc} = Check Test Case ${TESTNAME} - Keyword should be ${tc.kws[0]} The result of 1 + 1 should be 3 - Keyword should be ${tc.kws[1]} The result of 1 + 2 should be 3 - Keyword should be ${tc.kws[2]} The result of 1 + 3 should be 3 + Keyword should be ${tc[0]} The result of 1 + 1 should be 3 + Keyword should be ${tc[1]} The result of 1 + 2 should be 3 + Keyword should be ${tc[2]} The result of 1 + 3 should be 3 Can have different arguments than definition ${tc} = Check Test Case ${TESTNAME} - Keyword should be ${tc.kws[0]} The result of 38 + 3 + 1 should be 42 - Keyword should be ${tc.kws[1]} The non-existing of 666 should be 42 + Keyword should be ${tc[0]} The result of 38 + 3 + 1 should be 42 + Keyword should be ${tc[1]} The non-existing of 666 should be 42 Can use variables ${tc} = Check Test Case ${TESTNAME} - Keyword should be ${tc.kws[0]} The result of \${1} + \${2} should be \${3} + Keyword should be ${tc[0]} The result of \${1} + \${2} should be \${3} Cannot have more arguments than variables ${tc} = Check Test Case ${TESTNAME} - Keyword should be ${tc.kws[0]} The result of \${calc} should be 3 + Keyword should be ${tc[0]} The result of \${calc} should be 3 ... 1 + 2 extra Cannot have less arguments than variables ${tc} = Check Test Case ${TESTNAME} - Keyword should be ${tc.kws[0]} The result of \${calc} should be \${extra} + Keyword should be ${tc[0]} The result of \${calc} should be \${extra} ... 1 + 2 *** Keywords *** diff --git a/atest/robot/running/timeouts.robot b/atest/robot/running/timeouts.robot index 6a0b6edbb57..020db103dd5 100644 --- a/atest/robot/running/timeouts.robot +++ b/atest/robot/running/timeouts.robot @@ -16,14 +16,14 @@ Timeouted Test Passes Timeouted Test Fails Before Timeout Check Test Case Failing Before Timeout -Show Correct Trace Back When Failing Before Timeout +Show Correct Traceback When Failing Before Timeout ${tc} = Check Test Case ${TEST NAME} ${expected} = Catenate SEPARATOR=\n ... Traceback (most recent call last): ... ${SPACE*2}File "*", line *, in exception ... ${SPACE*4}raise exception(msg) ... RuntimeError: Failure before timeout - Check Log Message ${tc.kws[0].msgs[-1]} ${expected} pattern=yes level=DEBUG + Check Log Message ${tc[0, -1]} ${expected} DEBUG pattern=True traceback=True Timeouted Test Timeouts Check Test Case Sleeping And Timeouting @@ -63,17 +63,17 @@ Test Timeouts When Also Keywords Are Timeouted Keyword Timeout From Variable ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].timeout} 1 millisecond + Should Be Equal ${tc[0].timeout} 1 millisecond Keyword Timeout From Argument ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].timeout} 1 second - Should Be Equal ${tc.kws[1].timeout} 2 milliseconds + Should Be Equal ${tc[0].timeout} 1 second + Should Be Equal ${tc[1].timeout} 2 milliseconds Embedded Arguments Timeout From Argument ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].timeout} 1 second - Should Be Equal ${tc.kws[1].timeout} 3 milliseconds + Should Be Equal ${tc[0].timeout} 1 second + Should Be Equal ${tc[1].timeout} 3 milliseconds Local Variables Are Not Visible In Child Keyword Timeout Check Test Case ${TEST NAME} @@ -88,9 +88,9 @@ Test Timeout During Setup Teardown After Test Timeout [Documentation] Test that teardown is executed after a test has timed out ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.teardown.msgs[0]} Teardown executed + Check Log Message ${tc.teardown[0]} Teardown executed ${tc} = Check Test Case Teardown With Sleep After Test Timeout - Check Log Message ${tc.teardown.kws[1].msgs[0]} Teardown executed + Check Log Message ${tc.teardown[1, 0]} Teardown executed Failing Teardown After Test Timeout Check Test Case ${TEST NAME} @@ -98,7 +98,7 @@ Failing Teardown After Test Timeout Test Timeout During Teardown [Documentation] Test timeout should not interrupt teardown but test should be failed afterwards ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.teardown.kws[1].msgs[0]} Teardown executed + Check Log Message ${tc.teardown[1, 0]} Teardown executed Timeouted Setup Passes Check Test Case ${TEST NAME} @@ -133,8 +133,8 @@ Keyword Timeout Should Not Be Active For Run Keyword Variants But To Keywords Th Logging With Timeouts [Documentation] Testing that logging works with timeouts ${tc} = Check Test Case Timeouted Keyword Passes - Check Log Message ${tc.kws[0].msgs[1]} Testing logging in timeouted test - Check Log Message ${tc.kws[1].kws[0].msgs[1]} Testing logging in timeouted keyword + Check Log Message ${tc[0, 1]} Testing logging in timeouted test + Check Log Message ${tc[1, 0, 1]} Testing logging in timeouted keyword Timeouted Keyword Called With Wrong Number of Arguments Check Test Case ${TEST NAME} @@ -144,31 +144,31 @@ Timeouted Keyword Called With Wrong Number of Arguments with Run Keyword Test Timeout Logging ${tc} = Check Test Case Passing - Timeout should have been active ${tc.kws[0]} 1 second 1 + Timeout should have been active ${tc[0]} 1 second 1 ${tc} = Check Test Case Failing Before Timeout - Timeout should have been active ${tc.kws[0]} 2 seconds 3 + Timeout should have been active ${tc[0]} 2 seconds 3 ${tc} = Check Test Case Sleeping And Timeouting - Timeout should have been active ${tc.kws[0]} 1 second 2 exceeded=True + Timeout should have been active ${tc[0]} 1 second 2 exceeded=True Keyword Timeout Logging ${tc} = Check Test Case Timeouted Keyword Passes - Keyword timeout should have been active ${tc.kws[1].kws[0]} 5 seconds 2 + Keyword timeout should have been active ${tc[1, 0]} 5 seconds 2 ${tc} = Check Test Case Timeouted Keyword Fails Before Timeout - Keyword timeout should have been active ${tc.kws[0].kws[0]} 2 hours 30 minutes 3 + Keyword timeout should have been active ${tc[0, 0]} 2 hours 30 minutes 3 ${tc} = Check Test Case Timeouted Keyword Timeouts - Keyword timeout should have been active ${tc.kws[0].kws[0]} 99 milliseconds 2 exceeded=True + Keyword timeout should have been active ${tc[0, 0]} 99 milliseconds 2 exceeded=True Zero timeout is ignored ${tc} = Check Test Case ${TEST NAME} Should Be Equal ${tc.timeout} 0 seconds - Should Be Equal ${tc.kws[0].timeout} 0 seconds - Should Be True ${tc.kws[0].elapsedtime} > 99 + Should Be Equal ${tc[0].timeout} 0 seconds + Elapsed Time Should Be Valid ${tc[0].elapsed_time} minimum=0.099 Negative timeout is ignored ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].timeout} - 1 second - Should Be Equal ${tc.kws[0].timeout} - 1 second - Should Be True ${tc.kws[0].elapsedtime} > 99 + Should Be Equal ${tc[0].timeout} - 1 second + Should Be Equal ${tc[0].timeout} - 1 second + Elapsed Time Should Be Valid ${tc[0].elapsed_time} minimum=0.099 Invalid test timeout Check Test Case ${TEST NAME} @@ -179,10 +179,9 @@ Invalid keyword timeout *** Keywords *** Timeout should have been active [Arguments] ${kw} ${timeout} ${msg count} ${exceeded}=False ${type}=Test - Check Log Message ${kw.msgs[0]} ${type} timeout ${timeout} active. * left. DEBUG pattern=True - Length Should Be ${kw.msgs} ${msg count} - Run Keyword If ${exceeded} - ... Timeout should have exceeded ${kw} ${timeout} ${type} + Check Log Message ${kw[0]} ${type} timeout ${timeout} active. * left. DEBUG pattern=True + Length Should Be ${kw.body} ${msg count} + IF ${exceeded} Timeout should have exceeded ${kw} ${timeout} ${type} Keyword timeout should have been active [Arguments] ${kw} ${timeout} ${msg count} ${exceeded}=False @@ -190,4 +189,4 @@ Keyword timeout should have been active Timeout should have exceeded [Arguments] ${kw} ${timeout} ${type}=Test - Check Log Message ${kw.msgs[1]} ${type} timeout ${timeout} exceeded. FAIL + Check Log Message ${kw[1]} ${type} timeout ${timeout} exceeded. FAIL diff --git a/atest/robot/running/timeouts_with_custom_messages.robot b/atest/robot/running/timeouts_with_custom_messages.robot index 46127b1ae28..4f21b34fb55 100644 --- a/atest/robot/running/timeouts_with_custom_messages.robot +++ b/atest/robot/running/timeouts_with_custom_messages.robot @@ -9,19 +9,15 @@ Default Test Timeout Message Test Timeout Message Check Test Case ${TEST NAME} - Using more than one value with timeout should error 1 9 2 Test Timeout Message In Multiple Columns Check Test Case ${TEST NAME} - Using more than one value with timeout should error 2 13 7 Keyword Timeout Message Check Test Case ${TEST NAME} - Using more than one value with timeout should error 3 26 2 Keyword Timeout Message In Multiple Columns Check Test Case ${TEST NAME} - Using more than one value with timeout should error 4 30 7 *** Keywords *** Using more than one value with timeout should error diff --git a/atest/robot/running/try_except/except_behaviour.robot b/atest/robot/running/try_except/except_behaviour.robot index 74a8adcce74..1ede85342a5 100644 --- a/atest/robot/running/try_except/except_behaviour.robot +++ b/atest/robot/running/try_except/except_behaviour.robot @@ -5,19 +5,19 @@ Test Template Verify try except and block statuses *** Test Cases *** Equals is the default matcher - FAIL PASS + FAIL PASS pattern_types=[None] Equals with whitespace FAIL PASS Glob matcher - FAIL NOT RUN PASS + FAIL NOT RUN PASS pattern_types=['GloB', 'gloB'] Startswith matcher - FAIL PASS + FAIL PASS pattern_types=['start'] Regexp matcher - FAIL NOT RUN PASS + FAIL NOT RUN PASS pattern_types=['REGEXP', 'REGEXP'] Regexp escapes FAIL PASS @@ -35,16 +35,22 @@ Non-string pattern FAIL NOT RUN NOT RUN NOT RUN NOT RUN Variable in pattern type - FAIL PASS + FAIL PASS pattern_types=['\${regexp}'] Invalid variable in pattern type - FAIL FAIL PASS + FAIL FAIL PASS pattern_types=['\${does not exist}'] Invalid pattern type - FAIL FAIL + FAIL NOT RUN NOT RUN pattern_types=['glob', 'invalid'] + +Invalid pattern type from variable + FAIL FAIL pattern_types=["\${{'invalid'}}"] Non-string pattern type - FAIL FAIL + FAIL FAIL pattern_types=['\${42}'] + +Pattern type multiple times + FAIL PASS NOT RUN pattern_types=['start'] Pattern type without patterns FAIL PASS @@ -53,7 +59,7 @@ Skip cannot be caught SKIP NOT RUN PASS tc_status=SKIP Return cannot be caught - PASS NOT RUN PASS path=body[0].body[0] + PASS NOT RUN PASS path=body[0].body[0] AS gets the message FAIL PASS diff --git a/atest/robot/running/try_except/invalid_try_except.robot b/atest/robot/running/try_except/invalid_try_except.robot index e69a824b577..45ad4c198fb 100644 --- a/atest/robot/running/try_except/invalid_try_except.robot +++ b/atest/robot/running/try_except/invalid_try_except.robot @@ -81,3 +81,10 @@ CONTINUE in FINALLY RETURN in FINALLY TRY:PASS FINALLY:FAIL path=body[0].body[0] + +Invalid TRY/EXCEPT causes syntax error that cannot be caught + TRY:FAIL EXCEPT:NOT RUN ELSE:NOT RUN + +Dangling FINALLY + [Template] Check Test Case + ${TEST NAME} diff --git a/atest/robot/running/try_except/try_except.robot b/atest/robot/running/try_except/try_except.robot index aca14fc3d85..8d074cd6446 100644 --- a/atest/robot/running/try_except/try_except.robot +++ b/atest/robot/running/try_except/try_except.robot @@ -35,21 +35,21 @@ Default except pattern FAIL PASS Syntax errors cannot be caught - FAIL + FAIL NOT RUN NOT RUN Finally block executed when no failures [Template] None ${tc}= Verify try except and block statuses PASS NOT RUN PASS PASS - Check Log Message ${tc.body[0].body[0].body[0].msgs[0]} all good - Check Log Message ${tc.body[0].body[2].body[0].msgs[0]} in the else - Check Log Message ${tc.body[0].body[3].body[0].msgs[0]} Hello from finally! + Check Log Message ${tc[0, 0, 0, 0]} all good + Check Log Message ${tc[0, 2, 0, 0]} in the else + Check Log Message ${tc[0, 3, 0, 0]} Hello from finally! Finally block executed after catch [Template] None ${tc}= Verify try except and block statuses FAIL PASS PASS - Check Log Message ${tc.body[0].body[0].body[0].msgs[0]} all not good FAIL - Check Log Message ${tc.body[0].body[1].body[0].msgs[0]} we are safe now - Check Log Message ${tc.body[0].body[2].body[0].msgs[0]} Hello from finally! + Check Log Message ${tc[0, 0, 0, 0]} all not good FAIL + Check Log Message ${tc[0, 1, 0, 0]} we are safe now + Check Log Message ${tc[0, 2, 0, 0]} Hello from finally! Finally block executed after failure in except FAIL FAIL NOT RUN PASS diff --git a/atest/robot/running/try_except/try_except_resource.robot b/atest/robot/running/try_except/try_except_resource.robot index 6f557b433e4..590cc5ffd60 100644 --- a/atest/robot/running/try_except/try_except_resource.robot +++ b/atest/robot/running/try_except/try_except_resource.robot @@ -4,9 +4,10 @@ Library Collections *** Keywords *** Verify try except and block statuses - [Arguments] @{types_and_statuses} ${tc_status}= ${path}=body[0] + [Arguments] @{types_and_statuses} ${tc_status}= ${path}=body[0] ${pattern_types}=[] ${tc}= Check test status @{{[s.split(':')[-1] for s in $types_and_statuses]}} tc_status=${tc_status} Block statuses should be ${tc.${path}} @{types_and_statuses} + Pattern types should be ${tc.${path}} ${pattern_types} RETURN ${tc} Check Test Status @@ -34,3 +35,11 @@ Block statuses should be Should Be Equal ${block.status} ${type_and_status} END END + +Pattern types should be + [Arguments] ${try_except} ${pattern_types} + @{pattern_types} = Evaluate ${pattern_types} + FOR ${except} ${expected} IN ZIP ${try_except.body[1:]} ${pattern_types} mode=shortest + Should Be Equal ${except.type} EXCEPT + Should Be Equal ${except.pattern_type} ${expected} + END diff --git a/atest/robot/running/while/break_and_continue.robot b/atest/robot/running/while/break_and_continue.robot index 8fb4aac3eb5..bc932d39d12 100644 --- a/atest/robot/running/while/break_and_continue.robot +++ b/atest/robot/running/while/break_and_continue.robot @@ -1,7 +1,7 @@ *** Settings *** Resource while.resource Suite Setup Run Tests ${EMPTY} running/while/break_and_continue.robot -Test Template Check while loop +Test Template Check WHILE loop *** Test Cases *** With CONTINUE @@ -31,6 +31,24 @@ With BREAK inside EXCEPT With BREAK inside TRY-ELSE PASS 1 +BREAK with continuable failures + FAIL 1 + +CONTINUE with continuable failures + FAIL 2 + +Invalid BREAK + FAIL 1 + +Invalid CONTINUE + FAIL 1 + +Invalid BREAK not executed + PASS 1 + +Invalid CONTINUE not executed + NOT RUN 1 + With CONTINUE in UK PASS 5 body[0].body[0] diff --git a/atest/robot/running/while/invalid_while.robot b/atest/robot/running/while/invalid_while.robot index c6687e9b247..e2526405943 100644 --- a/atest/robot/running/while/invalid_while.robot +++ b/atest/robot/running/while/invalid_while.robot @@ -1,23 +1,61 @@ *** Settings *** Resource while.resource -Suite Setup Run Tests ${EMPTY} running/while/invalid_while.robot +Suite Setup Run Tests --log test_result_model_as_well running/while/invalid_while.robot *** Test Cases *** -No condition - Check Test Case ${TESTNAME} - Multiple conditions - ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].condition} Too, many, ! + ${tc} = Check Invalid WHILE Test Case + Should Be Equal ${tc[0].condition} Too, many, conditions, ! Invalid condition - Check Test Case ${TESTNAME} + Check Invalid WHILE Test Case + +Non-existing ${variable} in condition + Check Invalid WHILE Test Case -Non-existing variable in condition - Check Test Case ${TESTNAME} +Non-existing $variable in condition + Check Invalid WHILE Test Case + +Recommend $var syntax if invalid condition contains ${var} + Check Test Case ${TEST NAME} + +Invalid condition on second round + Check Test Case ${TEST NAME} No body - Check Test Case ${TESTNAME} + Check Invalid WHILE Test Case body=False No END - Check Test Case ${TESTNAME} + Check Invalid WHILE Test Case + +Invalid data causes syntax error + Check Test Case ${TEST NAME} + +Invalid condition causes normal error + Check Test Case ${TEST NAME} + +Non-existing variable in condition causes normal error + Check Test Case ${TEST NAME} + +Templatest are not supported + ${tc} = Check Test Case ${TEST NAME} + Should Be Equal ${tc[0].type} WHILE + Should Be Equal ${tc[0].status} FAIL + Should Be Equal ${tc[0, 0].type} ITERATION + Should Be Equal ${tc[0, 0].status} NOT RUN + Check Keyword Data ${tc[0, 0, 0]} ${EMPTY} args=1 status=NOT RUN + Check Keyword Data ${tc[0, 0, 1]} ${EMPTY} args=2 status=NOT RUN + +*** Keywords *** +Check Invalid WHILE Test Case + [Arguments] ${body}=True + ${tc} = Check Test Case ${TESTNAME} + Should Be Equal ${tc[0].type} WHILE + Should Be Equal ${tc[0].status} FAIL + Should Be Equal ${tc[0, 0].type} ITERATION + Should Be Equal ${tc[0, 0].status} NOT RUN + IF ${body} + Should Be Equal ${tc[0, 0, 0].full_name} BuiltIn.Fail + Should Be Equal ${tc[0, 0, 0].status} NOT RUN + END + RETURN ${tc} diff --git a/atest/robot/running/while/nested_while.robot b/atest/robot/running/while/nested_while.robot index 96e08c15726..e745c002619 100644 --- a/atest/robot/running/while/nested_while.robot +++ b/atest/robot/running/while/nested_while.robot @@ -5,24 +5,24 @@ Suite Setup Run Tests ${EMPTY} running/while/nested_while.robot *** Test Cases *** Inside FOR ${tc}= Check test case ${TEST NAME} - Check loop attributes ${tc.body[0].body[0].body[0]} PASS 4 - Check loop attributes ${tc.body[0].body[1].body[0]} PASS 3 - Check loop attributes ${tc.body[0].body[2].body[0]} PASS 2 - Length should be ${tc.body[0].body} 3 + Check loop attributes ${tc[0, 0, 0]} PASS 4 + Check loop attributes ${tc[0, 1, 0]} PASS 3 + Check loop attributes ${tc[0, 2, 0]} PASS 2 + Length should be ${tc[0].body} 3 Failing inside FOR ${tc}= Check test case ${TEST NAME} - Check loop attributes ${tc.body[0].body[0].body[0]} FAIL 2 - Length should be ${tc.body[0].body} 1 + Check loop attributes ${tc[0, 0, 0]} FAIL 2 + Length should be ${tc[0].body} 1 Inside IF ${tc}= Check test case ${TEST NAME} - Check loop attributes ${tc.body[0].body[0].body[1]} PASS 4 + Check loop attributes ${tc[0, 0, 1]} PASS 4 In suite setup ${suite}= Get Test Suite Nested While - Check loop attributes ${suite.setup.body[1]} PASS 4 + Check loop attributes ${suite.setup[1]} PASS 4 In suite teardown ${suite}= Get Test Suite Nested While - Check loop attributes ${suite.teardown.body[1]} PASS 4 + Check loop attributes ${suite.teardown[1]} PASS 4 diff --git a/atest/robot/running/while/on_limit.robot b/atest/robot/running/while/on_limit.robot new file mode 100644 index 00000000000..91415d27cb9 --- /dev/null +++ b/atest/robot/running/while/on_limit.robot @@ -0,0 +1,59 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} running/while/on_limit.robot +Resource while.resource + +*** Test Cases *** +On limit pass with time limit defined + Check WHILE Loop PASS not known + +On limit pass with iteration limit defined + Check WHILE loop PASS 5 + +On limit fail + Check WHILE Loop FAIL 5 + +On limit pass with failures in loop + Check WHILE Loop FAIL 1 + +On limit pass with continuable failure + Check WHILE Loop FAIL 2 + +On limit fail with continuable failure + Check WHILE Loop FAIL 2 + +Invalid on_limit + Check WHILE Loop FAIL 1 not_run=True + +Invalid on_limit from variable + Check WHILE Loop FAIL 1 not_run=True + +On limit without limit + Check WHILE Loop FAIL 1 not_run=True + +On limit with invalid variable + Check WHILE Loop FAIL 1 not_run=True + +On limit message + Check WHILE Loop FAIL 11 + +On limit message without limit + Check WHILE Loop FAIL 10000 + +On limit message from variable + Check WHILE Loop FAIL 5 + +Part of on limit message from variable + Check WHILE Loop FAIL 5 + +On limit message is not used if limit is not hit + Check WHILE Loop PASS 2 + +Nested while on limit message + Check WHILE Loop FAIL 1 path=body[0] + Check WHILE Loop FAIL 5 path=body[0].body[0].body[0] + +On limit message before limit + Check WHILE Loop FAIL 5 + +On limit message with invalid variable + Check WHILE Loop FAIL 1 not_run=True diff --git a/atest/robot/running/while/while.resource b/atest/robot/running/while/while.resource index 4ee25df6dc0..392399f1bb6 100644 --- a/atest/robot/running/while/while.resource +++ b/atest/robot/running/while/while.resource @@ -1,17 +1,21 @@ *** Settings *** -Resource atest_resource.robot - +Resource atest_resource.robot *** Keywords *** -Check while loop - [Arguments] ${status} ${iterations} ${path}=body[0] - ${tc}= Check test case ${TEST NAME} - ${loop}= Check loop attributes ${tc.${path}} ${status} ${iterations} +Check WHILE loop + [Arguments] ${status} ${iterations} ${path}=body[0] ${not_run}=False + ${tc}= Check Test Case ${TEST NAME} + ${loop}= Check Loop Attributes ${tc.${path}} ${status} ${iterations} + IF ${not_run} + Should Be Equal ${loop.body[0].status} NOT RUN + END RETURN ${loop} -Check loop attributes +Check Loop Attributes [Arguments] ${loop} ${status} ${iterations} - Should be equal ${loop.type} WHILE - Should be equal ${loop.status} ${status} - Length Should Be ${loop.kws} ${iterations} + Should Be Equal ${loop.type} WHILE + Should Be Equal ${loop.status} ${status} + IF '${iterations}' != 'not known' + Length Should Be ${loop.non_messages} ${iterations} + END RETURN ${loop} diff --git a/atest/robot/running/while/while.robot b/atest/robot/running/while/while.robot index 91ff24732f1..76580a70e04 100644 --- a/atest/robot/running/while/while.robot +++ b/atest/robot/running/while/while.robot @@ -5,7 +5,7 @@ Suite Setup Run Tests ${EMPTY} running/while/while.robot *** Test Cases *** Loop executed once ${loop}= Check While Loop PASS 1 - Check Log Message ${loop.body[0].body[0].msgs[0]} 1 + Check Log Message ${loop[0, 0, 0]} 1 Loop executed multiple times Check While Loop PASS 5 @@ -17,12 +17,24 @@ Loop not executed Should Be Equal ${item.status} NOT RUN END +No Condition + Check While Loop PASS 5 + Execution fails on the first loop Check While Loop FAIL 1 Execution fails after some loops Check While Loop FAIL 3 +Continuable failure in loop + Check While Loop FAIL 3 + +Normal failure after continuable failure in loop + Check While Loop FAIL 2 + +Normal failure outside loop after continuable failures in loop + Check While Loop FAIL 2 + Loop in loop Check While Loop PASS 5 Check While Loop PASS 3 path=body[0].body[0].body[2] @@ -35,3 +47,8 @@ Loop fails in keyword With RETURN Check While Loop PASS 1 path=body[0].body[0] + +Condition evaluation time is included in elapsed time + ${loop} = Check WHILE loop PASS 1 + Elapsed Time Should Be Valid ${loop.elapsed_time} minimum=0.2 + Elapsed Time Should Be Valid ${loop.body[0].elapsed_time} minimum=0.1 diff --git a/atest/robot/running/while/while_limit.robot b/atest/robot/running/while/while_limit.robot index e1d29da9799..22185673eee 100644 --- a/atest/robot/running/while/while_limit.robot +++ b/atest/robot/running/while/while_limit.robot @@ -4,40 +4,63 @@ Resource while.resource *** Test Cases *** Default limit is 10000 iterations - Check Test Case ${TESTNAME} + Check WHILE Loop FAIL 10000 Limit with iteration count - Check while loop FAIL 5 + Check WHILE Loop FAIL 5 -Limit with iteration count with spaces - ${tc}= Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].limit} 3 0 +Iteration count with 'times' suffix + Check WHILE Loop FAIL 3 -Limit with iteration count with underscore - ${tc}= Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].limit} 1_0 +Iteration count with 'x' suffix + Check WHILE Loop FAIL 4 + +Iteration count normalization + ${loop}= Check WHILE Loop PASS 1 body[0] + Should Be Equal ${loop.limit} 1_000 + ${loop}= Check WHILE Loop FAIL 30 body[1] + Should Be Equal ${loop.limit} 3 0 T i m e S Limit as timestr - Check Test Case ${TESTNAME} + Check WHILE Loop FAIL not known Limit from variable - Check Test Case ${TESTNAME} + Check WHILE Loop FAIL 11 Part of limit from variable - Check Test Case ${TESTNAME} + Check WHILE Loop FAIL not known Limit can be disabled - Check Test Case ${TESTNAME} + Check WHILE Loop PASS 10041 + +No condition with limit + Check WHILE Loop FAIL 2 + +Limit exceeds in teardown + Check WHILE Loop FAIL not known teardown.body[0] + +Limit exceeds after failures in teardown + Check WHILE Loop FAIL 2 teardown.body[0] + +Continue after limit in teardown + Check WHILE Loop PASS not known teardown.body[0] Invalid limit invalid suffix - Check Test Case ${TESTNAME} + Check WHILE Loop FAIL 1 not_run=True Invalid limit invalid value - Check Test Case ${TESTNAME} + Check WHILE Loop FAIL 1 not_run=True Invalid limit mistyped prefix - Check Test Case ${TESTNAME} + Check WHILE Loop FAIL 1 not_run=True + +Limit with non-existing variable + Check WHILE Loop FAIL 1 not_run=True + +Limit used multiple times + ${loop}= Check WHILE Loop FAIL 1 not_run=True + Should Be Equal ${loop.limit} 2 Invalid values after limit - ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.body[0].condition} $variable < 2, limit=-1x, invalid, values + ${loop}= Check WHILE Loop FAIL 1 not_run=True + Should Be Equal ${loop.condition} $variable < 2, limit=2, invalid diff --git a/atest/robot/standard_libraries/builtin/builtin_propertys.robot b/atest/robot/standard_libraries/builtin/builtin_propertys.robot new file mode 100644 index 00000000000..623baaf6a52 --- /dev/null +++ b/atest/robot/standard_libraries/builtin/builtin_propertys.robot @@ -0,0 +1,11 @@ +*** Settings *** +Resource atest_resource.robot + +*** Test Cases *** +Normal run + Run Tests ${EMPTY} standard_libraries/builtin/builtin_propertys.robot + Check Test Case Test propertys + +Dry-run + Run Tests --dryrun --variable DRYRUN:True standard_libraries/builtin/builtin_propertys.robot + Check Test Case Test propertys diff --git a/atest/robot/standard_libraries/builtin/call_method.robot b/atest/robot/standard_libraries/builtin/call_method.robot index e6980cf031a..b32218f47d5 100644 --- a/atest/robot/standard_libraries/builtin/call_method.robot +++ b/atest/robot/standard_libraries/builtin/call_method.robot @@ -1,25 +1,35 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/call_method.robot +Suite Setup Run Tests --loglevel DEBUG standard_libraries/builtin/call_method.robot Resource atest_resource.robot *** Test Cases *** Call Method - Check Test Case ${TEST NAME} + Check Test Case ${TEST NAME} Call Method Returns - Check Test Case ${TEST NAME} + Check Test Case ${TEST NAME} Called Method Fails - Check Test Case ${TEST NAME} + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} Calling method 'my_method' failed: Expected failure FAIL + ${error} = Catenate SEPARATOR=\n + ... RuntimeError: Expected failure + ... + ... The above exception was the direct cause of the following exception: + ... + ... RuntimeError: Calling method 'my_method' failed: Expected failure + Traceback Should Be ${tc[0, 1]} + ... standard_libraries/builtin/objects_for_call_method.py my_method raise RuntimeError('Expected failure') + ... error=${error} Call Method With Kwargs - Check Test Case ${TEST NAME} + Check Test Case ${TEST NAME} Equals in non-kwargs must be escaped - Check Test Case ${TEST NAME} + Check Test Case ${TEST NAME} Call Method From Module - Check Test Case ${TEST NAME} + Check Test Case ${TEST NAME} Call Non Existing Method - Check Test Case ${TEST NAME} + Check Test Case ${TEST NAME} diff --git a/atest/robot/standard_libraries/builtin/converter.robot b/atest/robot/standard_libraries/builtin/converter.robot index 632e676d759..4911659cec2 100644 --- a/atest/robot/standard_libraries/builtin/converter.robot +++ b/atest/robot/standard_libraries/builtin/converter.robot @@ -5,7 +5,7 @@ Resource atest_resource.robot *** Test Cases *** Convert To Integer ${tc}= Check Test Case ${TEST NAME} - Verify argument type message ${tc.kws[0].kws[0].msgs[0]} + Verify argument type message ${tc[0, 0, 0]} Convert To Integer With Base Check Test Case ${TEST NAME} @@ -18,19 +18,19 @@ Convert To Integer With Embedded Base Convert To Binary ${tc}= Check Test Case ${TEST NAME} - Verify argument type message ${tc.kws[0].kws[0].msgs[0]} + Verify argument type message ${tc[0, 0, 0]} Convert To Octal ${tc}= Check Test Case ${TEST NAME} - Verify argument type message ${tc.kws[0].kws[0].msgs[0]} + Verify argument type message ${tc[0, 0, 0]} Convert To Hex ${tc}= Check Test Case ${TEST NAME} - Verify argument type message ${tc.kws[0].kws[0].msgs[0]} + Verify argument type message ${tc[0, 0, 0]} Convert To Number ${tc}= Check Test Case ${TEST NAME} - Verify argument type message ${tc.kws[0].kws[0].msgs[0]} + Verify argument type message ${tc[0, 0, 0]} Convert To Number With Precision Check Test Case ${TEST NAME} @@ -40,11 +40,11 @@ Numeric conversions with long types Convert To String ${tc}= Check Test Case ${TEST NAME} - Verify argument type message ${tc.kws[0].msgs[0]} + Verify argument type message ${tc[0, 0]} Convert To Boolean ${tc}= Check Test Case ${TEST NAME} - Verify argument type message ${tc.kws[0].msgs[0]} + Verify argument type message ${tc[0, 0]} Create List Check Test Case ${TEST NAME} diff --git a/atest/robot/standard_libraries/builtin/count.robot b/atest/robot/standard_libraries/builtin/count.robot index 91acc6c8fe5..43122824093 100644 --- a/atest/robot/standard_libraries/builtin/count.robot +++ b/atest/robot/standard_libraries/builtin/count.robot @@ -6,24 +6,24 @@ Resource builtin_resource.robot Get Count [Documentation] Tested also by Should Contain X Times keyword that uses this intenally. ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Item found from container 2 times. - Check Log Message ${tc.kws[1].kws[0].msgs[0]} Item found from container 2 times. - Check Log Message ${tc.kws[2].kws[0].msgs[0]} Item found from container 1 time. - Check Log Message ${tc.kws[3].kws[0].msgs[0]} Item found from container 1 time. - Check Log Message ${tc.kws[4].kws[0].msgs[0]} Item found from container 50 times. - Check Log Message ${tc.kws[5].kws[0].msgs[0]} Item found from container 0 times. + Check Log Message ${tc[0, 0, 0]} Item found from container 2 times. + Check Log Message ${tc[1, 0, 0]} Item found from container 2 times. + Check Log Message ${tc[2, 0, 0]} Item found from container 1 time. + Check Log Message ${tc[3, 0, 0]} Item found from container 1 time. + Check Log Message ${tc[4, 0, 0]} Item found from container 50 times. + Check Log Message ${tc[5, 0, 0]} Item found from container 0 times. Should Contain X Times with strings ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Item found from container 2 times. - Check Log Message ${tc.kws[1].msgs[0]} Item found from container 1 time. - Check Log Message ${tc.kws[3].msgs[0]} Item found from container 0 times. + Check Log Message ${tc[0, 0]} Item found from container 2 times. + Check Log Message ${tc[1, 0]} Item found from container 1 time. + Check Log Message ${tc[3, 0]} Item found from container 0 times. Should Contain X Times with containers ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Item found from container 1 time. - Check Log Message ${tc.kws[1].msgs[0]} Item found from container 2 times. - Check Log Message ${tc.kws[3].msgs[0]} Item found from container 0 times. + Check Log Message ${tc[0, 0]} Item found from container 1 time. + Check Log Message ${tc[1, 0]} Item found from container 2 times. + Check Log Message ${tc[3, 0]} Item found from container 0 times. Should Contain X Times failing Check test case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/evaluate.robot b/atest/robot/standard_libraries/builtin/evaluate.robot index d43a7f03d7d..02696b60849 100644 --- a/atest/robot/standard_libraries/builtin/evaluate.robot +++ b/atest/robot/standard_libraries/builtin/evaluate.robot @@ -9,6 +9,9 @@ Resource atest_resource.robot Evaluate Check Test Case ${TESTNAME} +Custom additions to builtins are supported + Check Test Case ${TESTNAME} + Modules are imported automatically Check Test Case ${TESTNAME} @@ -36,6 +39,9 @@ Explicit modules can override builtins Explicit modules used in lambda Check Test Case ${TESTNAME} +Evaluation namespace is mutable + Check Test Case ${TESTNAME} + Custom namespace Check Test Case ${TESTNAME} @@ -108,5 +114,11 @@ Evaluate Nonstring Evaluate doesn't see module globals Check Test Case ${TESTNAME} +Automatic variables are seen in expression part of comprehensions only with Python 3.12+ + Check Test Case ${TESTNAME} + +Automatic variables are not seen inside lambdas + Check Test Case ${TESTNAME} + Evaluation errors can be caught Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/fail.robot b/atest/robot/standard_libraries/builtin/fail.robot index 5076fb2fe28..c78ede1bbe6 100644 --- a/atest/robot/standard_libraries/builtin/fail.robot +++ b/atest/robot/standard_libraries/builtin/fail.robot @@ -5,45 +5,51 @@ Resource atest_resource.robot *** Test Cases *** Fail ${tc}= Check Test Tags ${TESTNAME} force1 force2 - Length Should Be ${tc.kws[0].msgs} 1 + Length Should Be ${tc[0].body} 1 -Fail With Message +Fail with message ${tc}= Check Test Tags ${TESTNAME} force1 force2 - Length Should Be ${tc.kws[0].msgs} 1 + Length Should Be ${tc[0].body} 1 + +Fail with non-string message + Check Test Case ${TESTNAME} + +Fail with non-true message having non-empty string representation + Check Test Case ${TESTNAME} Set one tag ${tc}= Check Test Tags ${TESTNAME} force1 force2 tag - Length Should Be ${tc.kws[0].msgs} 2 - Check Log Message ${tc.kws[0].msgs[0]} Set tag 'tag'. + Length Should Be ${tc[0].body} 2 + Check Log Message ${tc[0, 0]} Set tag 'tag'. Set multiple tags ${tc}= Check Test Tags ${TESTNAME} force1 force2 tag1 tag2 - Length Should Be ${tc.kws[0].msgs} 2 - Check Log Message ${tc.kws[0].msgs[0]} Set tags 'tag1' and 'tag2'. + Length Should Be ${tc[0].body} 2 + Check Log Message ${tc[0, 0]} Set tags 'tag1' and 'tag2'. Remove one tag ${tc}= Check Test Tags ${TESTNAME} force2 - Length Should Be ${tc.kws[0].msgs} 2 - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'force1'. + Length Should Be ${tc[0].body} 2 + Check Log Message ${tc[0, 0]} Removed tag 'force1'. Remove multiple tags ${tc}= Check Test Tags ${TESTNAME} - Length Should Be ${tc.kws[0].msgs} 2 - Check Log Message ${tc.kws[0].msgs[0]} Removed tags 'force1' and 'force2'. + Length Should Be ${tc[0].body} 2 + Check Log Message ${tc[0, 0]} Removed tags 'force1' and 'force2'. Remove multiple tags with pattern ${tc}= Check Test Tags ${TESTNAME} - Length Should Be ${tc.kws[0].msgs} 2 - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'force?'. + Length Should Be ${tc[0].body} 2 + Check Log Message ${tc[0, 0]} Removed tag 'force?'. Set and remove tags ${tc}= Check Test Tags ${TESTNAME} force2 tag1 tag2 - Length Should Be ${tc.kws[0].msgs} 3 - Check Log Message ${tc.kws[0].msgs[0]} Removed tags 'force1' and 'nonEx'. - Check Log Message ${tc.kws[0].msgs[1]} Set tags 'tag1' and 'tag2'. + Length Should Be ${tc[0].body} 3 + Check Log Message ${tc[0, 0]} Removed tags 'force1' and 'nonEx'. + Check Log Message ${tc[0, 1]} Set tags 'tag1' and 'tag2'. Set tags should not be removed ${tc}= Check Test Tags ${TESTNAME} fii foo - Length Should Be ${tc.kws[0].msgs} 3 - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'f*'. - Check Log Message ${tc.kws[0].msgs[1]} Set tags 'foo' and 'fii'. + Length Should Be ${tc[0].body} 3 + Check Log Message ${tc[0, 0]} Removed tag 'f*'. + Check Log Message ${tc[0, 1]} Set tags 'foo' and 'fii'. diff --git a/atest/robot/standard_libraries/builtin/fatal_error.robot b/atest/robot/standard_libraries/builtin/fatal_error.robot index a840ddb8f20..009dcd947f3 100644 --- a/atest/robot/standard_libraries/builtin/fatal_error.robot +++ b/atest/robot/standard_libraries/builtin/fatal_error.robot @@ -10,4 +10,4 @@ Subsequent tests are not executed after `Fatal Error` keyword has been used Check Test Case ${TESTNAME} Suite teardown is executed after `Fatal Error` keyword - Check Log Message ${SUITE.teardown.msgs[0]} AssertionError FAIL + Check Log Message ${SUITE.teardown[0]} AssertionError FAIL diff --git a/atest/robot/standard_libraries/builtin/keyword_should_exist.robot b/atest/robot/standard_libraries/builtin/keyword_should_exist.robot index 481c5491150..1cd444746e5 100644 --- a/atest/robot/standard_libraries/builtin/keyword_should_exist.robot +++ b/atest/robot/standard_libraries/builtin/keyword_should_exist.robot @@ -31,6 +31,9 @@ Keyword does not exist Keyword does not exist with custom message Check Test Case ${TESTNAME} +Recommendations not shown if keyword does not exist + Check Test Case ${TESTNAME} + Duplicate keywords Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/length.robot b/atest/robot/standard_libraries/builtin/length.robot index ce90b08a30c..7825b0c8ff7 100644 --- a/atest/robot/standard_libraries/builtin/length.robot +++ b/atest/robot/standard_libraries/builtin/length.robot @@ -5,19 +5,19 @@ Resource builtin_resource.robot *** Test Cases *** Get Length ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Length is 0 - Check Log Message ${tc.kws[1].kws[0].msgs[0]} Length is 1 - Check Log Message ${tc.kws[2].kws[0].msgs[0]} Length is 2 - Check Log Message ${tc.kws[3].kws[0].msgs[0]} Length is 3 - Check Log Message ${tc.kws[4].kws[0].msgs[0]} Length is 11 - Check Log Message ${tc.kws[5].kws[0].msgs[0]} Length is 0 + Check Log Message ${tc[0, 0, 0]} Length is 0. + Check Log Message ${tc[1, 0, 0]} Length is 1. + Check Log Message ${tc[2, 0, 0]} Length is 2. + Check Log Message ${tc[3, 0, 0]} Length is 3. + Check Log Message ${tc[4, 0, 0]} Length is 11. + Check Log Message ${tc[5, 0, 0]} Length is 0. Length Should Be ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[-1].msgs[0]} Length is 2 - Check Log Message ${tc.kws[-1].msgs[1]} Length of '*' should be 3 but is 2. FAIL pattern=yep - Check Log Message ${tc.kws[-1].msgs[2]} Traceback* DEBUG pattern=yep - Length Should Be ${tc.kws[-1].msgs} 3 + Check Log Message ${tc[-1, 0]} Length is 2. + Check Log Message ${tc[-1, 1]} Length of '*' should be 3 but is 2. FAIL pattern=yep + Check Log Message ${tc[-1, 2]} Traceback* DEBUG pattern=yep + Length Should Be ${tc[-1].body} 3 Length Should Be with custom message Check Test Case ${TESTNAME} @@ -26,25 +26,25 @@ Length Should Be with invalid length Check Test Case ${TESTNAME} Should Be Empty - Check test case ${TESTNAME} 1 - Check test case ${TESTNAME} 2 - Check test case ${TESTNAME} 3 + Check Test Case ${TESTNAME} 1 + Check Test Case ${TESTNAME} 2 + Check Test Case ${TESTNAME} 3 Should Be Empty with custom message - Check test case ${TESTNAME} + Check Test Case ${TESTNAME} Should Not Be Empty - Check test case ${TESTNAME} 1 - Check test case ${TESTNAME} 2 + Check Test Case ${TESTNAME} 1 + Check Test Case ${TESTNAME} 2 Should Not Be Empty with custom message - Check test case ${TESTNAME} + Check Test Case ${TESTNAME} Getting length with `length` method - Check test case ${TESTNAME} + Check Test Case ${TESTNAME} Getting length with `size` method - Check test case ${TESTNAME} + Check Test Case ${TESTNAME} Getting length with `length` attribute - Check test case ${TESTNAME} + Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/log.robot b/atest/robot/standard_libraries/builtin/log.robot index 10ae859f4f1..d714149f292 100644 --- a/atest/robot/standard_libraries/builtin/log.robot +++ b/atest/robot/standard_libraries/builtin/log.robot @@ -8,182 +8,191 @@ ${HTML} Robot Framework *** Test Cases *** Log ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Hello, world! - Check Log Message ${tc.kws[1].msgs[0]} 42 - Check Log Message ${tc.kws[2].msgs[0]} None - Check Log Message ${tc.kws[3].msgs[0]} String presentation of MyObject + Check Log Message ${tc[0, 0]} Hello, world! + Check Log Message ${tc[1, 0]} 42 + Check Log Message ${tc[2, 0]} None + Check Log Message ${tc[3, 0]} String presentation of MyObject Log with different levels ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[1]} Log says: Hello from tests! INFO - Check Log Message ${tc.kws[1].msgs[1]} Trace level TRACE - Check Log Message ${tc.kws[2].msgs[1]} Debug level DEBUG - Check Log Message ${tc.kws[3].msgs[1]} Info level INFO - Check Log Message ${tc.kws[4].msgs[1]} Warn level WARN - Check Log Message ${tc.kws[5].msgs[1]} Error level ERROR - Check Log Message ${ERRORS[0]} Warn level WARN - Check Log Message ${ERRORS[1]} Error level ERROR - Length Should Be ${ERRORS} 4 # Two deprecation warnings from `repr`. + Check Log Message ${tc[0, 1]} Log says: Hello from tests! INFO + Check Log Message ${tc[1, 1]} Trace level TRACE + Check Log Message ${tc[2, 1]} Debug level DEBUG + Check Log Message ${tc[3, 1]} Info level INFO + Check Log Message ${tc[4, 1]} Warn level WARN + Check Log Message ${tc[5, 1]} Error level ERROR + Check Log Message ${ERRORS[0]} Warn level WARN + Check Log Message ${ERRORS[1]} Error level ERROR + Length Should Be ${ERRORS} 4 # Two deprecation warnings from `repr`. Invalid log level failure is catchable Check Test Case ${TEST NAME} HTML is escaped by default ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} not bold - Check Log Message ${tc.kws[1].msgs[0]} ${HTML} + Check Log Message ${tc[0, 0]} not bold + Check Log Message ${tc[1, 0]} ${HTML} HTML pseudo level ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} bold html=True - Check Log Message ${tc.kws[1].msgs[0]} ${HTML} html=True + Check Log Message ${tc[0, 0]} bold html=True + Check Log Message ${tc[1, 0]} ${HTML} html=True Explicit HTML ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} bold html=True - Check Log Message ${tc.kws[1].msgs[0]} ${HTML} DEBUG html=True - Check Log Message ${tc.kws[2].msgs[0]} ${HTML} DEBUG + Check Log Message ${tc[0, 0]} bold html=True + Check Log Message ${tc[1, 0]} ${HTML} DEBUG html=True + Check Log Message ${tc[2, 0]} ${HTML} DEBUG FAIL is not valid log level Check Test Case ${TEST NAME} Log also to console ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Hello, console! - Check Log Message ${tc.kws[1].msgs[0]} ${HTML} DEBUG html=True + Check Log Message ${tc[0, 0]} Hello, console! + Check Log Message ${tc[1, 0]} ${HTML} DEBUG html=True Stdout Should Contain Hello, console!\n Stdout Should Contain ${HTML}\n +CONSOLE pseudo level + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} Hello, info and console! + Stdout Should Contain Hello, info and console!\n + repr=True ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} The 'repr' argument of 'BuiltIn.Log' is deprecated. Use 'formatter=repr' instead. WARN - Check Log Message ${tc.kws[0].msgs[1]} Nothing special here - Check Log Message ${tc.kws[1].msgs[0]} The 'repr' argument of 'BuiltIn.Log' is deprecated. Use 'formatter=repr' instead. WARN - Check Log Message ${tc.kws[1].msgs[1]} 'Hyvää yötä ☃!' + Check Log Message ${tc[0, 0]} The 'repr' argument of 'BuiltIn.Log' is deprecated. Use 'formatter=repr' instead. WARN + Check Log Message ${tc[0, 1]} Nothing special here + Check Log Message ${tc[1, 0]} The 'repr' argument of 'BuiltIn.Log' is deprecated. Use 'formatter=repr' instead. WARN + Check Log Message ${tc[1, 1]} 'Hyvää yötä ☃!' formatter=repr ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} 'Nothing special here' - Check Log Message ${tc.kws[1].msgs[0]} 'Hyvää yötä ☃!' - Check Log Message ${tc.kws[2].msgs[0]} 42 DEBUG - Check Log Message ${tc.kws[4].msgs[0]} b'\\x00abc\\xff (formatter=repr)' - Check Log Message ${tc.kws[6].msgs[0]} 'hyvä' + Check Log Message ${tc[0, 0]} 'Nothing special here' + Check Log Message ${tc[1, 0]} 'Hyvää yötä ☃!' + Check Log Message ${tc[2, 0]} 42 DEBUG + Check Log Message ${tc[4, 0]} b'\\x00abc\\xff (formatter=repr)' + Check Log Message ${tc[6, 0]} 'hyvä' Stdout Should Contain b'\\x00abc\\xff (formatter=repr)' formatter=ascii ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} 'Nothing special here' - Check Log Message ${tc.kws[1].msgs[0]} 'Hyv\\xe4\\xe4 y\\xf6t\\xe4 \\u2603!' - Check Log Message ${tc.kws[2].msgs[0]} 42 DEBUG - Check Log Message ${tc.kws[4].msgs[0]} b'\\x00abc\\xff (formatter=ascii)' - Check Log Message ${tc.kws[6].msgs[0]} 'hyva\\u0308' + Check Log Message ${tc[0, 0]} 'Nothing special here' + Check Log Message ${tc[1, 0]} 'Hyv\\xe4\\xe4 y\\xf6t\\xe4 \\u2603!' + Check Log Message ${tc[2, 0]} 42 DEBUG + Check Log Message ${tc[4, 0]} b'\\x00abc\\xff (formatter=ascii)' + Check Log Message ${tc[6, 0]} 'hyva\\u0308' Stdout Should Contain b'\\x00abc\\xff (formatter=ascii)' formatter=str ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Nothing special here - Check Log Message ${tc.kws[1].msgs[0]} Hyvää yötä ☃! - Check Log Message ${tc.kws[2].msgs[0]} 42 DEBUG - Check Log Message ${tc.kws[4].msgs[0]} abc\\xff (formatter=str) - Check Log Message ${tc.kws[6].msgs[0]} hyvä - Stdout Should Contain abc\\xff (formatter=str) + Check Log Message ${tc[0, 0]} Nothing special here + Check Log Message ${tc[1, 0]} Hyvää yötä ☃! + Check Log Message ${tc[2, 0]} 42 DEBUG + Check Log Message ${tc[4, 0]} abc\xff (formatter=str) + Check Log Message ${tc[6, 0]} hyvä + Stdout Should Contain abc\xff (formatter=str) formatter=repr pretty prints ${tc} = Check Test Case ${TEST NAME} ${long string} = Evaluate ' '.join(['Robot Framework'] * 1000) - ${small dict} = Set Variable {3: b'items', 'a': 'sorted', 'small': 'dict'} + ${small dict} = Set Variable {'small': 'dict', 3: b'items', 'NOT': 'sorted'} ${small list} = Set Variable ['small', b'list', 'not sorted', 4] - Check Log Message ${tc.kws[1].msgs[0]} '${long string}' - Check Log Message ${tc.kws[3].msgs[0]} ${small dict} - Check Log Message ${tc.kws[5].msgs[0]} {'big': 'dict',\n\ 'list': [1, 2, 3],\n\ 'long': '${long string}',\n\ 'nested': ${small dict}} - Check Log Message ${tc.kws[7].msgs[0]} ${small list} - Check Log Message ${tc.kws[9].msgs[0]} ['big',\n\ 'list',\n\ '${long string}',\n\ b'${long string}',\n\ ['nested', ('tuple', 2)],\n\ ${small dict}] - Check Log Message ${tc.kws[11].msgs[0]} ['hyvä', b'hyv\\xe4', {'☃': b'\\x00\\xff'}] + Check Log Message ${tc[1, 0]} '${long string}' + Check Log Message ${tc[3, 0]} ${small dict} + Check Log Message ${tc[5, 0]} {'big': 'dict',\n 'long': '${long string}',\n 'nested': ${small dict},\n 'list': [1, 2, 3],\n 'sorted': False} + Check Log Message ${tc[7, 0]} ${small list} + Check Log Message ${tc[9, 0]} ['big',\n 'list',\n '${long string}',\n b'${long string}',\n ['nested', ('tuple', 2)],\n ${small dict}] + Check Log Message ${tc[11, 0]} ['hyvä', b'hyv\\xe4', {'☃': b'\\x00\\xff'}] Stdout Should Contain ${small dict} Stdout Should Contain ${small list} formatter=len ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} 20 - Check Log Message ${tc.kws[1].msgs[0]} 13 DEBUG - Check Log Message ${tc.kws[3].msgs[0]} 21 - Check Log Message ${tc.kws[5].msgs[0]} 5 + Check Log Message ${tc[0, 0]} 20 + Check Log Message ${tc[1, 0]} 13 DEBUG + Check Log Message ${tc[3, 0]} 21 + Check Log Message ${tc[5, 0]} 5 formatter=type ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} str - Check Log Message ${tc.kws[1].msgs[0]} str - Check Log Message ${tc.kws[2].msgs[0]} int DEBUG - Check Log Message ${tc.kws[4].msgs[0]} bytes - Check Log Message ${tc.kws[6].msgs[0]} datetime + Check Log Message ${tc[0, 0]} str + Check Log Message ${tc[1, 0]} str + Check Log Message ${tc[2, 0]} int DEBUG + Check Log Message ${tc[4, 0]} bytes + Check Log Message ${tc[6, 0]} datetime formatter=invalid Check Test Case ${TEST NAME} Log callable ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} *objects_for_call_method.MyObject* pattern=yes - Check Log Message ${tc.kws[2].msgs[0]} at *> pattern=yes + Check Log Message ${tc[0, 0]} *objects_for_call_method.MyObject* pattern=yes + Check Log Message ${tc[2, 0]} at *> pattern=yes Log Many ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Log Many says: - Check Log Message ${tc.kws[0].msgs[1]} 1 - Check Log Message ${tc.kws[0].msgs[2]} 2 - Check Log Message ${tc.kws[0].msgs[3]} 3 - Check Log Message ${tc.kws[0].msgs[4]} String presentation of MyObject - Check Log Message ${tc.kws[1].msgs[0]} Log Many says: Hi!! - Check Log Message ${tc.kws[2].msgs[0]} 1 - Check Log Message ${tc.kws[2].msgs[1]} 2 - Check Log Message ${tc.kws[2].msgs[2]} 3 - Check Log Message ${tc.kws[2].msgs[3]} String presentation of MyObject - Should Be Empty ${tc.kws[3].msgs} - Should Be Empty ${tc.kws[4].msgs} - Check Log Message ${tc.kws[5].msgs[0]} -- - Check Log Message ${tc.kws[5].msgs[1]} -[]- - Check Log Message ${tc.kws[5].msgs[2]} -{}- - Check Log Message ${tc.kws[6].msgs[0]} 1 - Check Log Message ${tc.kws[6].msgs[1]} 2 + Check Log Message ${tc[0, 0]} Log Many says: + Check Log Message ${tc[0, 1]} 1 + Check Log Message ${tc[0, 2]} 2 + Check Log Message ${tc[0, 3]} 3 + Check Log Message ${tc[0, 4]} String presentation of MyObject + Check Log Message ${tc[1, 0]} Log Many says: Hi!! + Check Log Message ${tc[2, 0]} 1 + Check Log Message ${tc[2, 1]} 2 + Check Log Message ${tc[2, 2]} 3 + Check Log Message ${tc[2, 3]} String presentation of MyObject + Should Be Empty ${tc[3].body} + Should Be Empty ${tc[4].body} + Check Log Message ${tc[5, 0]} preserve + Check Log Message ${tc[5, 1]} ${EMPTY} + Check Log Message ${tc[5, 2]} empty + Check Log Message ${tc[5, 3]} ${EMPTY} + Check Log Message ${tc[6, 0]} -- + Check Log Message ${tc[6, 1]} -[]- + Check Log Message ${tc[6, 2]} -{}- + Check Log Message ${tc[7, 0]} 1 + Check Log Message ${tc[7, 1]} 2 Log Many with named and dict arguments ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} a=1 - Check Log Message ${tc.kws[0].msgs[1]} b=2 - Check Log Message ${tc.kws[0].msgs[2]} 3=c - Check Log Message ${tc.kws[0].msgs[3]} obj=String presentation of MyObject - Check Log Message ${tc.kws[1].msgs[0]} a=1 - Check Log Message ${tc.kws[1].msgs[1]} b=2 - Check Log Message ${tc.kws[1].msgs[2]} 3=c - Check Log Message ${tc.kws[1].msgs[3]} obj=String presentation of MyObject - Check Log Message ${tc.kws[2].msgs[0]} a=1 - Check Log Message ${tc.kws[2].msgs[1]} b=2 - Check Log Message ${tc.kws[2].msgs[2]} 3=c - Check Log Message ${tc.kws[2].msgs[3]} obj=String presentation of MyObject - Check Log Message ${tc.kws[2].msgs[4]} b=no override - Check Log Message ${tc.kws[2].msgs[5]} 3=three + Check Log Message ${tc[0, 0]} a=1 + Check Log Message ${tc[0, 1]} b=2 + Check Log Message ${tc[0, 2]} 3=c + Check Log Message ${tc[0, 3]} obj=String presentation of MyObject + Check Log Message ${tc[1, 0]} a=1 + Check Log Message ${tc[1, 1]} b=2 + Check Log Message ${tc[1, 2]} 3=c + Check Log Message ${tc[1, 3]} obj=String presentation of MyObject + Check Log Message ${tc[2, 0]} a=1 + Check Log Message ${tc[2, 1]} b=2 + Check Log Message ${tc[2, 2]} 3=c + Check Log Message ${tc[2, 3]} obj=String presentation of MyObject + Check Log Message ${tc[2, 4]} b=no override + Check Log Message ${tc[2, 5]} 3=three Log Many with positional, named and dict arguments ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} 1 - Check Log Message ${tc.kws[0].msgs[1]} 2 - Check Log Message ${tc.kws[0].msgs[2]} three=3 - Check Log Message ${tc.kws[0].msgs[3]} 4=four - Check Log Message ${tc.kws[1].msgs[0]} 1 - Check Log Message ${tc.kws[1].msgs[1]} 2 - Check Log Message ${tc.kws[1].msgs[2]} 3 - Check Log Message ${tc.kws[1].msgs[3]} String presentation of MyObject - Check Log Message ${tc.kws[1].msgs[4]} a=1 - Check Log Message ${tc.kws[1].msgs[5]} b=2 - Check Log Message ${tc.kws[1].msgs[6]} 3=c - Check Log Message ${tc.kws[1].msgs[7]} obj=String presentation of MyObject - Check Log Message ${tc.kws[1].msgs[8]} 1 - Check Log Message ${tc.kws[1].msgs[9]} 2 - Check Log Message ${tc.kws[1].msgs[10]} 3 - Check Log Message ${tc.kws[1].msgs[11]} String presentation of MyObject - Check Log Message ${tc.kws[1].msgs[12]} a=1 - Check Log Message ${tc.kws[1].msgs[13]} b=2 - Check Log Message ${tc.kws[1].msgs[14]} 3=c - Check Log Message ${tc.kws[1].msgs[15]} obj=String presentation of MyObject + Check Log Message ${tc[0, 0]} 1 + Check Log Message ${tc[0, 1]} 2 + Check Log Message ${tc[0, 2]} three=3 + Check Log Message ${tc[0, 3]} 4=four + Check Log Message ${tc[1, 0]} 1 + Check Log Message ${tc[1, 1]} 2 + Check Log Message ${tc[1, 2]} 3 + Check Log Message ${tc[1, 3]} String presentation of MyObject + Check Log Message ${tc[1, 4]} a=1 + Check Log Message ${tc[1, 5]} b=2 + Check Log Message ${tc[1, 6]} 3=c + Check Log Message ${tc[1, 7]} obj=String presentation of MyObject + Check Log Message ${tc[1, 8]} 1 + Check Log Message ${tc[1, 9]} 2 + Check Log Message ${tc[1, 10]} 3 + Check Log Message ${tc[1, 11]} String presentation of MyObject + Check Log Message ${tc[1, 12]} a=1 + Check Log Message ${tc[1, 13]} b=2 + Check Log Message ${tc[1, 14]} 3=c + Check Log Message ${tc[1, 15]} obj=String presentation of MyObject Log Many with non-existing variable Check Test Case ${TEST NAME} @@ -197,7 +206,7 @@ Log Many with dict variable containing non-dict Log To Console ${tc} = Check Test Case ${TEST NAME} FOR ${i} IN RANGE 4 - Should Be Empty ${tc.kws[${i}].msgs} + Should Be Empty ${tc[${i}].body} END Stdout Should Contain stdout äö w/ newline\n Stdout Should Contain stdout äö w/o new......line äö diff --git a/atest/robot/standard_libraries/builtin/log_variables.robot b/atest/robot/standard_libraries/builtin/log_variables.robot index 5da8636f347..3d58d5affbb 100644 --- a/atest/robot/standard_libraries/builtin/log_variables.robot +++ b/atest/robot/standard_libraries/builtin/log_variables.robot @@ -5,7 +5,7 @@ Resource atest_resource.robot *** Test Cases *** Log Variables In Suite Setup - Set Test Variable ${KW} ${SUITE.setup.body[7]} + Set Test Variable ${KW} ${SUITE.setup[7]} Set Test Variable ${INDEX} ${0} Check Variable Message \${/} = * pattern=yes Check Variable Message \${:} = ${:} @@ -15,14 +15,16 @@ Log Variables In Suite Setup Check Variable Message \${cli_var_3} = CLI3 Check Variable Message \${DEBUG_FILE} = NONE Check Variable Message \&{DICT} = { key=value | two=2 } + Check Variable Message \${ENDLESS} = repeat('RF') Check Variable Message \${EXECDIR} = * pattern=yes Check Variable Message \${False} = * pattern=yes + Check Variable Message \${ITERABLE} = at 0x*> pattern=yes Check Variable Message \@{LIST} = [ Hello | world ] Check Variable Message \${LOG_FILE} = NONE Check Variable Message \${LOG_LEVEL} = INFO Check Variable Message \${None} = None Check Variable Message \${null} = None - Check Variable Message \&{OPTIONS} = { include=[] | exclude=[] | skip=[] | skip_on_failure=[] } + Check Variable Message \&{OPTIONS} = { rpa=False | include=[] | exclude=[] | skip=[] | skip_on_failure=[] | console_width=78 } Check Variable Message \${OUTPUT_DIR} = * pattern=yes Check Variable Message \${OUTPUT_FILE} = * pattern=yes Check Variable Message \${PREV_TEST_MESSAGE} = @@ -42,11 +44,11 @@ Log Variables In Suite Setup Check Variable Message \${SUITE_SOURCE} = * pattern=yes Check Variable Message \${TEMPDIR} = * pattern=yes Check Variable Message \${True} = * pattern=yes - Should Be Equal As Integers ${kw.message_count} 35 Wrong total message count + Length Should Be ${kw.messages} 37 Log Variables In Test ${test} = Check Test Case Log Variables - Set Test Variable ${KW} ${test.body[0]} + Set Test Variable ${KW} ${test[0]} Set Test Variable ${INDEX} ${1} Check Variable Message \${/} = * pattern=yes Check Variable Message \${:} = ${:} @@ -56,14 +58,16 @@ Log Variables In Test Check Variable Message \${cli_var_3} = CLI3 Check Variable Message \${DEBUG_FILE} = NONE Check Variable Message \&{DICT} = { key=value | two=2 } + Check Variable Message \${ENDLESS} = repeat('RF') Check Variable Message \${EXECDIR} = * pattern=yes Check Variable Message \${False} = * pattern=yes + Check Variable Message \${ITERABLE} = at 0x*> pattern=yes Check Variable Message \@{LIST} = [ Hello | world ] Check Variable Message \${LOG_FILE} = NONE Check Variable Message \${LOG_LEVEL} = TRACE Check Variable Message \${None} = None Check Variable Message \${null} = None - Check Variable Message \&{OPTIONS} = { include=[] | exclude=[] | skip=[] | skip_on_failure=[] } + Check Variable Message \&{OPTIONS} = { rpa=False | include=[] | exclude=[] | skip=[] | skip_on_failure=[] | console_width=78 } Check Variable Message \${OUTPUT_DIR} = * pattern=yes Check Variable Message \${OUTPUT_FILE} = * pattern=yes Check Variable Message \${PREV_TEST_MESSAGE} = @@ -85,11 +89,11 @@ Log Variables In Test Check Variable Message \${TEST_NAME} = Log Variables Check Variable Message \@{TEST_TAGS} = [ ] Check Variable Message \${True} = * pattern=yes - Should Be Equal As Integers ${kw.message_count} 39 Wrong total message count + Length Should Be ${kw.messages} 41 Log Variables After Setting New Variables ${test} = Check Test Case Log Variables - Set Test Variable ${KW} ${test.body[4]} + Set Test Variable ${KW} ${test[4]} Set Test Variable ${INDEX} ${1} Check Variable Message \${/} = * DEBUG pattern=yes Check Variable Message \${:} = ${:} DEBUG @@ -99,16 +103,18 @@ Log Variables After Setting New Variables Check Variable Message \${cli_var_3} = CLI3 DEBUG Check Variable Message \${DEBUG_FILE} = NONE DEBUG Check Variable Message \&{DICT} = { key=value | two=2 } DEBUG + Check Variable Message \${ENDLESS} = repeat('RF') DEBUG Check Variable Message \${EXECDIR} = * DEBUG pattern=yes Check Variable Message \${False} = * DEBUG pattern=yes Check Variable Message \@{int_list_1} = [ 0 | 1 | 2 | 3 ] DEBUG Check Variable Message \@{int_list_2} = [ 0 | 1 | 2 | 3 ] DEBUG + Check Variable Message \${ITERABLE} = at 0x*> DEBUG pattern=yes Check Variable Message \@{LIST} = [ Hello | world ] DEBUG Check Variable Message \${LOG_FILE} = NONE DEBUG Check Variable Message \${LOG_LEVEL} = TRACE DEBUG Check Variable Message \${None} = None DEBUG Check Variable Message \${null} = None DEBUG - Check Variable Message \&{OPTIONS} = { include=[] | exclude=[] | skip=[] | skip_on_failure=[] } DEBUG + Check Variable Message \&{OPTIONS} = { rpa=False | include=[] | exclude=[] | skip=[] | skip_on_failure=[] | console_width=78 } DEBUG Check Variable Message \${OUTPUT_DIR} = * DEBUG pattern=yes Check Variable Message \${OUTPUT_FILE} = * DEBUG pattern=yes Check Variable Message \${PREV_TEST_MESSAGE} = DEBUG @@ -131,11 +137,11 @@ Log Variables After Setting New Variables Check Variable Message \@{TEST_TAGS} = [ ] DEBUG Check Variable Message \${True} = * DEBUG pattern=yes Check Variable Message \${var} = Hello DEBUG - Should Be Equal As Integers ${kw.message_count} 42 Wrong total message count + Length Should Be ${kw.messages} 44 Log Variables In User Keyword ${test} = Check Test Case Log Variables - Set Test Variable ${KW} ${test.body[5].body[2]} + Set Test Variable ${KW} ${test[5, 2]} Set Test Variable ${INDEX} ${1} Check Variable Message \${/} = * pattern=yes Check Variable Message \${:} = ${:} @@ -145,14 +151,16 @@ Log Variables In User Keyword Check Variable Message \${cli_var_3} = CLI3 Check Variable Message \${DEBUG_FILE} = NONE Check Variable Message \&{DICT} = { key=value | two=2 } + Check Variable Message \${ENDLESS} = repeat('RF') Check Variable Message \${EXECDIR} = * pattern=yes Check Variable Message \${False} = * pattern=yes + Check Variable Message \${ITERABLE} = at 0x*> pattern=yes Check Variable Message \@{LIST} = [ Hello | world ] Check Variable Message \${LOG_FILE} = NONE Check Variable Message \${LOG_LEVEL} = TRACE Check Variable Message \${None} = None Check Variable Message \${null} = None - Check Variable Message \&{OPTIONS} = { include=[] | exclude=[] | skip=[] | skip_on_failure=[] } + Check Variable Message \&{OPTIONS} = { rpa=False | include=[] | exclude=[] | skip=[] | skip_on_failure=[] | console_width=78 } Check Variable Message \${OUTPUT_DIR} = * pattern=yes Check Variable Message \${OUTPUT_FILE} = * pattern=yes Check Variable Message \${PREV_TEST_MESSAGE} = @@ -175,7 +183,7 @@ Log Variables In User Keyword Check Variable Message \@{TEST_TAGS} = [ ] Check Variable Message \${True} = * pattern=yes Check Variable Message \${ukvar} = Value of an uk variable - Should Be Equal As Integers ${kw.message_count} 40 Wrong total message count + Length Should Be ${kw.messages} 42 List and dict variables failing during iteration Check Test Case ${TEST NAME} @@ -183,5 +191,5 @@ List and dict variables failing during iteration *** Keywords *** Check Variable Message [Arguments] ${expected} ${level}=INFO ${pattern}= - Check Log Message ${KW.msgs[${INDEX}]} ${expected} ${level} pattern=${pattern} + Check Log Message ${KW[${INDEX}]} ${expected} ${level} pattern=${pattern} Set Test Variable ${INDEX} ${INDEX + 1} diff --git a/atest/robot/standard_libraries/builtin/misc.robot b/atest/robot/standard_libraries/builtin/misc.robot index 38994c9afac..a7af9cba20c 100644 --- a/atest/robot/standard_libraries/builtin/misc.robot +++ b/atest/robot/standard_libraries/builtin/misc.robot @@ -11,9 +11,9 @@ Catenate Comment ${tc} = Check Test Case ${TEST NAME} - Should Be Empty ${tc.kws[0].msgs} - Should Be Empty ${tc.kws[1].msgs} - Should Be Empty ${tc.kws[2].msgs} + Should Be Empty ${tc[0].body} + Should Be Empty ${tc[1].body} + Should Be Empty ${tc[2].body} Regexp Escape Check Test Case ${TEST NAME} diff --git a/atest/robot/standard_libraries/builtin/reload_library.robot b/atest/robot/standard_libraries/builtin/reload_library.robot index 25cb84aad6a..97bf6e4d58e 100644 --- a/atest/robot/standard_libraries/builtin/reload_library.robot +++ b/atest/robot/standard_libraries/builtin/reload_library.robot @@ -5,12 +5,12 @@ Resource atest_resource.robot *** Test Cases *** Reload and add keyword ${tc}= Check Test Case ${TESTNAME} - Check log message ${tc.kws[2].msgs[0]} Reloaded library Reloadable with 7 keywords. + Check log message ${tc[2, 0]} Reloaded library Reloadable with 7 keywords. Reloading changes args ${tc}= Check Test Case ${TESTNAME} - Should be equal ${tc.kws[0].doc} Doc for original 1 with args arg - Should be equal ${tc.kws[3].doc} Doc for original 1 with args arg1, arg2 + Should be equal ${tc[0].doc} Doc for original 1 with args arg + Should be equal ${tc[3].doc} Doc for original 1 with args arg1, arg2 Reloading can remove a keyword Check Test Case ${TESTNAME} @@ -32,8 +32,8 @@ Reloading None fails Static library ${tc}= Check Test Case ${TESTNAME} - Should be equal ${tc.kws[2].doc} This doc for static + Should be equal ${tc[2].doc} This doc for static Module library ${tc}= Check Test Case ${TESTNAME} - Should be equal ${tc.kws[3].doc} This doc for module + Should be equal ${tc[3].doc} This doc for module diff --git a/atest/robot/standard_libraries/builtin/reload_with_name.robot b/atest/robot/standard_libraries/builtin/reload_with_name.robot index 7b04683ff74..dcabc6ea7f6 100644 --- a/atest/robot/standard_libraries/builtin/reload_with_name.robot +++ b/atest/robot/standard_libraries/builtin/reload_with_name.robot @@ -5,7 +5,7 @@ Resource atest_resource.robot *** Test Cases *** Reload with name ${tc}= Check Test Case ${TESTNAME} - Check log message ${tc.kws[1].msgs[0]} Reloaded library foo with 7 keywords. + Check log message ${tc[1, 0]} Reloaded library foo with 7 keywords. Reload with instance Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/repeat_keyword.robot b/atest/robot/standard_libraries/builtin/repeat_keyword.robot index c745e9c1b9d..b4cfbae94c2 100644 --- a/atest/robot/standard_libraries/builtin/repeat_keyword.robot +++ b/atest/robot/standard_libraries/builtin/repeat_keyword.robot @@ -5,27 +5,27 @@ Resource atest_resource.robot *** Test Cases *** Times As String ${tc} = Check Test Case ${TEST NAME} - Check Repeated Messages ${tc.kws[0]} 2 Hello, repeating world! + Check Repeated Messages ${tc[0]} 2 Hello, repeating world! Times As Integer ${tc} = Check Test Case ${TEST NAME} - Check Repeated Messages ${tc.kws[0]} 42 This works too!! + Check Repeated Messages ${tc[0]} 42 This works too!! Times With 'times' Postfix ${tc} = Check Test Case ${TEST NAME} - Check Repeated Messages ${tc.kws[0]} 3 This is done 3 times - Check Repeated Messages ${tc.kws[1]} 2 Case and space insensitive + Check Repeated Messages ${tc[0]} 3 This is done 3 times + Check Repeated Messages ${tc[1]} 2 Case and space insensitive Times With 'x' Postfix ${tc} = Check Test Case ${TEST NAME} - Check Repeated Messages ${tc.kws[0]} 10 Close to old repeating syntax - Check Repeated Messages ${tc.kws[1]} 1 Case and space + Check Repeated Messages ${tc[0]} 10 Close to old repeating syntax + Check Repeated Messages ${tc[1]} 1 Case and space Zero And Negative Times ${tc} = Check Test Case ${TEST NAME} - Check Repeated Messages ${tc.kws[0]} 0 - Check Repeated Messages ${tc.kws[2]} 0 - Check Repeated Messages ${tc.kws[3]} 0 + Check Repeated Messages ${tc[0]} 0 name=This is not executed + Check Repeated Messages ${tc[2]} 0 name=\${name} + Check Repeated Messages ${tc[3]} 0 name=This is not executed Invalid Times Check Test Case Invalid Times 1 @@ -33,16 +33,16 @@ Invalid Times Repeat Keyword With Time String ${tc} = Check Test Case ${TEST NAME} - Check Repeated Messages With Time ${tc.kws[0]} This is done for 00:00:00.003 - Check Repeated Messages With Time ${tc.kws[1]} This is done for 3 milliseconds - Check Repeated Messages With Time ${tc.kws[2]} This is done for 3ms + Check Repeated Messages With Time ${tc[0]} This is done for 00:00:00.003 + Check Repeated Messages With Time ${tc[1]} This is done for 3 milliseconds + Check Repeated Messages With Time ${tc[2]} This is done for 3ms Repeat Keyword Arguments As Variables ${tc} = Check Test Case ${TEST_NAME} - Check Repeated Keyword Name ${tc.kws[1]} 2 BuiltIn.Should Be Equal - Check Repeated Keyword Name ${tc.kws[3]} 42 BuiltIn.Should Be Equal - Check Repeated Keyword Name ${tc.kws[5]} 10 BuiltIn.No Operation - Check Repeated Keyword Name ${tc.kws[7]} 1 BuiltIn.Should Be Equal + Check Repeated Keyword Name ${tc[1]} 2 BuiltIn.Should Be Equal + Check Repeated Keyword Name ${tc[3]} 42 BuiltIn.Should Be Equal + Check Repeated Keyword Name ${tc[5]} 10 BuiltIn.No Operation + Check Repeated Keyword Name ${tc[7]} 1 BuiltIn.Should Be Equal Repeated Keyword As Non-existing Variable Check Test Case ${TEST_NAME} @@ -56,44 +56,52 @@ Repeated Keyword Failing Repeat Keyword With Continuable Failure ${tc} = Check Test Case ${TEST_NAME} - Length Should Be ${tc.kws[0].kws} 3 + Length Should Be ${tc[0].body} 6 + Length Should Be ${tc[0].messages} 3 Repeat Keyword With Failure After Continuable Failure ${tc} = Check Test Case ${TEST_NAME} - Length Should Be ${tc.kws[0].kws} 2 + Length Should Be ${tc[0].body} 4 + Length Should Be ${tc[0].messages} 2 Repeat Keyword With Pass Execution ${tc} = Check Test Case ${TEST_NAME} - Length Should Be ${tc.kws[0].kws} 1 + Length Should Be ${tc[0].body} 2 + Length Should Be ${tc[0].messages} 1 Repeat Keyword With Pass Execution After Continuable Failure ${tc} = Check Test Case ${TEST_NAME} - Length Should Be ${tc.kws[0].kws} 2 + Length Should Be ${tc[0].body} 4 + Length Should Be ${tc[0].messages} 2 *** Keywords *** Check Repeated Messages - [Arguments] ${kw} ${count} ${msg}=${None} - Should Be Equal As Integers ${kw.kw_count} ${count} - FOR ${i} IN RANGE ${count} - Check Log Message ${kw.msgs[${i}]} Repeating keyword, round ${i+1}/${count}. - Check Log Message ${kw.kws[${i}].msgs[0]} ${msg} + [Arguments] ${kw} ${rounds} ${msg}= ${name}= + IF ${rounds} == 0 + Length Should Be ${kw.body} 1 + Check Log Message ${kw[0]} Keyword '${name}' repeated zero times. + ELSE + Length Should Be ${kw.body} ${{int($rounds) * 2}} + Length Should Be ${kw.messages} ${rounds} + END + FOR ${i} IN RANGE ${rounds} + Check Log Message ${kw[${i * 2}]} Repeating keyword, round ${i+1}/${rounds}. + Check Log Message ${kw[${i * 2 + 1}, 0]} ${msg} END - Run Keyword If ${count} == 0 Check Log Message ${kw.msgs[0]} Keyword 'This is not executed' repeated zero times. - Run Keyword If ${count} != 0 Should Be Equal As Integers ${kw.msg_count} ${count} Check Repeated Messages With Time [Arguments] ${kw} ${msg}=${None} - Should Be True ${kw.kw_count} > 0 - FOR ${i} IN RANGE ${kw.kw_count} - Check Log Message ${kw.msgs[${i}]} + Should Be True len($kw.body) / 2 == len($kw.messages) and len($kw.body) > 0 + FOR ${i} IN RANGE ${{len($kw.messages)}} + Check Log Message ${kw[${i * 2}]} ... Repeating keyword, round ${i+1}, *remaining. pattern=yes - Check Log Message ${kw.kws[${i}].msgs[0]} ${msg} + Check Log Message ${kw[${i * 2 + 1}, 0]} ${msg} END - Should Be Equal As Integers ${kw.msg_count} ${kw.kw_count} + Should Be Equal ${{len($kw.messages) * 2}} ${{len($kw.body)}} Check Repeated Keyword Name [Arguments] ${kw} ${count} ${name}=${None} - Should Be Equal As Integers ${kw.kw_count} ${count} - FOR ${i} IN RANGE ${count} - Should Be Equal ${kw.kws[${i}].name} ${name} + Should Be True len($kw.body) / 2 == len($kw.messages) == ${count} + FOR ${i} IN RANGE 1 ${count} * 2 2 + Should Be Equal ${kw[${i}].full_name} ${name} END diff --git a/atest/robot/standard_libraries/builtin/replace_variables.robot b/atest/robot/standard_libraries/builtin/replace_variables.robot index 713bc7ff491..96c56e64235 100644 --- a/atest/robot/standard_libraries/builtin/replace_variables.robot +++ b/atest/robot/standard_libraries/builtin/replace_variables.robot @@ -1,8 +1,8 @@ -*** Setting *** +*** Settings *** Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/replace_variables.robot Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Replace Variables Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/run_keyword.robot b/atest/robot/standard_libraries/builtin/run_keyword.robot index 574fdaa98e6..faa8580d011 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword.robot @@ -4,52 +4,80 @@ Resource atest_resource.robot *** Test Cases *** Run Keyword - ${tc} = Check test Case ${TEST NAME} - Check Run Keyword ${tc.kws[0]} BuiltIn.Log This is logged with Run Keyword - Check Keyword Data ${tc.kws[1].kws[0]} BuiltIn.No Operation - Check Run Keyword ${tc.kws[2]} BuiltIn.Log Many 1 2 3 4 5 - Check Run Keyword ${tc.kws[4]} BuiltIn.Log Run keyword with variable: Log - Check Run Keyword ${tc.kws[6]} BuiltIn.Log Many one two + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword ${tc[0]} BuiltIn.Log This is logged with Run Keyword + Check Keyword Data ${tc[1, 0]} BuiltIn.No Operation + Check Run Keyword ${tc[2]} BuiltIn.Log Many 1 2 3 4 5 + Check Run Keyword ${tc[4]} BuiltIn.Log Run keyword with variable: Log + Check Run Keyword ${tc[6]} BuiltIn.Log Many one two Run Keyword Returning Value - ${tc} = Check test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} BuiltIn.Run Keyword \${ret} Set Variable, hello world - Check Keyword Data ${tc.kws[0].kws[0]} BuiltIn.Set Variable args=hello world - Check Keyword Data ${tc.kws[2]} BuiltIn.Run Keyword \${ret} Evaluate, 1+2 - Check Keyword Data ${tc.kws[2].kws[0]} BuiltIn.Evaluate args=1+2 + ${tc} = Check Test Case ${TEST NAME} + Check Keyword Data ${tc[0]} BuiltIn.Run Keyword \${ret} Set Variable, hello world + Check Keyword Data ${tc[0, 0]} BuiltIn.Set Variable args=hello world + Check Keyword Data ${tc[2]} BuiltIn.Run Keyword \${ret} Evaluate, 1+2 + Check Keyword Data ${tc[2, 0]} BuiltIn.Evaluate args=1+2 Run Keyword With Arguments That Needs To Be Escaped - ${tc} = Check test Case ${TEST NAME} - Check Log Message ${tc.kws[1].kws[0].msgs[0]} c:\\temp\\foo - Check Log Message ${tc.kws[1].kws[0].msgs[1]} \${notvar} + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[1, 0, 0]} c:\\temp\\foo + Check Log Message ${tc[1, 0, 1]} \${notvar} Escaping Arguments From Opened List Variable - ${tc} = Check test Case ${TEST NAME} - Check Log Message ${tc.kws[1].kws[0].msgs[0]} message=foo - Check Log Message ${tc.kws[3].kws[0].msgs[0]} 42 + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[1, 0, 0]} message=foo + Check Log Message ${tc[3, 0, 0]} 42 Run Keyword With UK - ${tc} = Check test Case ${TEST NAME} - Check Run Keyword In UK ${tc.kws[0]} BuiltIn.Log Using UK - Check Run Keyword In UK ${tc.kws[1]} BuiltIn.Log Many yksi kaksi + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword In UK ${tc[0]} BuiltIn.Log Using UK + Check Run Keyword In UK ${tc[1]} BuiltIn.Log Many yksi kaksi Run Keyword In Multiple Levels And With UK - Check test Case ${TEST NAME} + Check Test Case ${TEST NAME} + +With keyword accepting embedded arguments + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword With Embedded Args ${tc[0]} Embedded "arg" arg + +With library keyword accepting embedded arguments + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword With Embedded Args ${tc[0]} Embedded "arg" in library arg + +With keyword accepting embedded arguments as variables + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword With Embedded Args ${tc[0]} Embedded "\${VARIABLE}" value + Check Run Keyword With Embedded Args ${tc[1]} Embedded "\${1}" 1 + +With library keyword accepting embedded arguments as variables + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword With Embedded Args ${tc[0]} Embedded "\${VARIABLE}" in library value + Check Run Keyword With Embedded Args ${tc[1]} Embedded "\${1}" in library 1 + +With keyword accepting embedded arguments as variables containing objects + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword With Embedded Args ${tc[0]} Embedded "\${OBJECT}" Robot + Check Run Keyword With Embedded Args ${tc[1]} Embedded object "\${OBJECT}" Robot + +With library keyword accepting embedded arguments as variables containing objects + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword With Embedded Args ${tc[0]} Embedded "\${OBJECT}" in library Robot + Check Run Keyword With Embedded Args ${tc[1]} Embedded object "\${OBJECT}" in library Robot Run Keyword In For Loop - ${tc} = Check test Case ${TEST NAME} - Check Run Keyword ${tc.kws[0].kws[0].kws[0]} BuiltIn.Log hello from for loop - Check Run Keyword In UK ${tc.kws[0].kws[2].kws[0]} BuiltIn.Log hei maailma - Check Run Keyword ${tc.kws[1].kws[0].kws[0]} BuiltIn.Log hello from second for loop + ${tc} = Check Test Case ${TEST NAME} + Check Run Keyword ${tc[0, 0, 0]} BuiltIn.Log hello from for loop + Check Run Keyword In UK ${tc[0, 2, 0]} BuiltIn.Log hei maailma + Check Run Keyword ${tc[1, 0, 0]} BuiltIn.Log hello from second for loop Run Keyword With Test Timeout Check Test Case ${TEST NAME} Passing ${tc} = Check Test Case ${TEST NAME} Exceeded - Check Run Keyword ${tc.kws[0]} BuiltIn.Log Before Timeout + Check Run Keyword ${tc[0]} BuiltIn.Log Before Timeout Run Keyword With KW Timeout - Check test Case ${TEST NAME} Passing - Check test Case ${TEST NAME} Exceeded + Check Test Case ${TEST NAME} Passing + Check Test Case ${TEST NAME} Exceeded Run Keyword With Invalid Keyword Name Check Test Case ${TEST NAME} @@ -69,15 +97,27 @@ Stdout and stderr are not captured when running Run Keyword *** Keywords *** Check Run Keyword - [Arguments] ${kw} ${subkw_name} @{msgs} - Should Be Equal ${kw.name} BuiltIn.Run Keyword - Should Be Equal ${kw.kws[0].name} ${subkw_name} + [Arguments] ${kw} ${name} @{msgs} + Should Be Equal ${kw.full_name} BuiltIn.Run Keyword + Should Be Equal ${kw[0].full_name} ${name} FOR ${index} ${msg} IN ENUMERATE @{msgs} - Check Log Message ${kw.kws[0].msgs[${index}]} ${msg} + Check Log Message ${kw[0, ${index}]} ${msg} END Check Run Keyword In Uk [Arguments] ${kw} ${subkw_name} @{msgs} - Should Be Equal ${kw.name} BuiltIn.Run Keyword - Should Be Equal ${kw.kws[0].name} My UK - Check Run Keyword ${kw.kws[0].kws[0]} ${subkw_name} @{msgs} + Should Be Equal ${kw.full_name} BuiltIn.Run Keyword + Should Be Equal ${kw[0].full_name} My UK + Check Run Keyword ${kw[0, 0]} ${subkw_name} @{msgs} + +Check Run Keyword With Embedded Args + [Arguments] ${kw} ${subkw_name} ${msg} + Should Be Equal ${kw.full_name} BuiltIn.Run Keyword + IF ${subkw_name.endswith('library')} + Should Be Equal ${kw[0].full_name} embedded_args.${subkw_name} + Check Log Message ${kw[0, 0]} ${msg} + ELSE + Should Be Equal ${kw[0].full_name} ${subkw_name} + Should Be Equal ${kw[0, 0].full_name} BuiltIn.Log + Check Log Message ${kw[0, 0, 0]} ${msg} + END diff --git a/atest/robot/standard_libraries/builtin/run_keyword_and_continue_on_failure.robot b/atest/robot/standard_libraries/builtin/run_keyword_and_continue_on_failure.robot index 3f83802c905..2af70af225d 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_and_continue_on_failure.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_and_continue_on_failure.robot @@ -5,16 +5,16 @@ Resource atest_resource.robot *** Test Cases *** Run Keyword And Continue On Failure ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Expected Failure FAIL - Check Log Message ${tc.kws[1].kws[0].msgs[0]} Expected Failure 2 FAIL - Check Log Message ${tc.kws[2].msgs[0]} This should be executed + Check Log Message ${tc[0, 0, 0]} Expected Failure FAIL + Check Log Message ${tc[1, 0, 0]} Expected Failure 2 FAIL + Check Log Message ${tc[2, 0]} This should be executed Run Keyword And Continue On Failure In For Loop Check Test Case ${TESTNAME} Run User keyword And Continue On Failure ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[1].msgs[0]} This should be executed + Check Log Message ${tc[1, 0]} This should be executed Run Keyword And Continue On Failure With For Loops Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/run_keyword_and_return.robot b/atest/robot/standard_libraries/builtin/run_keyword_and_return.robot index b0fbeccc939..9e345446a7f 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_and_return.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_and_return.robot @@ -5,15 +5,15 @@ Resource atest_resource.robot *** Test Cases *** Return one value ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.kws[0].kws[0].msgs[0]} Returning from the enclosing user keyword. + Check Log Message ${tc[0, 0, 1]} Returning from the enclosing user keyword. Return multiple values Check Test Case ${TESTNAME} Return nothing ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.kws[0].kws[0].kws[0].msgs[0]} No return value - Check log message ${tc.kws[0].kws[0].msgs[0]} Returning from the enclosing user keyword. + Check Log Message ${tc[0, 0, 0, 0]} No return value + Check Log Message ${tc[0, 0, 1]} Returning from the enclosing user keyword. Nested usage Check Test Case ${TESTNAME} @@ -23,13 +23,13 @@ Keyword fails Inside Run Keyword variants ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.kws[2].kws[0].kws[0].msgs[0]} First keyword - Check log message ${tc.kws[2].kws[0].kws[2].msgs[0]} Returning from the enclosing user keyword. + Check Log Message ${tc[2, 0, 0, 0]} First keyword + Check Log Message ${tc[2, 0, 2, 1]} Returning from the enclosing user keyword. Using Run Keyword variants ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.kws[2].kws[0].kws[0].kws[1].msgs[0]} Second keyword - Check log message ${tc.kws[2].kws[0].kws[0].kws[2].msgs[0]} Returning from the enclosing user keyword. + Check Log Message ${tc[2, 0, 0, 1, 0]} Second keyword + Check Log Message ${tc[2, 0, 0, 2, 1]} Returning from the enclosing user keyword. Outside user keyword Check Test Case ${TESTNAME} @@ -42,9 +42,9 @@ Return strings that needs to be escaped Run Keyword And Return If ${tc} = Check Test Case ${TESTNAME} - Check log message ${tc.kws[0].kws[1].msgs[0]} Returning from the enclosing user keyword. - Check log message ${tc.kws[2].kws[1].msgs[0]} Returning from the enclosing user keyword. - Check log message ${tc.kws[4].kws[0].kws[2].kws[0].msgs[0]} Returning from the enclosing user keyword. + Check Log Message ${tc[0, 1, 1]} Returning from the enclosing user keyword. + Check Log Message ${tc[2, 1, 1]} Returning from the enclosing user keyword. + Check Log Message ${tc[4, 0, 2, 0, 1]} Returning from the enclosing user keyword. Run Keyword And Return If can have non-existing keywords and variables if condition is not true Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/run_keyword_and_warn_on_failure.robot b/atest/robot/standard_libraries/builtin/run_keyword_and_warn_on_failure.robot index 721feb89810..442c10ac1c5 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_and_warn_on_failure.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_and_warn_on_failure.robot @@ -5,16 +5,16 @@ Resource atest_resource.robot *** Test Cases *** Run Keyword And Warn On Failure ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Executing keyword 'FAIL' failed:\nExpected Warn WARN + Check Log Message ${tc[0, 1]} Executing keyword 'FAIL' failed:\nExpected Warn WARN Run Keyword And Warn On Failure For Keyword Teardown ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} + Check Log Message ${tc[0, 1]} ... Executing keyword 'Failing Keyword Teardown' failed:\nKeyword teardown failed:\nExpected WARN Run User keyword And Warn On Failure ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} + Check Log Message ${tc[0, 1]} ... Executing keyword 'Exception In User Defined Keyword' failed:\nExpected Warn In User Keyword WARN Run Keyword And Warn On Failure With Syntax Error @@ -22,7 +22,7 @@ Run Keyword And Warn On Failure With Syntax Error Run Keyword And Warn On Failure With Failure On Test Teardown ${tc}= Check Test Case ${TESTNAME} - Check Log Message ${tc.teardown.msgs[0]} + Check Log Message ${tc.teardown[1]} ... Executing keyword 'Should Be Equal' failed:\nx != y WARN Run Keyword And Warn On Failure With Timeout @@ -30,5 +30,5 @@ Run Keyword And Warn On Failure With Timeout Run Keyword And Warn On Failure On Suite Teardown ${suite} = Get Test Suite Run Keyword And Warn On Failure - Check Log Message ${suite.teardown.msgs[0]} + Check Log Message ${suite.teardown[1]} ... Executing keyword 'Fail' failed:\nExpected Warn From Suite Teardown WARN diff --git a/atest/robot/standard_libraries/builtin/run_keyword_based_on_suite_stats.robot b/atest/robot/standard_libraries/builtin/run_keyword_based_on_suite_stats.robot index 749b766674d..0ac6326e777 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_based_on_suite_stats.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_based_on_suite_stats.robot @@ -1,13 +1,13 @@ -*** Setting *** +*** Settings *** Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/run_keyword_based_on_suite_stats Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Run Keyword If All Tests Passed ${suite} = Get Test Suite Run Keyword If All Tests Passed When All Pass Should Be Equal As Integers ${suite.statistics.failed} 0 - Should Be Equal ${suite.teardown.kws[0].name} My Teardown - Check Log Message ${suite.teardown.kws[0].kws[0].msgs[0]} Suite teardown message + Should Be Equal ${suite.teardown[0].name} My Teardown + Check Log Message ${suite.teardown[0, 0, 0]} Suite teardown message Run Keyword If All Tests Passed Can't be Used In Test Check Test Case Run Keyword If All Tests Passed Can't be Used In Test @@ -18,8 +18,8 @@ Run Keyword If All tests Passed Is not Executed When Any Test Fails Run Keyword If Any Tests Failed ${suite} = Get Test Suite Run Keyword If Any Tests Failed When Test Fails Should Be Equal As Integers ${suite.statistics.failed} 1 - Should Be Equal ${suite.teardown.kws[0].name} My Teardown - Check Log Message ${suite.teardown.kws[0].kws[0].msgs[0]} Suite teardown message + Should Be Equal ${suite.teardown[0].name} My Teardown + Check Log Message ${suite.teardown[0, 0, 0]} Suite teardown message Run Keyword If Any Tests Failed Can't be Used In Test Check Test Case Run Keyword If Any Tests Failed Can't be Used In Test diff --git a/atest/robot/standard_libraries/builtin/run_keyword_if_test_passed_failed.robot b/atest/robot/standard_libraries/builtin/run_keyword_if_test_passed_failed.robot index 08d0f4e6100..b635c2444c6 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_if_test_passed_failed.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_if_test_passed_failed.robot @@ -1,16 +1,16 @@ -*** Setting *** +*** Settings *** Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/run_keyword_if_test_passed_failed Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Run Keyword If Test Failed when test fails ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.teardown.body[0].name} BuiltIn.Log - Check Log Message ${tc.teardown.body[0].msgs[0]} Hello from teardown! + Should Be Equal ${tc.teardown[0].full_name} BuiltIn.Log + Check Log Message ${tc.teardown[0, 0]} Hello from teardown! Run Keyword If Test Failed in user keyword when test fails ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.teardown.body[1].body[0].msgs[0]} Apparently test failed! FAIL + Check Log Message ${tc.teardown[1, 0, 0]} Apparently test failed! FAIL Run Keyword If Test Failed when test passes ${tc} = Check Test Case ${TEST NAME} @@ -18,7 +18,7 @@ Run Keyword If Test Failed when test passes Run Keyword If Test Failed in user keyword when test passes ${tc} = Check Test Case ${TEST NAME} - Should Be Empty ${tc.teardown.body[1].body} + Should Be Empty ${tc.teardown[1].body} Run Keyword If Test Failed when test is skipped ${tc} = Check Test Case ${TEST NAME} @@ -26,35 +26,35 @@ Run Keyword If Test Failed when test is skipped Run Keyword If Test Failed in user keyword when test is skipped ${tc} = Check Test Case ${TEST NAME} - Should Be Empty ${tc.teardown.body[1].body} + Should Be Empty ${tc.teardown[1].body} Run Keyword If Test Failed Can't Be Used In Setup ${tc} = Check Test Case ${TEST NAME} Length Should Be ${tc.setup.body} 1 - Check Log Message ${tc.setup.body[0]} Keyword 'Run Keyword If Test Failed' can only be used in test teardown. FAIL + Check Log Message ${tc.setup[0]} Keyword 'Run Keyword If Test Failed' can only be used in test teardown. FAIL Run Keyword If Test Failed Can't Be Used in Test Check Test Case ${TEST NAME} Run Keyword If Test Failed Uses User Keyword ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.teardown.kws[0].kws[0].msgs[0]} Teardown message + Check Log Message ${tc.teardown[0, 0, 0]} Teardown message Run Keyword If Test Failed Fails Check Test Case ${TEST NAME} Run Keyword If test Failed Can't Be Used In Suite Setup or Teardown ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${SUITE.suites[0].setup.msgs[0]} Keyword 'Run Keyword If Test Failed' can only be used in test teardown. FAIL - Check Log Message ${SUITE.suites[0].teardown.msgs[0]} Keyword 'Run Keyword If Test Failed' can only be used in test teardown. FAIL + Check Log Message ${SUITE.suites[0].setup[0]} Keyword 'Run Keyword If Test Failed' can only be used in test teardown. FAIL + Check Log Message ${SUITE.suites[0].teardown[0]} Keyword 'Run Keyword If Test Failed' can only be used in test teardown. FAIL Run Keyword If Test Passed when test passes ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.teardown.body[0].msgs[0]} Teardown of passing test + Check Log Message ${tc.teardown[0, 0]} Teardown of passing test Run Keyword If Test Passed in user keyword when test passes ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.teardown.body[1].body[0].msgs[0]} Apparently test passed! FAIL + Check Log Message ${tc.teardown[1, 0, 0]} Apparently test passed! FAIL Run Keyword If Test Passed when test fails ${tc} = Check Test Case ${TEST NAME} @@ -62,7 +62,7 @@ Run Keyword If Test Passed when test fails Run Keyword If Test Passed in user keyword when test fails ${tc} = Check Test Case ${TEST NAME} - Should Be Empty ${tc.teardown.body[1].body} + Should Be Empty ${tc.teardown[1].body} Run Keyword If Test Passed when test is skipped ${tc} = Check Test Case ${TEST NAME} @@ -70,7 +70,7 @@ Run Keyword If Test Passed when test is skipped Run Keyword If Test Passed in user keyword when test is skipped ${tc} = Check Test Case ${TEST NAME} - Should Be Empty ${tc.teardown.body[1].body} + Should Be Empty ${tc.teardown[1].body} Run Keyword If Test Passed Can't Be used In Setup Check Test Case ${TEST NAME} @@ -80,8 +80,8 @@ Run Keyword If Test Passed Can't Be used In Test Run Keyword If Test Passes Uses User Keyword ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.teardown.kws[0].kws[0].msgs[0]} Teardown message - Check Keyword Data ${tc.teardown.kws[0].kws[0]} BuiltIn.Log args=\${message} + Check Log Message ${tc.teardown[0, 0, 0]} Teardown message + Check Keyword Data ${tc.teardown[0, 0]} BuiltIn.Log args=\${message} Run Keyword If Test Passed Fails Check Test Case ${TEST NAME} @@ -94,27 +94,27 @@ Run Keyword If Test Failed When Teardown Fails Run Keyword If Test Passed/Failed With Earlier Ignored Failures ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.teardown.kws[0].kws[0].status} FAIL - Should Be Equal ${tc.teardown.kws[0].status} PASS - Should Be Equal ${tc.teardown.kws[1].kws[0].status} FAIL - Should Be Equal ${tc.teardown.kws[1].status} PASS - Should Be Equal ${tc.teardown.status} PASS + Should Be Equal ${tc.teardown[0, 0].status} FAIL + Should Be Equal ${tc.teardown[0].status} PASS + Should Be Equal ${tc.teardown[1, 0].status} FAIL + Should Be Equal ${tc.teardown[1].status} PASS + Should Be Equal ${tc.teardown.status} PASS Run Keyword If Test Passed/Failed after skip in teardown ${tc} = Check Test Case ${TEST NAME} - Should Be Empty ${tc.teardown.body[1].body} - Should Be Empty ${tc.teardown.body[2].body} + Should Be Empty ${tc.teardown[1].body} + Should Be Empty ${tc.teardown[2].body} Continuable Failure In Teardown Check Test Case ${TEST NAME} Run Keyword If test Passed Can't Be Used In Suite Setup or Teardown ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${SUITE.suites[2].setup.msgs[0]} Keyword 'Run Keyword If Test Passed' can only be used in test teardown. FAIL - Check Log Message ${SUITE.suites[2].teardown.msgs[0]} Keyword 'Run Keyword If Test Passed' can only be used in test teardown. FAIL + Check Log Message ${SUITE.suites[2].setup[0]} Keyword 'Run Keyword If Test Passed' can only be used in test teardown. FAIL + Check Log Message ${SUITE.suites[2].teardown[0]} Keyword 'Run Keyword If Test Passed' can only be used in test teardown. FAIL Variable Values Should Not Be Visible As Keyword's Arguments ${tc} = Check Test Case Run Keyword If Test Failed Uses User Keyword - Check Keyword Data ${tc.teardown} BuiltIn.Run Keyword If Test Failed args=Teardown UK, \${TEARDOWN MESSAGE} type=TEARDOWN - Check Keyword Data ${tc.teardown.kws[0]} Teardown UK args=\${TEARDOWN MESSAGE} - Check Keyword Data ${tc.teardown.kws[0].kws[0]} BuiltIn.Log args=\${message} + Check Keyword Data ${tc.teardown} BuiltIn.Run Keyword If Test Failed args=Teardown UK, \${TEARDOWN MESSAGE} type=TEARDOWN + Check Keyword Data ${tc.teardown[0]} Teardown UK args=\${TEARDOWN MESSAGE} + Check Keyword Data ${tc.teardown[0, 0]} BuiltIn.Log args=\${message} diff --git a/atest/robot/standard_libraries/builtin/run_keyword_if_unless.robot b/atest/robot/standard_libraries/builtin/run_keyword_if_unless.robot index cd6869316a6..5141a284b7e 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_if_unless.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_if_unless.robot @@ -1,28 +1,28 @@ -*** Setting *** +*** Settings *** Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/run_keyword_if_unless.robot Resource atest_resource.robot -*** Variable *** +*** Variables *** ${EXECUTED} This is executed -*** Test Case *** +*** Test Cases *** Run Keyword If With True Expression ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.body[0].body[0].msgs[0]} ${EXECUTED} + Check Log Message ${tc[0, 0, 0]} ${EXECUTED} Run Keyword If With False Expression ${tc} = Check Test Case ${TEST NAME} - Should Be Equal As Integers ${tc.body[0].keyword_count} 0 + Should Be Empty ${tc[0].body} Run Keyword In User Keyword ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.body[0].body[0].body[0].msgs[0]} ${EXECUTED} - Should Be Equal As Integers ${tc.body[1].body[0].keyword_count} 0 + Check Log Message ${tc[0, 0, 0, 0]} ${EXECUTED} + Should Be Empty ${tc[1, 0].body} Run Keyword With ELSE ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.body[1].body[0].msgs[0]} ${EXECUTED} - Check Log Message ${tc.body[3].body[0].msgs[0]} ${EXECUTED} + Check Log Message ${tc[1, 0, 0]} ${EXECUTED} + Check Log Message ${tc[3, 0, 0]} ${EXECUTED} Keyword Name in ELSE as variable Check Test Case ${TEST NAME} @@ -45,18 +45,18 @@ Only first ELSE is significant Run Keyword With ELSE IF ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.body[1].body[0].msgs[0]} ${EXECUTED} + Check Log Message ${tc[1, 0, 0]} ${EXECUTED} Run Keyword with ELSE IF and ELSE ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.body[0].body[0].msgs[0]} ${EXECUTED} - Check Log Message ${tc.body[1].body[0].msgs[0]} ${EXECUTED} + Check Log Message ${tc[0, 0, 0]} ${EXECUTED} + Check Log Message ${tc[1, 0, 0]} ${EXECUTED} Run Keyword with multiple ELSE IF ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.body[0].body[0].msgs[0]} ${EXECUTED} - Check Log Message ${tc.body[1].body[0].msgs[0]} ${EXECUTED} - Check Log Message ${tc.body[2].body[0].msgs[0]} ${EXECUTED} + Check Log Message ${tc[0, 0, 0]} ${EXECUTED} + Check Log Message ${tc[1, 0, 0]} ${EXECUTED} + Check Log Message ${tc[2, 0, 0]} ${EXECUTED} Keyword Name in ELSE IF as variable Check Test Case ${TEST NAME} @@ -79,53 +79,53 @@ ELSE IF without keyword is invalid ELSE before ELSE IF is ignored ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.body[0].body[0].msgs[0]} ${EXECUTED} + Check Log Message ${tc[0, 0, 0]} ${EXECUTED} ELSE and ELSE IF inside list arguments should be escaped Check Test Case ${TEST NAME} ELSE and ELSE IF must be upper case ${tc} = Check Test Case ${TEST NAME} - Test ELSE (IF) Escaping ${tc.body[0].body[0]} else - Test ELSE (IF) Escaping ${tc.body[1].body[0]} ELSE iF + Test ELSE (IF) Escaping ${tc[0, 0]} else + Test ELSE (IF) Escaping ${tc[1, 0]} ELSE iF ELSE and ELSE IF must be whitespace sensitive ${tc} = Check Test Case ${TEST NAME} - Test ELSE (IF) Escaping ${tc.body[0].body[0]} EL SE - Test ELSE (IF) Escaping ${tc.body[1].body[0]} ELSEIF + Test ELSE (IF) Escaping ${tc[0, 0]} EL SE + Test ELSE (IF) Escaping ${tc[1, 0]} ELSEIF Run Keyword With Escaped ELSE and ELSE IF ${tc} = Check Test Case ${TEST NAME} - Test ELSE (IF) Escaping ${tc.body[0].body[0]} ELSE - Test ELSE (IF) Escaping ${tc.body[1].body[0]} ELSE IF + Test ELSE (IF) Escaping ${tc[0, 0]} ELSE + Test ELSE (IF) Escaping ${tc[1, 0]} ELSE IF Run Keyword With ELSE and ELSE IF from Variable ${tc} = Check Test Case ${TEST NAME} - Test ELSE (IF) Escaping ${tc.body[0].body[0]} ELSE - Test ELSE (IF) Escaping ${tc.body[1].body[0]} ELSE - Test ELSE (IF) Escaping ${tc.body[2].body[0]} ELSE IF - Test ELSE (IF) Escaping ${tc.body[3].body[0]} ELSE IF + Test ELSE (IF) Escaping ${tc[0, 0]} ELSE + Test ELSE (IF) Escaping ${tc[1, 0]} ELSE + Test ELSE (IF) Escaping ${tc[2, 0]} ELSE IF + Test ELSE (IF) Escaping ${tc[3, 0]} ELSE IF Run Keyword Unless With False Expression ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${ERRORS[0]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN - Check Log Message ${tc.body[1].body[0]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN - Check Log Message ${tc.body[1].body[1].msgs[0]} ${EXECUTED} + Check Log Message ${ERRORS[0]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN + Check Log Message ${tc[1, 0]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN + Check Log Message ${tc[1, 1, 0]} ${EXECUTED} Run Keyword Unless With True Expression ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${ERRORS[1]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN - Check Log Message ${tc.body[0].body[0]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN - Length Should Be ${tc.body[0].body} 1 + Check Log Message ${ERRORS[1]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN + Check Log Message ${tc[0, 0]} Keyword 'BuiltIn.Run Keyword Unless' is deprecated. WARN + Length Should Be ${tc[0].body} 1 Variable Values Should Not Be Visible As Keyword's Arguments ${tc} = Check Test Case Run Keyword In User Keyword - Check Keyword Data ${tc.body[0].body[0]} BuiltIn.Run Keyword If args='\${status}' == 'PASS', Log, \${message} - Check Keyword Data ${tc.body[0].body[0].body[0]} BuiltIn.Log args=\${message} + Check Keyword Data ${tc[0, 0]} BuiltIn.Run Keyword If args='\${status}' == 'PASS', Log, \${message} + Check Keyword Data ${tc[0, 0, 0]} BuiltIn.Log args=\${message} *** Keywords *** Test ELSE (IF) Escaping [Arguments] ${kw} ${else (if)} - Length Should Be ${kw.msgs} 2 - Check Log Message ${kw.msgs[0]} ${else (if)} - Check Log Message ${kw.msgs[1]} ${EXECUTED} + Length Should Be ${kw.body} 2 + Check Log Message ${kw[0]} ${else (if)} + Check Log Message ${kw[1]} ${EXECUTED} diff --git a/atest/robot/standard_libraries/builtin/run_keyword_variants_registering.robot b/atest/robot/standard_libraries/builtin/run_keyword_variants_registering.robot index 33e6bb7845e..4a253a71d71 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_variants_registering.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_variants_registering.robot @@ -1,9 +1,9 @@ -*** Setting *** +*** Settings *** Documentation Tests for registering own run keyword variant Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/run_keyword_variants_registering.robot Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Not registered Keyword Fails With Content That Should Not Be Evaluated Twice Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/run_keyword_variants_variable_handling.robot b/atest/robot/standard_libraries/builtin/run_keyword_variants_variable_handling.robot index dd277e90c6b..632d23d74a1 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_variants_variable_handling.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_variants_variable_handling.robot @@ -1,19 +1,28 @@ -*** Setting *** +*** Settings *** Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/run_keyword_variants_variable_handling.robot Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Variable Values Should Not Be Visible As Keyword's Arguments ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0]} BuiltIn.Run Keyword args=My UK, Log, \${OBJECT} - Check Keyword Data ${tc.kws[0].kws[0]} My UK args=Log, \${OBJECT} - Check Keyword Data ${tc.kws[0].kws[0].kws[0]} BuiltIn.Run Keyword args=\${name}, \@{args} - Check Keyword Data ${tc.kws[0].kws[0].kws[0].kws[0]} BuiltIn.Log args=\@{args} + Check Keyword Data ${tc[0]} BuiltIn.Run Keyword args=My UK, Log, \${OBJECT} + Check Keyword Data ${tc[0, 0]} My UK args=Log, \${OBJECT} + Check Keyword Data ${tc[0, 0, 0]} BuiltIn.Run Keyword args=\${name}, \@{args} + Check Keyword Data ${tc[0, 0, 0, 0]} BuiltIn.Log args=\@{args} + Check Log Message ${tc[0, 0, 0, 0, 0]} Robot + Check Keyword Data ${tc[0, 0, 1, 0]} BuiltIn.Log args=\${args}[0] + Check Log Message ${tc[0, 0, 1, 0, 0]} Robot Run Keyword When Keyword and Arguments Are in List Variable ${tc} = Check Test Case ${TEST NAME} - Check Keyword Data ${tc.kws[0].kws[0]} \\Log Many args=c:\\\\temp\\\\foo, \\\${notvar} - Check Keyword Data ${tc.kws[1].kws[0]} \\Log Many args=\\\${notvar} + Check Keyword Data ${tc[0, 0]} \\Log Many args=c:\\\\temp\\\\foo, \\\${notvar} + Check Keyword Data ${tc[1, 0]} \\Log Many args=\\\${notvar} + +Run Keyword With Empty List Variable + Check Test Case ${TEST NAME} + +Run Keyword With Multiple Empty List Variables + Check Test Case ${TEST NAME} Run Keyword If When Arguments are In Multiple List ${tc} = Check Test Case ${TEST NAME} @@ -45,10 +54,10 @@ Run Keyword If With List And One Argument That needs to Be Processed ${tc} = Check Test Case ${TEST NAME} Check Keyword Arguments And Messages ${tc} -*** Keyword *** +*** Keywords *** Check Keyword Arguments And Messages [Arguments] ${tc} - Check Keyword Data ${tc.kws[0].kws[0]} \\Log Many args=\@{ARGS} - Check Keyword Data ${tc.kws[0].kws[0].kws[0]} BuiltIn.Log Many args=\@{args} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} c:\\temp\\foo - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[1]} \${notvar} + Check Keyword Data ${tc[0, 0]} \\Log Many args=\@{ARGS} + Check Keyword Data ${tc[0, 0, 0]} BuiltIn.Log Many args=\@{args} + Check Log Message ${tc[0, 0, 0, 0]} c:\\temp\\foo + Check Log Message ${tc[0, 0, 0, 1]} \${notvar} diff --git a/atest/robot/standard_libraries/builtin/run_keyword_variants_with_escaping_control_arguments.robot b/atest/robot/standard_libraries/builtin/run_keyword_variants_with_escaping_control_arguments.robot index bf6a2754738..6c55e2821a3 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_variants_with_escaping_control_arguments.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_variants_with_escaping_control_arguments.robot @@ -5,32 +5,32 @@ Resource atest_resource.robot *** Test Cases *** Run Keyword with Run Keywords with Arguments Inside List variable should escape AND ${tc}= Test Should Have Correct Keywords BuiltIn.Run Keywords - Check Log Message ${tc.kws[0].kws[0].kws[0].kws[0].msgs[0]} log message + Check Log Message ${tc[0, 0, 0, 0, 0]} log message Run Keyword with Run Keywords and Arguments Inside List variable should escape AND ${tc}= Test Should Have Correct Keywords BuiltIn.Run Keywords - Check Log Message ${tc.kws[0].kws[0].kws[0].kws[0].msgs[0]} log message + Check Log Message ${tc[0, 0, 0, 0, 0]} log message Run Keyword If with Run Keywords With Arguments Inside List variable should escape AND ${tc}= Test Should Have Correct Keywords BuiltIn.Run Keywords - Check Log Message ${tc.kws[0].kws[0].kws[0].kws[0].msgs[0]} log message + Check Log Message ${tc[0, 0, 0, 0, 0]} log message Run Keyword If with Run Keywords And Arguments Inside List variable should escape AND ${tc}= Test Should Have Correct Keywords BuiltIn.Run Keyword - Check Log Message ${tc.kws[0].kws[0].kws[0].kws[0].kws[0].msgs[0]} log message + Check Log Message ${tc[0, 0, 0, 0, 0, 0]} log message Run Keywords With Run Keyword If should not escape ELSE and ELSE IF ${tc}= Test Should Have Correct Keywords ... BuiltIn.Run Keyword If BuiltIn.Log BuiltIn.Run Keyword If - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} log message - Check Log Message ${tc.kws[0].kws[1].msgs[0]} that + Check Log Message ${tc[0, 0, 0, 0]} log message + Check Log Message ${tc[0, 1, 0]} that Run Keywords With Run Keyword If In List Variable Should Escape ELSE and ELSE IF From List Variable ${tc}= Test Should Have Correct Keywords ... BuiltIn.Run Keyword If BuiltIn.Log BuiltIn.Run Keyword If - Check Log Message ${tc.kws[0].kws[1].msgs[0]} that + Check Log Message ${tc[0, 1, 0]} that Run Keywords With Run Keyword If With Arguments From List Variable should escape ELSE and ELSE IF From List Variable ${tc}= Test Should Have Correct Keywords ... BuiltIn.Run Keyword If BuiltIn.Log BuiltIn.Run Keyword If - Check Log Message ${tc.kws[0].kws[1].msgs[0]} that + Check Log Message ${tc[0, 1, 0]} that diff --git a/atest/robot/standard_libraries/builtin/run_keyword_with_errors.robot b/atest/robot/standard_libraries/builtin/run_keyword_with_errors.robot index f3924a1d034..977d82e9da3 100644 --- a/atest/robot/standard_libraries/builtin/run_keyword_with_errors.robot +++ b/atest/robot/standard_libraries/builtin/run_keyword_with_errors.robot @@ -5,13 +5,13 @@ Resource atest_resource.robot *** Test Cases *** Ignore Error When Keyword Passes ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} My message + Check Log Message ${tc[0, 0, 0]} My message Ignore Error When Keyword Fails ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} My error message FAIL - Should Be Equal ${tc.kws[0].kws[0].status} FAIL - Should Be Equal ${tc.kws[0].status} PASS + Should Be Equal ${tc[0].status} PASS + Should Be Equal ${tc[0, 0].status} FAIL + Check Log Message ${tc[0, 0, 0]} My error message FAIL Ignore Error Returns When Keyword Passes Check Test Case ${TEST NAME} @@ -21,30 +21,30 @@ Ignore Error Returns When Keyword Fails Ignore Error With User Keyword When Keywords Pass ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Hello world - Check Keyword Data ${tc.kws[0].kws[0].kws[2]} BuiltIn.Evaluate \${ret} 1+2 + Check Log Message ${tc[0, 0, 0, 0]} Hello world + Check Keyword Data ${tc[0, 0, 2]} BuiltIn.Evaluate \${ret} 1+2 Ignore Error With User Keyword When Keyword Fails ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].kws[0].msgs[0]} Hello world - Check Log Message ${tc.kws[0].kws[0].kws[1].msgs[0]} Expected failure in UK FAIL - Length Should Be ${tc.kws[0].kws[0].kws} 3 - Should Be Equal ${tc.kws[0].kws[0].kws[-1].status} NOT RUN + Check Log Message ${tc[0, 0, 0, 0, 0]} Hello world + Check Log Message ${tc[0, 0, 1, 0]} Expected failure in UK FAIL + Length Should Be ${tc[0, 0].body} 3 + Should Be Equal ${tc[0, 0, -1].status} NOT RUN Ignore Error With Arguments That Needs To Be Escaped Check Test Case ${TEST NAME} Ignore Error When Timeout Occurs ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].status} FAIL Run Keyword And Ignore Error captured timeout even though it should not no values + Should Be Equal ${tc[0].status} FAIL Run Keyword And Ignore Error captured timeout even though it should not no values Ignore Error When Timeout Occurs In UK Check Test Case ${TEST NAME} -Ignore Error When Syntax Error At Parsing Time +Ignore Error Cannot Catch Syntax Errors Check Test Case ${TEST NAME} -Ignore Error When Syntax Error At Run Time +Ignore Error Can Catch Non-Syntax Errors Check Test Case ${TEST NAME} Ignore Error When Syntax Error In Setting Variables @@ -75,9 +75,9 @@ Ignore Error With "Passing" Exceptions Expect Error When Error Occurs ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} My error message FAIL - Should Be Equal ${tc.kws[0].kws[0].status} FAIL - Should Be Equal ${tc.kws[0].status} PASS + Should Be Equal ${tc[0].status} PASS + Should Be Equal ${tc[0, 0].status} FAIL + Check Log Message ${tc[0, 0, 0]} My error message FAIL Expect Error When Different Error Occurs Check Test Case ${TEST NAME} @@ -97,32 +97,32 @@ Expected Error Should Be Returned Expect Error With User Keyword When Keywords Pass ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Hello world - Check Keyword Data ${tc.kws[0].kws[0].kws[2]} BuiltIn.Evaluate \${ret} 1+2 + Check Log Message ${tc[0, 0, 0, 0]} Hello world + Check Keyword Data ${tc[0, 0, 2]} BuiltIn.Evaluate \${ret} 1+2 Expect Error With User Keyword When Keyword Fails ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].kws[0].msgs[0]} Hello world - Check Log Message ${tc.kws[0].kws[0].kws[1].msgs[0]} Expected failure in UK FAIL - Length Should Be ${tc.kws[0].kws[0].kws} 3 - Should Be Equal ${tc.kws[0].kws[0].kws[-1].status} NOT RUN + Check Log Message ${tc[0, 0, 0, 0, 0]} Hello world + Check Log Message ${tc[0, 0, 1, 0]} Expected failure in UK FAIL + Length Should Be ${tc[0, 0].body} 3 + Should Be Equal ${tc[0, 0, -1].status} NOT RUN Expect Error With Arguments That Needs To Be Escaped ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[1].kws[0].msgs[0]} c:\\temp\\foo\\not_new_line - Check Log Message ${tc.kws[1].kws[0].msgs[1]} \${notvar} + Check Log Message ${tc[1, 0, 0]} c:\\temp\\foo\\not_new_line + Check Log Message ${tc[1, 0, 1]} \${notvar} Expect Error When Timeout Occurs ${tc} = Check Test Case ${TEST NAME} - Should Be Equal ${tc.kws[0].status} FAIL Run Keyword And Expect Error captured timeout even though it should not no values + Should Be Equal ${tc[0].status} FAIL Run Keyword And Expect Error captured timeout even though it should not no values Expect Error When Timeout Occurs In UK Check Test Case ${TEST NAME} -Expect Error When Syntax Error At Parsing Time +Expect Error Cannot Catch Syntax Errors Check Test Case ${TEST NAME} -Expect Error When Syntax Error At Run Time +Expect Error Can Catch Non-Syntax Errors Check Test Case ${TEST NAME} Expect Error When Syntax Error In Setting Variables @@ -171,4 +171,4 @@ Expect Error With "Passing" Exceptions Variable Values Should Not Be Visible As Keyword's Arguments ${tc} = Check Test Case Ignore Error With Arguments That Needs To be Escaped - Check Keyword Data ${tc.kws[3].kws[0]} BuiltIn.Create List args=\@{NEEDS ESCAPING} + Check Keyword Data ${tc[3, 0]} BuiltIn.Create List args=\@{NEEDS ESCAPING} diff --git a/atest/robot/standard_libraries/builtin/run_keywords.robot b/atest/robot/standard_libraries/builtin/run_keywords.robot index 39049cea76d..e245b9146e7 100644 --- a/atest/robot/standard_libraries/builtin/run_keywords.robot +++ b/atest/robot/standard_libraries/builtin/run_keywords.robot @@ -1,4 +1,6 @@ *** Settings *** +Documentation Testing Run Keywords when used without AND. Tests with AND are in +... run_keywords_with_arguments.robot. Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/run_keywords.robot Resource atest_resource.robot @@ -6,12 +8,32 @@ Resource atest_resource.robot Passing keywords ${tc} = Test Should Have Correct Keywords ... BuiltIn.No Operation Passing BuiltIn.Log Variables - Check Log Message ${tc.kws[0].kws[1].kws[0].msgs[0]} Hello, world! + Check Log Message ${tc[0, 1, 0, 0]} Hello, world! Failing keyword Test Should Have Correct Keywords ... Passing Failing +Embedded arguments + ${tc} = Test Should Have Correct Keywords + ... Embedded "arg" Embedded "\${1}" Embedded object "\${OBJECT}" + Check Log Message ${tc[0, 0, 0, 0]} arg + Check Log Message ${tc[0, 1, 0, 0]} 1 + Check Log Message ${tc[0, 2, 0, 0]} Robot + +Embedded arguments with library keywords + ${tc} = Test Should Have Correct Keywords + ... embedded_args.Embedded "arg" in library + ... embedded_args.Embedded "\${1}" in library + ... embedded_args.Embedded object "\${OBJECT}" in library + Check Log Message ${tc[0, 0, 0]} arg + Check Log Message ${tc[0, 1, 0]} 1 + Check Log Message ${tc[0, 2, 0]} Robot + +Keywords names needing escaping + Test Should Have Correct Keywords + ... Needs \\escaping \\\${notvar} + Continuable failures Test Should Have Correct Keywords ... Continuable failure Multiple continuables Failing @@ -21,9 +43,14 @@ Keywords as variables ... BuiltIn.No Operation Passing BuiltIn.No Operation ... Passing BuiltIn.Log Variables Failing +Keywords names needing escaping as variable + Test Should Have Correct Keywords + ... Needs \\escaping \\\${notvar} Needs \\escaping \\\${notvar} + ... kw_index=1 + Non-existing variable as keyword name - ${tc} = Check Test Case ${TESTNAME} - Should Be Empty ${tc.kws[0].kws} + Test Should Have Correct Keywords + ... Passing Non-existing variable inside executed keyword Test Should Have Correct Keywords @@ -43,6 +70,9 @@ In test setup In test teardown Check Test Case ${TESTNAME} +In test teardown with non-existing variable in keyword name + Check Test Case ${TESTNAME} + In test teardown with ExecutionPassed exception Check Test Case ${TESTNAME} @@ -50,7 +80,7 @@ In test teardown with ExecutionPassed exception after continuable failure Check Test Case ${TESTNAME} In suite setup - Check Log Message ${SUITE.setup.kws[0].kws[0].msgs[0]} Hello, world! + Check Log Message ${SUITE.setup[0, 0, 0]} Hello, world! Should Contain Keywords ${SUITE.setup} Passing BuiltIn.No Operation In suite teardown diff --git a/atest/robot/standard_libraries/builtin/run_keywords_with_arguments.robot b/atest/robot/standard_libraries/builtin/run_keywords_with_arguments.robot index 4a4d98780d7..4e792da98bf 100644 --- a/atest/robot/standard_libraries/builtin/run_keywords_with_arguments.robot +++ b/atest/robot/standard_libraries/builtin/run_keywords_with_arguments.robot @@ -1,50 +1,52 @@ *** Settings *** +Documentation Testing Run Keywords when used with AND. Tests without AND are in +... run_keywords.robot. Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/run_keywords_with_arguments.robot Resource atest_resource.robot *** Test Cases *** With arguments ${tc}= Test Should Have Correct Keywords BuiltIn.Should Be Equal BuiltIn.No Operation BuiltIn.Log Many BuiltIn.Should Be Equal - Check Log Message ${tc.kws[0].kws[2].msgs[1]} 1 + Check Log Message ${tc[0, 2, 1]} 1 Should fail with failing keyword Test Should Have Correct Keywords BuiltIn.No Operation BuiltIn.Should Be Equal Should support keywords and arguments from variables ${tc}= Test Should Have Correct Keywords BuiltIn.Should Be Equal BuiltIn.No Operation BuiltIn.Log Many BuiltIn.Should Be Equal As Integers - Check Log Message ${tc.kws[0].kws[2].msgs[0]} hello - Check Log Message ${tc.kws[0].kws[2].msgs[1]} 1 - Check Log Message ${tc.kws[0].kws[2].msgs[2]} 2 - Check Log Message ${tc.kws[0].kws[2].msgs[3]} 3 + Check Log Message ${tc[0, 2, 0]} hello + Check Log Message ${tc[0, 2, 1]} 1 + Check Log Message ${tc[0, 2, 2]} 2 + Check Log Message ${tc[0, 2, 3]} 3 AND must be upper case ${tc}= Test Should Have Correct Keywords BuiltIn.Log Many no kw - Check Log Message ${tc.kws[0].kws[0].msgs[1]} and + Check Log Message ${tc[0, 0, 1]} and AND must be whitespace sensitive ${tc}= Test Should Have Correct Keywords BuiltIn.Log Many no kw - Check Log Message ${tc.kws[0].kws[0].msgs[1]} A ND + Check Log Message ${tc[0, 0, 1]} A ND Escaped AND ${tc}= Test Should Have Correct Keywords BuiltIn.Log Many no kw - Check Log Message ${tc.kws[0].kws[0].msgs[1]} AND + Check Log Message ${tc[0, 0, 1]} AND AND from Variable ${tc}= Test Should Have Correct Keywords BuiltIn.Log Many no kw - Check Log Message ${tc.kws[0].kws[0].msgs[1]} AND + Check Log Message ${tc[0, 0, 1]} AND AND in List Variable ${tc}= Test Should Have Correct Keywords BuiltIn.Log Many no kw - Check Log Message ${tc.kws[0].kws[0].msgs[1]} AND + Check Log Message ${tc[0, 0, 1]} AND Escapes in List Variable should be handled correctly ${tc}= Test Should Have Correct Keywords BuiltIn.Log Many no kw - Check Log Message ${tc.kws[0].kws[0].msgs[0]} 1 - Check Log Message ${tc.kws[0].kws[0].msgs[1]} AND - Check Log Message ${tc.kws[0].kws[0].msgs[2]} 2 - Check Log Message ${tc.kws[0].kws[0].msgs[3]} Log Many - Check Log Message ${tc.kws[0].kws[0].msgs[4]} x\${escaped} - Check Log Message ${tc.kws[0].kws[0].msgs[5]} c:\\temp + Check Log Message ${tc[0, 0, 0]} 1 + Check Log Message ${tc[0, 0, 1]} AND + Check Log Message ${tc[0, 0, 2]} 2 + Check Log Message ${tc[0, 0, 3]} Log Many + Check Log Message ${tc[0, 0, 4]} x\${escaped} + Check Log Message ${tc[0, 0, 5]} c:\\temp AND as last argument should raise an error Test Should Have Correct Keywords BuiltIn.Log Many BuiltIn.No Operation @@ -54,3 +56,15 @@ Consecutive AND's AND as first argument should raise an error Check Test Case ${TESTNAME} + +Keywords names needing escaping + Test Should Have Correct Keywords + ... Needs \\escaping \\\${notvar} Needs \\escaping \\\${notvar} + +Keywords names needing escaping as variable + Test Should Have Correct Keywords + ... Needs \\escaping \\\${notvar} Needs \\escaping \\\${notvar} + ... kw_index=1 + +In test teardown with non-existing variable in keyword name + Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/set_documentation.robot b/atest/robot/standard_libraries/builtin/set_documentation.robot index d155f09b210..bbe36cbe526 100644 --- a/atest/robot/standard_libraries/builtin/set_documentation.robot +++ b/atest/robot/standard_libraries/builtin/set_documentation.robot @@ -5,35 +5,40 @@ Resource atest_resource.robot *** Test Cases *** Set test documentation ${tc} = Check Test Doc ${TESTNAME} This has been set!\nTo several lines. - Check Log Message ${tc.kws[0].msgs[0]} Set test documentation to:\nThis has been set!\nTo several lines. + Check Log Message ${tc[0, 0]} Set test documentation to:\nThis has been set!\nTo several lines. Replace test documentation ${tc} = Check Test Doc ${TESTNAME} New doc - Check Log Message ${tc.kws[0].msgs[0]} Set test documentation to:\nNew doc + Check Log Message ${tc[0, 0]} Set test documentation to:\nNew doc Append to test documentation - ${tc} = Check Test Doc ${TESTNAME} Original doc is continued \n\ntwice! - Check Log Message ${tc.kws[0].msgs[0]} Set test documentation to:\nOriginal doc is continued - Check Log Message ${tc.kws[2].msgs[0]} Set test documentation to:\nOriginal doc is continued \n\ntwice! + ${tc} = Check Test Doc ${TESTNAME} Original doc is continued \n\ntwice! thrice!! + Check Log Message ${tc[0, 0]} Set test documentation to:\nOriginal doc is continued + Check Log Message ${tc[2, 0]} Set test documentation to:\nOriginal doc is continued \n\ntwice! + Check Log Message ${tc[4, 0]} Set test documentation to:\nOriginal doc is continued \n\ntwice! thrice + Check Log Message ${tc[6, 0]} Set test documentation to:\nOriginal doc is continued \n\ntwice! thrice! + Check Log Message ${tc[8, 0]} Set test documentation to:\nOriginal doc is continued \n\ntwice! thrice!! Set suite documentation ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Set suite documentation to:\nNew suite doc + Check Log Message ${tc[0, 0]} Set suite documentation to:\nNew suite doc Check Test Case ${TESTNAME} 2 Should Start With ${SUITE.suites[0].doc} New suite doc Append to suite documentation ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Set suite documentation to:\nNew suite doc is continued + Check Log Message ${tc[0, 0]} Set suite documentation to:\nNew suite doc is continued ${tc} = Check Test Case ${TESTNAME} 2 - Check Log Message ${tc.kws[1].msgs[0]} Set suite documentation to:\nNew suite doc is continued \n\ntwice! - Should Be Equal ${SUITE.suites[0].doc} New suite doc is continued \n\ntwice! + Check Log Message ${tc[1, 0]} Set suite documentation to:\nNew suite doc is continued \n\ntwice! + Check Log Message ${tc[3, 0]} Set suite documentation to:\nNew suite doc is continued \n\ntwice!,thrice + Check Log Message ${tc[5, 0]} Set suite documentation to:\nNew suite doc is continued \n\ntwice!,thrice?1 + Should Be Equal ${SUITE.suites[0].doc} New suite doc is continued \n\ntwice!,thrice?1 Set init file suite docs Should Be Equal ${SUITE.doc} Init file doc. Concatenated in setup. Appended in test. - Check Log Message ${SUITE.setup.msgs[0]} Set suite documentation to:\nInit file doc. Concatenated in setup. + Check Log Message ${SUITE.setup[0]} Set suite documentation to:\nInit file doc. Concatenated in setup. Set top level suite documentation ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Set suite documentation to:\nInit file doc. Concatenated in setup. Appended in test. + Check Log Message ${tc[0, 0]} Set suite documentation to:\nInit file doc. Concatenated in setup. Appended in test. diff --git a/atest/robot/standard_libraries/builtin/set_library_search_order.robot b/atest/robot/standard_libraries/builtin/set_library_search_order.robot index 6bc2e12bf8e..f7b692bbc7c 100644 --- a/atest/robot/standard_libraries/builtin/set_library_search_order.robot +++ b/atest/robot/standard_libraries/builtin/set_library_search_order.robot @@ -39,3 +39,8 @@ Library Search Order Is Space Insensitive Library Search Order Is Case Insensitive Check Test Case ${TEST NAME} +Search Order Controlled Match Containing Embedded Arguments Wins Over Exact Match + Check Test Case ${TEST NAME} + +Best Search Order Controlled Match Wins In Library + Check Test Case ${TEST NAME} diff --git a/atest/robot/standard_libraries/builtin/set_log_level.robot b/atest/robot/standard_libraries/builtin/set_log_level.robot index 709679cc2c3..621e617125c 100644 --- a/atest/robot/standard_libraries/builtin/set_log_level.robot +++ b/atest/robot/standard_libraries/builtin/set_log_level.robot @@ -5,24 +5,36 @@ Resource atest_resource.robot *** Test Cases *** Set Log Level ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Log level changed from INFO to TRACE. - Check Log Message ${tc.kws[1].msgs[1]} This is logged TRACE - Check Log Message ${tc.kws[2].msgs[1]} This is logged DEBUG - Check Log Message ${tc.kws[3].msgs[1]} This is logged INFO - Should Be Empty ${tc.kws[6].msgs} - Check Log Message ${tc.kws[7].msgs[0]} This is logged DEBUG - Check Log Message ${tc.kws[8].msgs[0]} This is logged INFO - Should Be Empty ${tc.kws[10].msgs} - Should Be Empty ${tc.kws[11].msgs} - Check Log Message ${tc.kws[12].msgs[0]} This is logged INFO - Should Be Empty ${tc.kws[15].msgs} - Check Log Message ${tc.kws[16].msgs[0]} This is logged ERROR - Should Be Empty ${tc.kws[18].msgs} - Should Be Empty ${tc.kws[19].msgs} + Check Log Message ${tc[0, 0]} Log level changed from INFO to TRACE. DEBUG + Check Log Message ${tc[1, 1]} This is logged TRACE + Check Log Message ${tc[2, 1]} This is logged DEBUG + Check Log Message ${tc[3, 1]} This is logged INFO + Check Log Message ${tc[4, 1]} Log level changed from TRACE to DEBUG. DEBUG + Should Be Empty ${tc[6].body} + Check Log Message ${tc[7, 0]} This is logged DEBUG + Check Log Message ${tc[8, 0]} This is logged INFO + Should Be Empty ${tc[9].body} + Should Be Empty ${tc[10].body} + Should Be Empty ${tc[11].body} + Check Log Message ${tc[12, 0]} This is logged INFO + Should Be Empty ${tc[15].body} + Check Log Message ${tc[16, 0]} This is logged ERROR + Should Be Empty ${tc[17].body} + Should Be Empty ${tc[18].body} + Should Be Empty ${tc[19].body} Invalid Log Level Failure Is Catchable Check Test Case ${TESTNAME} +Reset Log Level + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0]} Log level changed from INFO to DEBUG. DEBUG + Check Log Message ${tc[1, 0]} This is logged INFO + Check Log Message ${tc[2, 0]} This is logged DEBUG + Should Be Empty ${tc[3].body} + Check Log Message ${tc[4, 0]} This is logged INFO + Should Be Empty ${tc[5].body} + Log Level Goes To HTML File Should Contain ${OUTDIR}${/}set_log_level_log.html KW Info to log File Should Contain ${OUTDIR}${/}set_log_level_log.html KW Trace to log diff --git a/atest/robot/standard_libraries/builtin/set_resource_search_order.robot b/atest/robot/standard_libraries/builtin/set_resource_search_order.robot index d162ecd82b5..1d0a1bbd403 100644 --- a/atest/robot/standard_libraries/builtin/set_resource_search_order.robot +++ b/atest/robot/standard_libraries/builtin/set_resource_search_order.robot @@ -38,3 +38,9 @@ Resource Search Order Is Case Insensitive Default Resource Order Should Be Suite Specific Check Test Case ${TEST NAME} + +Search Order Controlled Match Containing Embedded Arguments Wins Over Exact Match + Check Test Case ${TEST NAME} + +Best Search Order Controlled Match Wins In Resource + Check Test Case ${TEST NAME} diff --git a/atest/robot/standard_libraries/builtin/set_suite_metadata.robot b/atest/robot/standard_libraries/builtin/set_suite_metadata.robot index 5170c9f8c06..36ca3731efc 100644 --- a/atest/robot/standard_libraries/builtin/set_suite_metadata.robot +++ b/atest/robot/standard_libraries/builtin/set_suite_metadata.robot @@ -5,49 +5,62 @@ Resource atest_resource.robot *** Test Cases *** Set new value Metadata should have value New metadata Set in test - ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0]} ... Set suite metadata 'New metadata' to value 'Set in test'. Override existing value Metadata should have value Initial New value - ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0]} ... Set suite metadata 'Initial' to value 'New value'. Names are case and space insensitive Metadata should have value My Name final value - ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[1].msgs[0]} + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[1, 0]} ... Set suite metadata 'MYname' to value 'final value'. Append to value Metadata should have value To Append Original is continued \n\ntwice! - ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0]} ... Set suite metadata 'To Append' to value 'Original'. - Check log message ${tc.kws[2].msgs[0]} + Check Log Message ${tc[2, 0]} ... Set suite metadata 'toappend' to value 'Original is continued'. - Check log message ${tc.kws[4].msgs[0]} + Check Log Message ${tc[4, 0]} ... Set suite metadata 'TOAPPEND' to value 'Original is continued \n\ntwice!'. + Check Log Message ${tc[6, 0]} + ... Set suite metadata 'Version' to value '1.0'. + Check Log Message ${tc[8, 0]} + ... Set suite metadata 'version' to value '1.0/2.0'. + Check Log Message ${tc[10, 0]} + ... Set suite metadata 'ver sion' to value '1.0/2.0/3.0'. Set top-level suite metadata Metadata should have value New metadata Metadata for top level suite top=yes - ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0]} ... Set suite metadata 'New metadata' to value 'Metadata for'. - Check log message ${tc.kws[1].msgs[0]} + Check Log Message ${tc[1, 0]} ... Set suite metadata 'newmetadata' to value 'Metadata for top level suite'. + Metadata should have value Separator 2top**level top=yes + Check Log Message ${tc[3, 0]} + ... Set suite metadata 'Separator' to value '2'. + Check Log Message ${tc[4, 0]} + ... Set suite metadata 'Separator' to value '2top'. + Check Log Message ${tc[5, 0]} + ... Set suite metadata 'Separator' to value '2top**level'. Non-ASCII and non-string names and values - ${tc} = Check test case ${TESTNAME} - Check log message ${tc.kws[0].msgs[0]} + ${tc} = Check Test Case ${TESTNAME} + Check Log Message ${tc[0, 0]} ... Set suite metadata '42' to value '1'. - Check log message ${tc.kws[2].msgs[0]} + Check Log Message ${tc[2, 0]} ... Set suite metadata '42' to value '1 päivä'. Modifying \${SUITE METADATA} has no effect also after setting metadata - Check test case ${TESTNAME} + Check Test Case ${TESTNAME} Metadata should have value Cannot be set otherwise Set in suite setup diff --git a/atest/robot/standard_libraries/builtin/set_test_message.robot b/atest/robot/standard_libraries/builtin/set_test_message.robot index 28882ff74d7..bb79583aa1e 100644 --- a/atest/robot/standard_libraries/builtin/set_test_message.robot +++ b/atest/robot/standard_libraries/builtin/set_test_message.robot @@ -6,42 +6,44 @@ Resource atest_resource.robot *** Test Cases *** Set Message To Successful Test ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\nMy Test + Check Log Message ${tc[0, 0]} Set test message to:\nMy Test Reset Message Check Test Case ${TEST NAME} Append To Message ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\nMy - Check Log Message ${tc.kws[1].msgs[0]} Set test message to:\nMy & its continuation <> + Check Log Message ${tc[0, 0]} Set test message to:\nMy + Check Log Message ${tc[1, 0]} Set test message to:\nMy & its continuation <> + Check Log Message ${tc[2, 0]} Set test message to:\nMy & its continuation <>1 + Check Log Message ${tc[3, 0]} Set test message to:\nMy & its continuation <>1,\n2 Set Non-ASCII Message ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\nHyvää yötä + Check Log Message ${tc[0, 0]} Set test message to:\nHyvää yötä Set Multiline Message ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\n1\n2\n3 + Check Log Message ${tc[0, 0]} Set test message to:\n1\n2\n3 Set HTML Message ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\nMy HTML message html=True + Check Log Message ${tc[0, 0]} Set test message to:\nMy HTML message html=True Append HTML to non-HTML ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\nMy non-HTML & html=False - Check Log Message ${tc.kws[1].msgs[0]} Set test message to:\nMy non-HTML <message> & its HTML continuation html=True + Check Log Message ${tc[0, 0]} Set test message to:\nMy non-HTML & html=False + Check Log Message ${tc[1, 0]} Set test message to:\nMy non-HTML <message> & its HTML continuation html=True Append non-HTML to HTML ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\nMy HTML message html=True - Check Log Message ${tc.kws[1].msgs[0]} Set test message to:\nMy HTML message & its non-HTML <continuation> html=True + Check Log Message ${tc[0, 0]} Set test message to:\nMy HTML message html=True + Check Log Message ${tc[1, 0]} Set test message to:\nMy HTML message & its non-HTML <continuation> html=True Append HTML to HTML ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Set test message to:\nMy HTML message html=True - Check Log Message ${tc.kws[1].msgs[0]} Set test message to:\nMy HTML message & its HTML continuation html=True + Check Log Message ${tc[0, 0]} Set test message to:\nMy HTML message html=True + Check Log Message ${tc[1, 0]} Set test message to:\nMy HTML message & its HTML continuation html=True Set Non-String Message Check Test Case ${TEST NAME} @@ -87,3 +89,18 @@ Not Allowed In Suite Setup or Teardown ... Also suite teardown failed: ... 'Set Test Message' keyword cannot be used in suite setup or teardown. Should Be Equal ${SUITE.suites[1].message} ${error} + +Append HTML to non-HTML with separator + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} Set test message to:\nA non HTML html=False + Check Log Message ${tc[1, 0]} Set test message to:\nA non HTML <message>&its HTML continuation html=True + +Append non-HTML to HTML with separator + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} Set test message to:\nA HTML message html=True + Check Log Message ${tc[1, 0]} Set test message to:\nA HTML message<\br>its non-HTML <continuation> html=True + +Append HTML to HTML with separator + ${tc} = Check Test Case ${TEST NAME} + Check Log Message ${tc[0, 0]} Set test message to:\nA HTML message html=True + Check Log Message ${tc[1, 0]} Set test message to:\nA HTML message && its HTML continuation html=True diff --git a/atest/robot/standard_libraries/builtin/set_variable_if.robot b/atest/robot/standard_libraries/builtin/set_variable_if.robot index 622fd25d053..c49447cb33e 100644 --- a/atest/robot/standard_libraries/builtin/set_variable_if.robot +++ b/atest/robot/standard_libraries/builtin/set_variable_if.robot @@ -46,3 +46,5 @@ With List Variables In Expressions And Values With List Variables Containing Escaped Values Check Test Case ${TESTNAME} +Lot of conditions + Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/setting_variables.robot b/atest/robot/standard_libraries/builtin/setting_variables.robot index c889df6f63f..18aa6b8d2b0 100644 --- a/atest/robot/standard_libraries/builtin/setting_variables.robot +++ b/atest/robot/standard_libraries/builtin/setting_variables.robot @@ -1,30 +1,30 @@ -*** Setting *** +*** Settings *** Documentation Tests for set variable and set test/suite/global variable keywords Suite Setup Run Tests ... --variable cli_var_1:CLI1 --variable cli_var_2:CLI2 --variable cli_var_3:CLI3 ... standard_libraries/builtin/setting_variables Resource atest_resource.robot -*** Test Case *** +*** Test Cases *** Set Variable ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} \${var} = Hello + Check Log Message ${tc[0, 0]} \${var} = Hello Set Variable With More Or Less Than One Value Check Test Case ${TESTNAME} Set Local Variable - Scalars ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[1].msgs[0]} \${scalar} = Hello world + Check Log Message ${tc[1, 0]} \${scalar} = Hello world Set Local Variable - Lists ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[3].msgs[0]} \@{list} = [ One | Two | Three ] - Check Log Message ${tc.kws[6].msgs[0]} \@{list} = [ 1 | 2 | 3 ] + Check Log Message ${tc[3, 0]} \@{list} = [ One | Two | Three ] + Check Log Message ${tc[6, 0]} \@{list} = [ 1 | 2 | 3 ] Set Local Variable - Dicts ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[4].msgs[0]} \&{DICT} = { a=1 | 2=b } + Check Log Message ${tc[4, 0]} \&{DICT} = { a=1 | 2=b } Set Local Variables Overrides Test Variables Check Test Case ${TESTNAME} @@ -56,7 +56,7 @@ Set Test Variable Needing Escaping Set Test Variable Affect Subsequent Keywords ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].doc} Makes a variable available everywhere within the scope of the current test. + Should Be Equal ${tc[0].doc} Makes a variable available everywhere within the scope of the current test. Set Test Variable In User Keyword Check Test Case ${TESTNAME} @@ -67,12 +67,18 @@ Set Test Variable Not Affecting Other Tests Test Variables Set In One Suite Are Not Available In Another Check Test Case ${TESTNAME} -Set Test Variable cannot be used in suite setup or teardown +Test variables set on suite level is not seen in tests + Check Test Case ${TESTNAME} + +Test variable set on suite level does not hide existing suite variable + Check Test Case ${TESTNAME} + +Test variable set on suite level can be overridden as suite variable Check Test Case ${TESTNAME} Set Task Variable as alias for Set Test Variable ${tc} = Check Test Case ${TESTNAME} - Should Be Equal ${tc.kws[0].doc} Makes a variable available everywhere within the scope of the current task. + Should Be Equal ${tc[0].doc} Makes a variable available everywhere within the scope of the current task. Set Suite Variable Check Test Case ${TESTNAME} 1 @@ -174,7 +180,7 @@ Setting scalar global variable with list value is not possible Check Test Case ${TEST NAME} 1 Check Test Case ${TEST NAME} 2 -*** Keyword *** +*** Keywords *** Check Suite Teardown Passed ${suite} = Get Test Suite Variables Should Be Equal ${suite.teardown.status} PASS diff --git a/atest/robot/standard_libraries/builtin/should_be_equal.robot b/atest/robot/standard_libraries/builtin/should_be_equal.robot index 30f8f35dd31..9469e0caf25 100644 --- a/atest/robot/standard_libraries/builtin/should_be_equal.robot +++ b/atest/robot/standard_libraries/builtin/should_be_equal.robot @@ -5,11 +5,11 @@ Resource builtin_resource.robot *** Test Cases *** Basics ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} - Verify argument type message ${tc.kws[1].msgs[0]} - Verify argument type message ${tc.kws[2].msgs[0]} float int - Verify argument type message ${tc.kws[3].msgs[0]} bytes bytes - Verify argument type message ${tc.kws[4].msgs[0]} + Verify argument type message ${tc[0, 0]} + Verify argument type message ${tc[1, 0]} + Verify argument type message ${tc[2, 0]} float int + Verify argument type message ${tc[3, 0]} bytes bytes + Verify argument type message ${tc[4, 0]} Case-insensitive Check Test Case ${TESTNAME} @@ -37,11 +37,11 @@ Fails without values Multiline comparison uses diff ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[1]} foo\nbar\ndar\n\n!=\n\nfoo\nbar\ngar\n\ndar + Check Log Message ${tc[0, 1]} foo\nbar\ndar\n\n!=\n\nfoo\nbar\ngar\n\ndar Multiline comparison with custom message ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[1]} foo\nbar\ndar\n\n!=\n\nfoo\nbar\ngar\n\ndar + Check Log Message ${tc[0, 1]} foo\nbar\ndar\n\n!=\n\nfoo\nbar\ngar\n\ndar Multiline comparison requires both multiline Check test case ${TESTNAME} @@ -57,17 +57,17 @@ formatter=repr/ascii with non-ASCII characters formatter=repr with multiline ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[1]} foo\nbar\ndar\n\n!=\n\nfoo\nbar\ngar\n\ndar + Check Log Message ${tc[0, 1]} foo\nbar\ndar\n\n!=\n\nfoo\nbar\ngar\n\ndar formatter=repr with multiline and different line endings ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[1]} 1\n2\n3\n\n!=\n\n1\n2\n3 - Check Log Message ${tc.kws[1].msgs[1]} 1\n2\n3\n\n!=\n\n1\n2\n3 + Check Log Message ${tc[0, 1]} 1\n2\n3\n\n!=\n\n1\n2\n3 + Check Log Message ${tc[1, 1]} 1\n2\n3\n\n!=\n\n1\n2\n3 formatter=repr/ascii with multiline and non-ASCII characters ${tc} = Check test case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[1]} Å\nÄ\n\Ö\n\n!=\n\nÅ\nÄ\n\Ö - Check Log Message ${tc.kws[1].msgs[1]} Å\nÄ\n\Ö\n\n!=\n\nÅ\nÄ\n\Ö + Check Log Message ${tc[0, 1]} Å\nÄ\n\Ö\n\n!=\n\nÅ\nÄ\n\Ö + Check Log Message ${tc[1, 1]} Å\nÄ\n\Ö\n\n!=\n\nÅ\nÄ\n\Ö Invalid formatter Check test case ${TESTNAME} @@ -80,22 +80,22 @@ Dictionaries of different type with same items pass Bytes containing non-ascii characters ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} bytes bytes - Verify argument type message ${tc.kws[1].msgs[0]} bytes bytes + Verify argument type message ${tc[0, 0]} bytes bytes + Verify argument type message ${tc[1, 0]} bytes bytes Unicode and bytes with non-ascii characters ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} bytes str + Verify argument type message ${tc[0, 0]} bytes str Types info is added if string representations are same ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} str int + Verify argument type message ${tc[0, 0]} str int Should Not Be Equal ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} str str - Verify argument type message ${tc.kws[1].msgs[0]} str int - Verify argument type message ${tc.kws[2].msgs[0]} str str + Verify argument type message ${tc[0, 0]} str str + Verify argument type message ${tc[1, 0]} str int + Verify argument type message ${tc[2, 0]} str str Should Not Be Equal case-insensitive Check Test Case ${TESTNAME} @@ -117,6 +117,6 @@ Should Not Be Equal and collapse spaces Should Not Be Equal with bytes containing non-ascii characters ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} bytes bytes - Verify argument type message ${tc.kws[1].msgs[0]} bytes str - Verify argument type message ${tc.kws[2].msgs[0]} bytes bytes + Verify argument type message ${tc[0, 0]} bytes bytes + Verify argument type message ${tc[1, 0]} bytes str + Verify argument type message ${tc[2, 0]} bytes bytes diff --git a/atest/robot/standard_libraries/builtin/should_be_equal_as_xxx.robot b/atest/robot/standard_libraries/builtin/should_be_equal_as_xxx.robot index 15d42822d4e..c571788cffc 100644 --- a/atest/robot/standard_libraries/builtin/should_be_equal_as_xxx.robot +++ b/atest/robot/standard_libraries/builtin/should_be_equal_as_xxx.robot @@ -5,35 +5,35 @@ Resource builtin_resource.robot *** Test Cases *** Should Be Equal As Integers ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} + Verify argument type message ${tc[0, 0]} Should Be Equal As Integers with base Check test case ${TESTNAME} Should Not Be Equal As Integers ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} + Verify argument type message ${tc[0, 0]} Should Not Be Equal As Integers with base Check test case ${TESTNAME} Should Be Equal As Numbers ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} + Verify argument type message ${tc[0, 0]} Should Be Equal As Numbers with precision Check test case ${TESTNAME} Should Not Be Equal As Numbers ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} + Verify argument type message ${tc[0, 0]} Should Not Be Equal As Numbers with precision Check test case ${TESTNAME} Should Be Equal As Strings ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} int + Verify argument type message ${tc[0, 0]} int Should Be Equal As Strings does NFC normalization Check test case ${TESTNAME} @@ -70,7 +70,7 @@ Should Be Equal As Strings repr multiline Should Not Be Equal As Strings ${tc}= Check test case ${TESTNAME} - Verify argument type message ${tc.kws[0].msgs[0]} str float + Verify argument type message ${tc[0, 0]} str float Should Not Be Equal As Strings case-insensitive Check test case ${TESTNAME} diff --git a/atest/robot/cli/dryrun/reserved.robot b/atest/robot/standard_libraries/builtin/should_be_equal_type_conversion.robot similarity index 50% rename from atest/robot/cli/dryrun/reserved.robot rename to atest/robot/standard_libraries/builtin/should_be_equal_type_conversion.robot index 30f74ad484f..752d7ad340b 100644 --- a/atest/robot/cli/dryrun/reserved.robot +++ b/atest/robot/standard_libraries/builtin/should_be_equal_type_conversion.robot @@ -1,40 +1,37 @@ *** Settings *** -Suite Setup Run Tests --dryrun cli/dryrun/reserved.robot +Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/should_be_equal_type_conversion.robot Resource atest_resource.robot *** Test Cases *** -For +Convert second argument using `type` Check Test Case ${TESTNAME} -Valid END after For +Automatic `type` Check Test Case ${TESTNAME} -If +Automatic `type` doesn't handle nested types Check Test Case ${TESTNAME} -Else If +First argument must match `type` Check Test Case ${TESTNAME} -Else +Conversion fails with `type` Check Test Case ${TESTNAME} -Else inside valid IF +Invalid type with `type` Check Test Case ${TESTNAME} -Else If inside valid IF +Convert both arguments using `types` Check Test Case ${TESTNAME} -End +Conversion fails with `types` Check Test Case ${TESTNAME} -End after valid FOR header +Invalid type with `types` Check Test Case ${TESTNAME} -End after valid If header +Cannot use both `type` and `types` Check Test Case ${TESTNAME} -Reserved inside FOR - Check Test Case ${TESTNAME} - -Reserved inside IF +Automatic type doesn't work with `types` Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/should_contain.robot b/atest/robot/standard_libraries/builtin/should_contain.robot index 148c1dc50ba..2e90122a0d2 100644 --- a/atest/robot/standard_libraries/builtin/should_contain.robot +++ b/atest/robot/standard_libraries/builtin/should_contain.robot @@ -27,6 +27,12 @@ Should Contain and do not collapse spaces Should Contain and collapse spaces Check Test Case ${TESTNAME} +Should Contain with bytes + Check Test Case ${TESTNAME} + +Should Contain with bytearray + Check Test Case ${TESTNAME} + Should Not Contain Check test case ${TESTNAME} diff --git a/atest/robot/standard_libraries/builtin/sleep.robot b/atest/robot/standard_libraries/builtin/sleep.robot index fbfc2b8a254..454392bdafa 100644 --- a/atest/robot/standard_libraries/builtin/sleep.robot +++ b/atest/robot/standard_libraries/builtin/sleep.robot @@ -5,24 +5,23 @@ Resource atest_resource.robot *** Test Cases *** Sleep ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[1].msgs[0]} Slept 1 second 111 milliseconds - Check Log Message ${tc.kws[3].msgs[0]} Slept 1 second 234 milliseconds - Check Log Message ${tc.kws[5].msgs[0]} Slept 1 second 112 milliseconds + Check Log Message ${tc[1, 0]} Slept 1 second 111 milliseconds. + Check Log Message ${tc[3, 0]} Slept 1 second 234 milliseconds. + Check Log Message ${tc[5, 0]} Slept 1 second 112 milliseconds. Sleep With Negative Time ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[1].msgs[0]} Slept 0 seconds - Check Log Message ${tc.kws[2].msgs[0]} Slept 0 seconds + Check Log Message ${tc[1, 0]} Slept 0 seconds. + Check Log Message ${tc[2, 0]} Slept 0 seconds. Sleep With Reason ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Slept 42 milliseconds - Check Log Message ${tc.kws[0].msgs[1]} No good reason + Check Log Message ${tc[0, 0]} Slept 42 milliseconds. + Check Log Message ${tc[0, 1]} No good reason Invalid Time Does Not Cause Uncatchable Error Check Test Case ${TESTNAME} Can Stop Sleep With Timeout ${tc}= Check Test Case ${TESTNAME} - Should Be True ${tc.elapsedtime} < 10000 - + Elapsed Time Should Be Valid ${tc.elapsed_time} maximum=10 diff --git a/atest/robot/standard_libraries/builtin/tags.robot b/atest/robot/standard_libraries/builtin/tags.robot index b3b5792ae69..0a4bf8eca0e 100644 --- a/atest/robot/standard_libraries/builtin/tags.robot +++ b/atest/robot/standard_libraries/builtin/tags.robot @@ -1,61 +1,61 @@ *** Settings *** -Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/tags -Resource atest_resource.robot +Suite Setup Run Tests ${EMPTY} standard_libraries/builtin/tags +Resource atest_resource.robot *** Variables *** -@{SUITE_TAGS} default force force-init set set-init +@{SUITE_TAGS} default force force-init set set-init *** Test Cases *** Set And Remove Tags In Suite Level - Should Have Only Suite Tags Set And Remove Tags In Suite Level + Should Have Only Suite Tags Set And Remove Tags In Suite Level Set No Tags - Should Have Only Suite Tags Set No Tags + Should Have Only Suite Tags Set No Tags Set One Tag - ${tc} = Tags Should Have Been Added Set One Tag one - Check Log Message ${tc.kws[0].msgs[0]} Set tag 'one'. + ${tc} = Tags Should Have Been Added Set One Tag one + Check Log Message ${tc[0, 0]} Set tag 'one'. Set Multiple Tags - ${tc} = Tags Should Have Been Added Set Multiple Tags 1 2 3 HELLO Some spaces here - Check Log Message ${tc.kws[0].msgs[0]} Set tags '1', '2' and '3'. - Check Log Message ${tc.kws[1].msgs[0]} Set tags 'HELLO', '' and 'Some spaces here'. + ${tc} = Tags Should Have Been Added Set Multiple Tags 1 2 3 HELLO Some spaces here + Check Log Message ${tc[0, 0]} Set tags '1', '2' and '3'. + Check Log Message ${tc[1, 0]} Set tags 'HELLO', '' and 'Some spaces here'. Tags Set In One Test Are Not Visible To Others - Should Have Only Suite Tags Tags Set In One Test Are Not Visible To Others + Should Have Only Suite Tags Tags Set In One Test Are Not Visible To Others Remove No Tags - Should Have Only Suite Tags Remove No Tags + Should Have Only Suite Tags Remove No Tags Remove One Tag - ${tc} = Tags Should Have Been Removed Remove One Tag force - Check Log Message ${tc.kws[0].msgs[0]} Removed tag 'force'. + ${tc} = Tags Should Have Been Removed Remove One Tag force + Check Log Message ${tc[0, 0]} Removed tag 'force'. Remove Non-Existing Tag - Should Have Only Suite Tags Remove Non-Existing Tag + Should Have Only Suite Tags Remove Non-Existing Tag Remove Multiple Tags - ${tc} = Tags Should Have Been Removed Remove Multiple Tags default set set-init - Check Log Message ${tc.kws[0].msgs[0]} Removed tags 'default', 'SET' and 'non-existing'. - Check Log Message ${tc.kws[1].msgs[0]} Removed tags '' and 'set-init'. + ${tc} = Tags Should Have Been Removed Remove Multiple Tags default set set-init + Check Log Message ${tc[0, 0]} Removed tags 'default', 'SET' and 'non-existing'. + Check Log Message ${tc[1, 0]} Removed tags '' and 'set-init'. Remove Tags With Pattern - Check Test Tags Remove Tags With Pattern + Check Test Tags Remove Tags With Pattern Tags Removed In One Test Are Not Removed From Others - Should Have Only Suite Tags Tags Removed In One Test Are Not Removed From Others + Should Have Only Suite Tags Tags Removed In One Test Are Not Removed From Others Set And Remove Tags In A User Keyword - Check Test Tags Set And Remove Tags In A User Keyword tc uk uk2 + Check Test Tags Set And Remove Tags In A User Keyword tc uk uk2 Set Tags In Test Setup - Check Test Tags Set Tags In Test Setup set-init setup tag + Check Test Tags Set Tags In Test Setup set-init setup tag Set Tags In Test Teardown - Check Test Tags Set Tags In Test Teardown set-init teardown + Check Test Tags Set Tags In Test Teardown set-init teardown Using Set And Remove Tags In Suite Teardown Fails - Should Be Equal ${SUITE.suites[1].message} Suite teardown failed:\n'Set Tags' cannot be used in suite teardown. + Should Be Equal ${SUITE.suites[1].message} Suite teardown failed:\n'Set Tags' cannot be used in suite teardown. Modifying ${TEST TAGS} after setting them has no affect on tags test has Check Test Tags ${TEST NAME} force-init set-init new @@ -65,19 +65,19 @@ Modifying ${TEST TAGS} after removing them has no affect on tags test has *** Keywords *** Should Have Only Suite Tags - [Arguments] ${testname} - Check Test Tags ${testname} @{SUITE_TAGS} + [Arguments] ${testname} + Check Test Tags ${testname} @{SUITE_TAGS} Tags Should Have Been Added - [Arguments] ${testname} @{added} - @{tags} = Create List @{SUITE_TAGS} @{added} - Sort List ${tags} - ${tc} = Check Test Tags ${testname} @{tags} - [Return] ${tc} + [Arguments] ${testname} @{added} + @{tags} = Create List @{SUITE_TAGS} @{added} + Sort List ${tags} + ${tc} = Check Test Tags ${testname} @{tags} + RETURN ${tc} Tags Should Have Been Removed - [Arguments] ${testname} @{removed} - @{tags} = Copy List ${SUITE_TAGS} - Remove Values From List ${tags} @{removed} - ${tc} = Check Test Tags ${testname} @{tags} - [Return] ${tc} + [Arguments] ${testname} @{removed} + @{tags} = Copy List ${SUITE_TAGS} + Remove Values From List ${tags} @{removed} + ${tc} = Check Test Tags ${testname} @{tags} + RETURN ${tc} diff --git a/atest/robot/standard_libraries/builtin/used_in_custom_libs_and_listeners.robot b/atest/robot/standard_libraries/builtin/used_in_custom_libs_and_listeners.robot index 8c2293677cf..347a7762ea4 100644 --- a/atest/robot/standard_libraries/builtin/used_in_custom_libs_and_listeners.robot +++ b/atest/robot/standard_libraries/builtin/used_in_custom_libs_and_listeners.robot @@ -8,31 +8,32 @@ Resource atest_resource.robot *** Test Cases *** Keywords Using BuiltIn ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Log level changed from INFO to DEBUG. - Check Log Message ${tc.kws[0].msgs[1]} Hello, debug world! DEBUG + Check Log Message ${tc[0, 0]} Log level changed from NONE to DEBUG. DEBUG + Check Log Message ${tc[0, 1]} Hello, debug world! DEBUG + Length should be ${tc[0].messages} 2 Listener Using BuiltIn Check Test Case ${TESTNAME} Use 'Run Keyword' with non-Unicode values ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} 42 - Check Log Message ${tc.kws[0].kws[1].msgs[0]} \\xff + Check Log Message ${tc[0, 0, 0]} 42 + Check Log Message ${tc[0, 1, 0]} \xff Use BuiltIn keywords with timeouts ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} Test timeout 1 day active. * seconds left. level=DEBUG pattern=True - Check Log Message ${tc.kws[0].msgs[1]} Log level changed from INFO to DEBUG. - Check Log Message ${tc.kws[0].msgs[2]} Hello, debug world! DEBUG - Check Log Message ${tc.kws[3].kws[0].msgs[0]} Test timeout 1 day active. * seconds left. level=DEBUG pattern=True - Check Log Message ${tc.kws[3].kws[0].msgs[1]} 42 - Check Log Message ${tc.kws[3].kws[1].msgs[0]} Test timeout 1 day active. * seconds left. level=DEBUG pattern=True - Check Log Message ${tc.kws[3].kws[1].msgs[1]} \\xff + Check Log Message ${tc[0, 0]} Log level changed from NONE to DEBUG. DEBUG + Check Log Message ${tc[0, 1]} Hello, debug world! DEBUG + Length should be ${tc[0].messages} 2 + Check Log Message ${tc[3, 0, 0]} Test timeout 1 day active. * seconds left. level=DEBUG pattern=True + Check Log Message ${tc[3, 0, 1]} 42 + Check Log Message ${tc[3, 1, 0]} Test timeout 1 day active. * seconds left. level=DEBUG pattern=True + Check Log Message ${tc[3, 1, 1]} \xff User keyword used via 'Run Keyword' ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} This is x-911-zzz + Check Log Message ${tc[0, 0, 0, 0]} This is x-911-zzz User keyword used via 'Run Keyword' with timeout and trace level ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[1]} This is x-911-zzz + Check Log Message ${tc[0, 1, 0, 1]} This is x-911-zzz diff --git a/atest/robot/standard_libraries/builtin/wait_until_keyword_succeeds.robot b/atest/robot/standard_libraries/builtin/wait_until_keyword_succeeds.robot index 6fb39ca708b..da2e5d8b791 100644 --- a/atest/robot/standard_libraries/builtin/wait_until_keyword_succeeds.robot +++ b/atest/robot/standard_libraries/builtin/wait_until_keyword_succeeds.robot @@ -6,20 +6,20 @@ Resource atest_resource.robot Fail Because Timeout exceeded ${tc} = Check Test Case ${TESTNAME} # Cannot test exactly how many times kw is run because it depends on interpreter speed. - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Still 2 times to fail! FAIL - Should Be True len($tc.kws[0].kws) < 4 + Check Log Message ${tc[0, 0, 0]} Still 2 times to fail! FAIL + Should Be True len($tc[0].non_messages) < 4 Pass with first Try ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Used to test that variable name, not value, is shown in arguments - Length Should Be ${tc.kws[0].kws} 1 + Check Log Message ${tc[0, 0, 0]} Used to test that variable name, not value, is shown in arguments + Length Should Be ${tc[0].body} 1 Pass With Some Medium Try ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].msgs[0]} Still 2 times to fail! FAIL - Check Log Message ${tc.kws[0].kws[1].msgs[0]} Still 1 times to fail! FAIL - Check Log Message ${tc.kws[0].kws[2].msgs[0]} Still 0 times to fail! FAIL - Length Should Be ${tc.kws[0].kws} 4 + Check Log Message ${tc[0, 0, 0]} Still 2 times to fail! FAIL + Check Log Message ${tc[0, 1, 0]} Still 1 times to fail! FAIL + Check Log Message ${tc[0, 2, 0]} Still 0 times to fail! FAIL + Length Should Be ${tc[0].body} 4 Pass With Last Possible Try Check Test Case ${TESTNAME} @@ -69,51 +69,57 @@ Retry count must be positive Check Test Case ${TESTNAME} 1 Check Test Case ${TESTNAME} 2 -Invalid Number Of Arguments Inside Wait Until Keyword Succeeds +No retry after syntax error Check Test Case ${TESTNAME} -Invalid Keyword Inside Wait Until Keyword Succeeds +No retry if keyword name is not string Check Test Case ${TESTNAME} -Keyword Not Found Inside Wait Until Keyword Succeeds +Retry if keyword is not found Check Test Case ${TESTNAME} -Fail With Nonexisting Variable Inside Wait Until Keyword Succeeds +Retry if wrong number of arguments + Check Test Case ${TESTNAME} + +Retry if variable is not found ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Variable '\${nonexisting}' not found. FAIL - Check Log Message ${tc.kws[0].kws[1].kws[0].msgs[0]} Variable '\${nonexisting}' not found. FAIL - Check Log Message ${tc.kws[0].kws[2].kws[0].msgs[0]} Variable '\${nonexisting}' not found. FAIL - Length Should Be ${tc.kws[0].kws} 3 + Check Log Message ${tc[0, 0, 0, 0]} Variable '\${nonexisting}' not found. FAIL + Check Log Message ${tc[0, 1, 0, 0]} Variable '\${nonexisting}' not found. FAIL + Check Log Message ${tc[0, 2, 0, 0]} Variable '\${nonexisting}' not found. FAIL + Length Should Be ${tc[0].non_messages} 3 Pass With Initially Nonexisting Variable Inside Wait Until Keyword Succeeds ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].kws[0].kws[0].msgs[0]} Variable '\${created after accessing first time}' not found. FAIL - Check Log Message ${tc.kws[0].kws[1].kws[0].msgs[0]} created in keyword teardown - Length Should Be ${tc.kws[0].kws} 2 + Check Log Message ${tc[0, 0, 0, 0]} Variable '\${created after accessing first time}' not found. FAIL + Check Log Message ${tc[0, 1, 0, 0]} created in keyword teardown + Length Should Be ${tc[0].body} 2 Variable Values Should Not Be Visible In Keyword Arguments ${tc} = Check Test Case Pass With First Try - Check Keyword Data ${tc.kws[0].kws[0]} BuiltIn.Log args=\${HELLO} + Check Keyword Data ${tc[0, 0]} BuiltIn.Log args=\${HELLO} Strict retry interval ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.body[0].kws} 4 - Should Be True 300 <= ${tc.body[0].elapsedtime} < 900 + Length Should Be ${tc[0].body} 4 + Elapsed Time Should Be Valid ${tc[0].elapsed_time} minimum=0.3 maximum=0.9 Fail with strict retry interval ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.body[0].kws} 3 - Should Be True 200 <= ${tc.body[0].elapsedtime} < 600 + Length Should Be ${tc[0].non_messages} 3 + Elapsed Time Should Be Valid ${tc[0].elapsed_time} minimum=0.2 maximum=0.6 Strict retry interval violation ${tc} = Check Test Case ${TESTNAME} - Length Should Be ${tc.body[0].kws} 4 - Should Be True 400 <= ${tc.body[0].elapsedtime} < 1200 + Length Should Be ${tc[0].non_messages} 4 + Elapsed Time Should Be Valid ${tc[0].elapsed_time} minimum=0.4 maximum=1.2 FOR ${index} IN 1 3 5 7 - Check Log Message ${tc.body[0].body[${index}]} + Check Log Message ${tc[0, ${index}]} ... Keyword execution time ??? milliseconds is longer than retry interval 100 milliseconds. ... WARN pattern=True END Strict and invalid retry interval Check Test Case ${TESTNAME} + +Keyword name as variable + Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/collections/dictionaries_should_be_equal.robot b/atest/robot/standard_libraries/collections/dictionaries_should_be_equal.robot new file mode 100644 index 00000000000..bf677da6fb9 --- /dev/null +++ b/atest/robot/standard_libraries/collections/dictionaries_should_be_equal.robot @@ -0,0 +1,73 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} standard_libraries/collections/dictionaries_should_be_equal.robot +Resource atest_resource.robot + +*** Test Cases *** +Comparison with itself + Check Test Case ${TESTNAME} + +Keys in different order + Check Test Case ${TESTNAME} + +Different dictionary types + Check Test Case ${TESTNAME} + +First dictionary missing keys + Check Test Case ${TESTNAME} + +Second dictionary missing keys + Check Test Case ${TESTNAME} + +Both dictionaries missing keys + Check Test Case ${TESTNAME} + +Missing keys and custom error message + Check Test Case ${TESTNAME} + +Missing keys and custom error message with values + Check Test Case ${TESTNAME} + +Different values + Check Test Case ${TESTNAME} + +Different values and custom error message + Check Test Case ${TESTNAME} + +Different values and custom error message with values + Check Test Case ${TESTNAME} + +`ignore_keys` + Check Test Case ${TESTNAME} + +`ignore_keys` with non-string keys + Check Test Case ${TESTNAME} + +`ignore_keys` recursive + Check Test Case ${TESTNAME} + +`ignore_keys` with missing keys + Check Test Case ${TESTNAME} + +`ignore_keys` with wrong values + Check Test Case ${TESTNAME} + +`ignore_keys` as string must be valid expression + Check Test Case ${TESTNAME} + +`ignore_keys` must be list + Check Test Case ${TESTNAME} + +`ignore_case` + Check Test Case ${TESTNAME} + +`ignore_case` with ´ignore_keys` + Check Test Case ${TESTNAME} + +`ignore_case` when normalized keys have conflict + Check Test Case ${TESTNAME} + +`ignore_value_order` set to True + Check Test Case ${TESTNAME} + +`ignore_value_order` set to False and dictionaries have lists in different order + Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/collections/dictionary.robot b/atest/robot/standard_libraries/collections/dictionary.robot index c49cd0f96da..8a386a2a70b 100644 --- a/atest/robot/standard_libraries/collections/dictionary.robot +++ b/atest/robot/standard_libraries/collections/dictionary.robot @@ -18,9 +18,9 @@ Set To Dictionary With **kwargs Remove From Dictionary ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Removed item with key 'b' and value '2'. - Check Log Message ${tc.kws[0].msgs[1]} Key 'x' not found. - Check Log Message ${tc.kws[0].msgs[2]} Key '2' not found. + Check Log Message ${tc[0, 0]} Removed item with key 'b' and value '2'. + Check Log Message ${tc[0, 1]} Key 'x' not found. + Check Log Message ${tc[0, 2]} Key '2' not found. Keep In Dictionary Check Test Case ${TEST NAME} @@ -62,94 +62,7 @@ Get From Dictionary With Invalid Key Check Test Case ${TEST NAME} 1 Check Test Case ${TEST NAME} 2 -Dictionary Should Contain Key - Check Test Case ${TEST NAME} - -Dictionary Should Contain Key With Missing Key - Check Test Case ${TEST NAME} 1 - Check Test Case ${TEST NAME} 2 - -Dictionary Should Contain Item - Check Test Case ${TEST NAME} - -Dictionary Should Contain Item With Missing Key - Check Test Case ${TEST NAME} - -Dictionary Should Contain Item With Wrong Value - Check Test Case ${TEST NAME} - -Dictionary Should Not Contain Key - Check Test Case ${TEST NAME} - -Dictionary Should Not Contain Key With Existing Key - Check Test Case ${TEST NAME} - -Dictionary Should (Not) Contain Key Does Not Require `has_key` - Check Test Case ${TEST NAME} - -Dictionary Should Contain Value - Check Test Case ${TEST NAME} - Check Test Case ${TEST NAME} - -Dictionary Should Contain Value With Missing Value - Check Test Case ${TEST NAME} 1 - Check Test Case ${TEST NAME} 2 - -Dictionary Should Not Contain Value - Check Test Case ${TEST NAME} - -Dictionary Should Not Contain Value With Existing Value - Check Test Case ${TEST NAME} - -Dictionaries Should Be Equal - Check Test Case ${TEST NAME} - -Dictionaries Of Different Type Should Be Equal - Check Test Case ${TEST NAME} - -Dictionaries Should Equal With First Dictionary Missing Keys - Check Test Case ${TEST NAME} - -Dictionaries Should Equal With Second Dictionary Missing Keys - Check Test Case ${TEST NAME} - -Dictionaries Should Equal With Both Dictionaries Missing Keys - Check Test Case ${TEST NAME} - -Dictionaries Should Be Equal With Different Keys And Own Error Message - Check Test Case ${TEST NAME} - -Dictionaries Should Be Equal With Different Keys And Own And Default Error Messages - Check Test Case ${TEST NAME} - -Dictionaries Should Be Equal With Different Values - Check Test Case ${TEST NAME} - -Dictionaries Should Be Equal With Different Values And Own Error Message - Check Test Case ${TEST NAME} - -Dictionaries Should Be Equal With Different Values And Own And Default Error Messages - Check Test Case ${TEST NAME} - -Dictionary Should Contain Sub Dictionary - Check Test Case ${TEST NAME} - -Dictionary Should Contain Sub Dictionary With Missing Keys - Check Test Case ${TEST NAME} - -Dictionary Should Contain Sub Dictionary With Missing Keys And Own Error Message - Check Test Case ${TEST NAME} - -Dictionary Should Contain Sub Dictionary With Missing Keys And Own And Default Error Message - Check Test Case ${TEST NAME} - -Dictionary Should Contain Sub Dictionary With Different Value - Check Test Case ${TEST NAME} - -Dictionary Should Contain Sub Dictionary With Different Value And Own Error Message - Check Test Case ${TEST NAME} - -Dictionary Should Contain Sub Dictionary With Different Value And Own And Default Error Message +Get From Dictionary With Default Check Test Case ${TEST NAME} Log Dictionary With Different Log Levels @@ -159,17 +72,17 @@ Log Dictionary With Different Log Levels ... a: 1 ... b: 2 ... c: - Check Log Message ${tc.kws[0].msgs[0]} ${expected} INFO - Should Be Empty ${tc.kws[1].msgs} - Check Log Message ${tc.kws[2].msgs[0]} ${expected} WARN - Check Log Message ${tc.kws[3].msgs[0]} ${expected} DEBUG - Check Log Message ${tc.kws[4].msgs[0]} ${expected} INFO + Check Log Message ${tc[0, 0]} ${expected} INFO + Should Be Empty ${tc[1].body} + Check Log Message ${tc[2, 0]} ${expected} WARN + Check Log Message ${tc[3, 0]} ${expected} DEBUG + Check Log Message ${tc[4, 0]} ${expected} INFO Log Dictionary With Different Dictionaries ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} Dictionary is empty. - Check Log Message ${tc.kws[1].msgs[0]} Dictionary has one item:\na: 1 - Check Log Message ${tc.kws[3].msgs[0]} Dictionary size is 3 and it contains following items:\nTrue: xxx\nfoo: []\n(1, 2, 3): 3.14 + Check Log Message ${tc[0, 0]} Dictionary is empty. + Check Log Message ${tc[1, 0]} Dictionary has one item:\na: 1 + Check Log Message ${tc[3, 0]} Dictionary size is 3 and it contains following items:\nTrue: xxx\nfoo: []\n(1, 2, 3): 3.14 Pop From Dictionary Without Default Check Test Case ${TEST NAME} diff --git a/atest/robot/standard_libraries/collections/dictionary_should_contain.robot b/atest/robot/standard_libraries/collections/dictionary_should_contain.robot new file mode 100644 index 00000000000..c13ab3e559b --- /dev/null +++ b/atest/robot/standard_libraries/collections/dictionary_should_contain.robot @@ -0,0 +1,103 @@ +*** Settings *** +Suite Setup Run Tests ${EMPTY} standard_libraries/collections/dictionary_should_contain.robot +Resource atest_resource.robot + +*** Test Cases *** +Should contain key + Check Test Case ${TESTNAME} + +Should contain key with custom message + Check Test Case ${TESTNAME} + +Should contain key with `ignore_case` + Check Test Case ${TESTNAME} + +Should not contain key + Check Test Case ${TESTNAME} + +Should not contain key with custom message + Check Test Case ${TESTNAME} + +Should not contain key with `ignore_case` + Check Test Case ${TESTNAME} + +Should contain value + Check Test Case ${TESTNAME} + +Should contain value with custom message + Check Test Case ${TESTNAME} + +Should contain value with `ignore_case` + Check Test Case ${TESTNAME} + +Should not contain value + Check Test Case ${TESTNAME} + +Should not contain value with custom message + Check Test Case ${TESTNAME} + +Should not contain value with `ignore_case` + Check Test Case ${TESTNAME} + +Should contain item + Check Test Case ${TESTNAME} + +Should contain item with missing key + Check Test Case ${TESTNAME} + +Should contain item with missing key and custom message + Check Test Case ${TESTNAME} + +Should contain item with wrong value + Check Test Case ${TESTNAME} + +Should contain item with wrong value and custom message + Check Test Case ${TESTNAME} + +Should contain item with values looking same but having different types + Check Test Case ${TESTNAME} + +Should contain item with `ignore_case` + Check Test Case ${TESTNAME} + +Should contain item with `ignore_case=key` + Check Test Case ${TESTNAME} + +Should contain item with `ignore_case=value` + Check Test Case ${TESTNAME} + +Should contain sub dictionary + Check Test Case ${TESTNAME} + +Should contain sub dictionary with missing keys + Check Test Case ${TESTNAME} + +Should contain sub dictionary with missing keys and custom error message + Check Test Case ${TESTNAME} + +Should contain sub dictionary with missing keys and custom error message containig values + Check Test Case ${TESTNAME} + +Should contain sub dictionary with wrong value + Check Test Case ${TESTNAME} + +Should contain sub dictionary with wrong value and custom error message + Check Test Case ${TESTNAME} + +Should contain sub dictionary with wrong value and custom error message containing values + Check Test Case ${TESTNAME} + +Should contain sub dictionary with `ignore_case` + Check Test Case ${TESTNAME} + +`ignore_case` when normalized keys have conflict + Check Test Case ${TESTNAME} + +`has_key` is not required + Check Test Case ${TESTNAME} + +Should contain sub dictionary with `ignore_value_order` + Check Test Case ${TESTNAME} + +Should contain sub dictionary with `ignore_value_order` set to False when dictionaries have lists in different order + Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/collections/list.robot b/atest/robot/standard_libraries/collections/list.robot index 510e2d05fd2..75573b13e78 100644 --- a/atest/robot/standard_libraries/collections/list.robot +++ b/atest/robot/standard_libraries/collections/list.robot @@ -60,8 +60,8 @@ Remove From List With Invalid Index Remove Duplicates ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} 0 duplicates removed. - Check Log Message ${tc.kws[2].msgs[0]} 3 duplicates removed. + Check Log Message ${tc[0, 0]} 0 duplicates removed. + Check Log Message ${tc[2, 0]} 3 duplicates removed. Count Values In List Check Test Case ${TEST NAME} @@ -149,19 +149,19 @@ List Should Not Contain Duplicates Is Case And Space Sensitive List Should Not Contain Duplicates With One Duplicate ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[1].msgs[0]} 'item' found 2 times. + Check Log Message ${tc[1, 0]} 'item' found 2 times. List Should Not Contain Duplicates With Multiple Duplicates ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[1].msgs[0]} '2' found 2 times. - Check Log Message ${tc.kws[1].msgs[1]} 'None' found 2 times. - Check Log Message ${tc.kws[1].msgs[2]} '4' found 4 times. - Check Log Message ${tc.kws[1].msgs[3]} '[1, 2, 3]' found 2 times. - Check Log Message ${tc.kws[1].msgs[4]} '[]' found 10 times. + Check Log Message ${tc[1, 0]} '2' found 2 times. + Check Log Message ${tc[1, 1]} 'None' found 2 times. + Check Log Message ${tc[1, 2]} '4' found 4 times. + Check Log Message ${tc[1, 3]} '[1, 2, 3]' found 2 times. + Check Log Message ${tc[1, 4]} '[]' found 10 times. List Should Not Contain Duplicates With Custom Error Message ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[2].msgs[0]} '42' found 42 times. + Check Log Message ${tc[2, 0]} '42' found 42 times. Lists Should Be Equal Check Test Case ${TEST NAME} @@ -202,12 +202,18 @@ Lists Should Be Equal With Named Indices As Dictionary With Too Few Values Lists Should Be Equal Ignore Order Check Test Case ${TEST NAME} +Ignore Order Is Recursive + Check Test Case ${TEST NAME} + List Should Contain Sub List Check Test Case ${TEST NAME} List Should Contain Sub List With Missing Values Check Test Case ${TEST NAME} +List Should Contain Sub List When The Only Missing Value Is Empty String + Check Test Case ${TEST NAME} + List Should Contain Sub List With Missing Values And Own Error Message Check Test Case ${TEST NAME} @@ -221,18 +227,18 @@ Log List With Different Log Levels ... 0: 11 ... 1: 12 ... 2: 13 - Check Log Message ${tc.kws[0].msgs[0]} ${expected} INFO - Variable Should Not Exist ${tc.kws[1].msgs[0]} - Check Log Message ${tc.kws[2].msgs[0]} ${expected} WARN - Check Log Message ${tc.kws[3].msgs[0]} ${expected} DEBUG - Check Log Message ${tc.kws[4].msgs[0]} ${expected} INFO + Check Log Message ${tc[0, 0]} ${expected} INFO + Variable Should Not Exist ${tc[1, 0]} + Check Log Message ${tc[2, 0]} ${expected} WARN + Check Log Message ${tc[3, 0]} ${expected} DEBUG + Check Log Message ${tc[4, 0]} ${expected} INFO Log List With Different Lists ${tc} = Check Test Case ${TEST NAME} - Check Log Message ${tc.kws[0].msgs[0]} List is empty. INFO - Check Log Message ${tc.kws[1].msgs[0]} List has one item:\n1 - Check Log Message ${tc.kws[4].msgs[0]} List has one item:\n(1, 2, 3) - Check Log Message ${tc.kws[6].msgs[0]} List length is 2 and it contains following items:\n0: (1, 2, 3)\n1: 3.12 + Check Log Message ${tc[0, 0]} List is empty. INFO + Check Log Message ${tc[1, 0]} List has one item:\n1 + Check Log Message ${tc[4, 0]} List has one item:\n(1, 2, 3) + Check Log Message ${tc[6, 0]} List length is 2 and it contains following items:\n0: (1, 2, 3)\n1: 3.12 Count Matches In List Case Insensitive Check Test Case ${TEST NAME} @@ -329,3 +335,24 @@ List Should Not Contain Value, Value Found and Own Error Message Glob Check List Error Check Test Case ${TEST NAME} + +Lists Should Be Equal With Ignore Case + Check Test Case ${TEST NAME} + +List Should Contain Value With Ignore Case + Check Test Case ${TEST NAME} + +List Should Not Contain Value With Ignore Case Does Contain Value + Check Test Case ${TEST NAME} + +List Should Contain Sub List With Ignore Case + Check Test Case ${TEST NAME} + +List Should Not Contain Duplicates With Ignore Case + Check Test Case ${TEST NAME} + +List Should Contain Value With Ignore Case And Nested List and Dictionary + Check Test Case ${TEST NAME} + +Lists Should be equal with Ignore Case and Order + Check Test Case ${TEST NAME} diff --git a/atest/robot/standard_libraries/datetime/convert_date_input_format.robot b/atest/robot/standard_libraries/datetime/convert_date_input_format.robot index 95639489caf..a226ff6794a 100644 --- a/atest/robot/standard_libraries/datetime/convert_date_input_format.robot +++ b/atest/robot/standard_libraries/datetime/convert_date_input_format.robot @@ -18,6 +18,9 @@ Epoch Datetime object Check Test Case ${TESTNAME} +Date object + Check Test Case ${TESTNAME} + Pad zeroes to missing values Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/datetime/convert_date_result_format.robot b/atest/robot/standard_libraries/datetime/convert_date_result_format.robot index e3d5cc8f706..4771ca72642 100644 --- a/atest/robot/standard_libraries/datetime/convert_date_result_format.robot +++ b/atest/robot/standard_libraries/datetime/convert_date_result_format.robot @@ -23,6 +23,3 @@ Should exclude milliseconds Epoch time is float regardless are millis included or not Check Test Case ${TESTNAME} - -Formatted with %f in middle - Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/dialogs/dialogs.robot b/atest/robot/standard_libraries/dialogs/dialogs.robot index edbdfdb4e36..bb049c007e6 100644 --- a/atest/robot/standard_libraries/dialogs/dialogs.robot +++ b/atest/robot/standard_libraries/dialogs/dialogs.robot @@ -1,6 +1,6 @@ *** Settings *** Suite Setup Run Tests ${EMPTY} standard_libraries/dialogs/dialogs.robot -Force Tags manual no-ci +Test Tags manual no-ci Resource atest_resource.robot *** Test Cases *** @@ -40,9 +40,27 @@ Get Value From User Cancelled Get Value From User Exited Check Test Case ${TESTNAME} +Get Value From User Shortcuts + Check Test Case ${TESTNAME} + Get Selection From User Check Test Case ${TESTNAME} +Get Selection From User When Default Value Provided by Index + Check Test Case ${TESTNAME} + +Get Selection From User When Default Value Provided by String + Check Test Case ${TESTNAME} + +Get Selection From User When Default Value Is Integer + Check Test Case ${TESTNAME} + +Get Selection From User When Default Value Index Is Out of Bounds + Check Test Case ${TESTNAME} + +Get Selection From User When Default Value Cannot Be Found + Check Test Case ${TESTNAME} + Get Selection From User Cancelled Check Test Case ${TESTNAME} @@ -63,3 +81,9 @@ Get Selections From User Exited Multiple dialogs in a row Check Test Case ${TESTNAME} + +Garbage Collection In Thread Should Not Cause Problems + Check Test Case ${TESTNAME} + +Timeout can close dialog + Check Test Case ${TESTNAME} diff --git a/atest/robot/standard_libraries/easter.robot b/atest/robot/standard_libraries/easter.robot index 7876de7afb4..cf8097982c5 100644 --- a/atest/robot/standard_libraries/easter.robot +++ b/atest/robot/standard_libraries/easter.robot @@ -8,6 +8,6 @@ Not None Shall Not Pass None Shall Pass ${tc} = Check Test Case ${TESTNAME} - Check Log Message ${tc.kws[0].msgs[0]} + Check Log Message ${tc[0, 0]} ...