===================
Robot Framework 7.2
===================

.. default-role:: code

`Robot Framework`_ 7.2 is a feature release with JSON output support (`#3423`_),
`GROUP` syntax for grouping keywords and control structures (`#5257`_), new
Libdoc technology (`#4304`_) including translations (`#3676`_), and various
other features.

Questions and comments related to the release can be sent to the `#devel`
channel on `Robot Framework Slack`_ and possible bugs submitted to
the `issue tracker`_.

If you have pip_ installed, just run

::

   pip install --upgrade robotframework

to install the latest available release or use

::

   pip install robotframework==7.2

to install exactly this version. Alternatively you can download the package
from PyPI_ and install it manually. For more details and other installation
approaches, see the `installation instructions`_.

Robot Framework 7.2 was released on Tuesday January 14, 2025.
It has been superseded by `Robot Framework 7.2.1 <rf-7.2.1.rst>`_ and
`Robot Framework 7.2.2 <rf-7.2.2.rst>`_.

.. _Robot Framework: http://robotframework.org
.. _Robot Framework Foundation: http://robotframework.org/foundation
.. _pip: http://pip-installer.org
.. _PyPI: https://pypi.python.org/pypi/robotframework
.. _issue tracker milestone: https://github.com/robotframework/robotframework/issues?q=milestone%3Av7.2
.. _issue tracker: https://github.com/robotframework/robotframework/issues
.. _robotframework-users: http://groups.google.com/group/robotframework-users
.. _Slack: http://slack.robotframework.org
.. _Robot Framework Slack: Slack_
.. _installation instructions: ../../INSTALL.rst

.. contents::
   :depth: 2
   :local:

Most important enhancements
===========================

JSON output format
------------------

Robot Framework creates an output file during execution. The output file is
needed when the log and the report are generated after the execution, and
various external tools also use it to be able to show detailed execution
information.

The output file format has traditionally been XML, but Robot Framework 7.2
supports also JSON output files (`#3423`_). The format is detected automatically
based on the output file extension::

    robot --output output.json example.robot

If JSON output files are needed with earlier Robot Framework versions, it is
possible to use the Rebot tool that got support to generate JSON output files
already in `Robot Framework 7.0`__::

    rebot --output output.json output.xml

The format produced by the Rebot tool has changed in Robot Framework 7.2,
though, so possible tools already using JSON outputs need to be updated (`#5160`_).
The motivation for the change was adding statistics and execution errors also
to the JSON output to make it compatible with the XML output.

JSON output files created during execution and generated by Rebot use the same
format. To learn more about the format, see its `schema definition`__.

__ https://github.com/robotframework/robotframework/blob/master/doc/releasenotes/rf-7.0.rst#json-result-format
__ https://github.com/robotframework/robotframework/tree/master/doc/schema#readme

`GROUP` syntax
--------------

The new `GROUP` syntax (`#5257`_) allows grouping related keywords and control
structures together:

.. sourcecode:: robotframework

    *** Test Cases ***
    Valid login
        GROUP    Open browser to login page
            Open Browser    ${LOGIN URL}
            Title Should Be    Login Page
        END
        GROUP    Submit credentials
            Input Username    username_field    demo
            Input Password    password_field    mode
            Click Button    login_button
        END
        GROUP    Login should have succeeded
            Title Should Be    Welcome Page
        END

    Anonymous group
        GROUP
            Log    Group name is optional.
        END

    Nesting
        GROUP
            GROUP    Nested group
                Log    Groups can be nested.
            END
            IF    True
                GROUP
                    Log    Groups can also be nested with other control structures.
                END
            END
        END

As the above examples demonstrates, groups can have a name, but the name is
optional. Groups can also be nested freely with each others and with other
control structures.

User keywords are in general recommended over the `GROUP` syntax, because
they are reusable and because they simplify tests or keywords where they are
used by hiding lower level details. In the log file user keywords and groups
look the same, though, except that there is a `GROUP` label instead of
a `KEYWORD` label.

All groups within a test or a keyword share the same variable namespace.
This means that, unlike when using keywords, there is no need to use arguments
or return values for sharing values. This can be a benefit in simple cases,
but if there are lot of variables, the benefit can turn into a problem and
cause a huge mess.

`GROUP` with templates
~~~~~~~~~~~~~~~~~~~~~~

The `GROUP` syntax can be used for grouping iterations with test templates:

.. sourcecode:: robotframework

    *** Settings ***
    Library           String
    Test Template     Upper case should be

    *** Test Cases ***
    Template example
        GROUP    ASCII characters
            a    A
            z    Z
        END
        GROUP    Latin-1 characters
            ä    Ä
            ß    SS
        END
        GROUP    Numbers
            1    1
            9    9
        END

    *** Keywords ***
    Upper case should be
        [Arguments]    ${char}    ${expected}
        ${actual} =    Convert To Upper Case    ${char}
        Should Be Equal    ${actual}    ${expected}

Programmatic usage
~~~~~~~~~~~~~~~~~~

One of the primary usages for groups is making it possible to create structured
tests, tasks and keywords programmatically. For example, the following pre-run
modifier adds a group with two keywords at the end of each modified test. Groups
can be added also by listeners that use the listener API version 3.

.. sourcecode:: python

    from robot.api import SuiteVisitor


    class GroupAdder(SuiteVisitor):

        def start_test(self, test):
            group = test.body.create_group(name='Example')
            group.body.create_keyword(name='Log', args=['Hello, world!'])
            group.body.create_keyword(name='No Operation')

Enhancements for working with bytes
-----------------------------------

Bytes and binary data are used extensively in some domains. Working with them
has been enhanced in various ways:

- String representation of bytes outside the ASCII range has been fixed (`#5052`_).
  This affects, for example, logging bytes and embedding bytes to strings in
  arguments like `Header: ${value_in_bytes}`. A major benefit of the fix is that
  the resulting string can be converted back to bytes using, for example, automatic
  argument conversion.

- Concatenating variables containing bytes yields bytes (`#5259`_). For example,
  something like `${x}${y}${z}` is bytes if all variables are bytes. If any variable
  is not bytes or there is anything else than variables, the resulting value is
  a string.

- The `Should Be Equal` keyword got support for argument conversion (`#5053`_) that
  also works with bytes. For example,
  `Should Be Equal  ${value}  RF  type=bytes` validates that
  `${value}` is equal to `b'RF'`.

New Libdoc technology
---------------------

The Libdoc tools is used for generating documentation for libraries and resource
files. It can generate spec files in XML and JSON formats for editors and other
tools, but its most important usage is generating HTML documentation for humans.

Libdoc's HTML outputs have been totally rewritten using a new technology (`#4304`_).
The motivation was to move forward from jQuery templates that are not anymore
maintained and to have a better base to develop HTML outputs forward in general.
The plan is to use the same technology with Robot's log and report files in the
future.

The idea was not to change existing functionality in this release to make it
easier to compare results created with old and new Libdoc versions. An exception
to this rule was that Libdoc's HTML user interface got localization support (`#3676`_).
Robot Framework 7.2 contains Libdoc translations for Finnish, French, Dutch and
Portuguese in addition to English. New translations can be added, and existing
enhanced, in the future releases. Instructions how to do that can be found
here__ and you can ask help on the `#devel` channel on our Slack_ if needed.

__ https://github.com/robotframework/robotframework/tree/master/src/web#readme

Other major enhancements and fixes
----------------------------------

- As already mentioned when discussing enhancements to working with bytes,
  the `Should Be Equal` keyword got support for argument conversion (`#5053`_).
  It is not limited to bytes, but supports anything Robot's automatic argument
  conversion supports like lists and dictionaries, decimal numbers, dates and so on.

- Logging APIs now work if Robot Framework is run on a thread (`#5255`_).

- A class decorated with the `@library` decorator is recognized as a library
  regardless does its name match the module name or not (`#4959`_).

- Logged messages are added to the result model that is build during execution
  (`#5260`_). The biggest benefit is that messages are now available to listeners
  inspecting the model.

Backwards incompatible changes
==============================

We try to avoid backwards incompatible changes in general and limit bigger
changes to major releases. There are, however, some backwards incompatible
changes in this release, but they should affect only very few users.

Listeners are notified about actions they initiate
--------------------------------------------------

Earlier if a listener executed a keyword using `BuiltIn.run_keyword` or logged
something, listeners were not notified about these events. This meant that
listeners could not react to all actions that occurred during execution and
that the model build during execution did not match information listeners got.

The aforementioned problem has now been fixed and listeners are notified about
all keywords and messages (`#5268`_). This should not typically cause problems,
but there is a possibility for recursion if a listener does something
after it gets a notification about an action it initiated itself.

Messages logged by `start_test` and `end_test` listener methods are preserved
-----------------------------------------------------------------------------

Messages logged by `start_test` and `end_test` listeners methods using
`robot.api.logger` used to be ignored, but nowadays they are preserved (`#5266`_).
They are shown in the log file directly under the corresponding test and in
the result model they are in `TestCase.body` along with keywords and control
structures used by the test.

Messages in `TestCase.body` can cause problems with tools processing results
if they expect to see only keywords and control structures. This requires
tools processing results to be updated.

Showing these messages in the log file can add unnecessary noise. If that
happens, listeners need to be configured to log less or to log using a level
that is not visible by default.

Change to handling SKIP with templates
--------------------------------------

Earlier when a test with a template had multiple iterations and one of the
iterations was skipped, the whole test was stopped and it got the SKIP status.
Possible remaining iterations were not executed and possible earlier failures
were ignored. This behavior was inconsistent compared to how failures are
handled, because with them, all iterations are executed.

Nowadays all iterations are executed even if one or more of them is skipped
(`#4426`_). The aggregated result of a templated test with multiple iterations is:

- FAIL if any of the iterations failed.
- PASS if there were no failures and at least one iteration passed.
- SKIP if all iterations were skipped.

Changes to handling bytes
-------------------------

As discussed above, `working with bytes`__ has been enhanced so that string
representation for bytes outside ASCII range has been fixed (`#5052`_) and
concatenating variables containing bytes yields bytes (`#5259`_). Both of
these are useful enhancements, but users depending on the old behavior need
to update their tests or tasks.

__ `Enhancements for working with bytes`_

Other backwards incompatible changes
------------------------------------

- JSON output format produced by Rebot has changed (`#5160`_).
- Source distribution format has been changed from `zip` to `tar.gz`. The reason
  is that the Python source distributions format has been standardized to `tar.gz`
  by `PEP 625 <https://peps.python.org/pep-0625/>`__ and `zip` distributions are
  deprecated (`#5296`_).
- The `Message.html` attribute is serialized to JSON only if its value is `True`
  (`#5216`_).
- Module is not used as a library if it contains a class decorated with the
  `@library` decorator (`#4959`_).

Deprecated features
===================

Robot Framework 7.2 deprecates using a literal value like `-tag` for creating
tags starting with a hyphen using the `Test Tags` setting (`#5252`_). In the
future this syntax will be used for removing tags set in higher level suite
initialization files, similarly as the `-tag` syntax can nowadays be used with
the `[Tags]` setting. If tags starting with a hyphen are needed, it is possible
to use the escaped format like `\-tag` to create them.

Acknowledgements
================


Robot Framework development is sponsored by the `Robot Framework Foundation`_
and its over 70 member organizations. If your organization is using Robot Framework
and benefiting from it, consider joining the foundation to support its
development as well.

Robot Framework 7.2 team funded by the foundation consisted of `Pekka Klärck`_ and
`Janne Härkönen <https://github.com/yanne>`_. Janne worked only part-time and was
mainly responsible on Libdoc enhancements. In addition to work done by them, the
community has provided some great contributions:

- Libdoc translations (`#3676`_) were provided by the following persons:

  - Dutch by `Elout van Leeuwen <https://github.com/leeuwe>`__ and
    `J. Foederer <https://github.com/JFoederer>`__
  - French by `Gad Hassine <https://github.com/hassineabd>`__
  - Portuguese by `Hélio Guilherme <https://github.com/HelioGuilherme66>`__

- `René <https://github.com/Snooz82>`__ provided a pull request to implement
  the `GROUP`  syntax (`#5257`_).

- `Lajos Olah <https://github.com/olesz>`__ enhanced how the SKIP status works
  when using templates with multiple iterations (`#4426`_).

- `Marcin Gmurczyk <https://github.com/MarcinGmurczyk>`__ made it possible to
  ignore order in values when comparing dictionaries (`#5007`_).

- `Mohd Maaz Usmani <https://github.com/m-usmani>`__ added support to control
  the separator when appending to an existing value using `Set Suite Metadata`,
  `Set Test Documentation` and other such keywords (`#5215`_).

- `Luis Carlos <https://github.com/martinezlc99>`__ made the public API of
  the `robot.api.parsing` module explicit (`#5245`_).

- `Theodore Georgomanolis <https://github.com/theodore86>`__ fixed `logging`
  module usage so that the original log level is restored after execution (`#5262`_).

- `Johnny.H <https://github.com/jnhyperion>`__ enhanced error message when using
  the `Rebot` tool with an output file containing no tests or tasks (`#5312`_).

Big thanks to Robot Framework Foundation, to community members listed above, and to
everyone else who has tested preview releases, submitted bug reports, proposed
enhancements, debugged problems, or otherwise helped with Robot Framework 7.2
development.

| `Pekka Klärck <https://github.com/pekkaklarck>`_
| Robot Framework lead developer

Full list of fixes and enhancements
===================================

.. list-table::
    :header-rows: 1

    * - ID
      - Type
      - Priority
      - Summary
    * - `#3423`_
      - enhancement
      - critical
      - Support JSON output files as part of execution
    * - `#3676`_
      - enhancement
      - critical
      - Libdoc localizations
    * - `#4304`_
      - enhancement
      - critical
      - New technology for Libdoc HTML outputs
    * - `#5052`_
      - bug
      - high
      - Invalid string representation for bytes outside ASCII range
    * - `#5167`_
      - bug
      - high
      - Crash if listener executes library keyword in `end_test` in the dry-run mode
    * - `#5255`_
      - bug
      - high
      - Logging APIs do not work if Robot Framework is run on thread
    * - `#4959`_
      - enhancement
      - high
      - Recognize library classes decorated with `@library` decorator regardless their name
    * - `#5053`_
      - enhancement
      - high
      - Support argument conversion with `Should Be Equal`
    * - `#5160`_
      - enhancement
      - high
      - Add execution errors and statistics to JSON output generated by Rebot
    * - `#5257`_
      - enhancement
      - high
      - `GROUP` syntax for grouping keywords and control structures
    * - `#5260`_
      - enhancement
      - high
      - Add log messages to result model that is build during execution and available to listeners
    * - `#5170`_
      - bug
      - medium
      - Failure in suite setup initiates exit-on-failure even if all tests have skip-on-failure active
    * - `#5245`_
      - bug
      - medium
      - `robot.api.parsing` doesn't have properly defined public API
    * - `#5254`_
      - bug
      - medium
      - Libdoc performance degradation starting from RF 6.0
    * - `#5262`_
      - bug
      - medium
      - `logging` module log level is not restored after execution
    * - `#5266`_
      - bug
      - medium
      - Messages logged by `start_test` and `end_test` listener methods are ignored
    * - `#5268`_
      - bug
      - medium
      - Listeners are not notified about actions they initiate
    * - `#5269`_
      - bug
      - medium
      - Recreating control structure results from JSON fails if they have messages mixed with iterations/branches
    * - `#5274`_
      - bug
      - medium
      - Problems with recommentation to use `$var` syntax if expression evaluation fails
    * - `#5282`_
      - bug
      - medium
      - `lineno` of keywords executed by `Run Keyword` variants is `None` in dry-run
    * - `#5289`_
      - bug
      - medium
      - Status of library keywords that are executed in dry-run is `NOT RUN`
    * - `#4426`_
      - enhancement
      - medium
      - All iterations of templated tests should be executed even if one is skipped
    * - `#5007`_
      - enhancement
      - medium
      - Collections: Support ignoring order in values when comparing dictionaries
    * - `#5215`_
      - enhancement
      - medium
      - Support controlling separator when appending current value using `Set Suite Metadata`, `Set Test Documentation` and other such keywords
    * - `#5219`_
      - enhancement
      - medium
      - Support stopping execution using `robot:exit-on-failure` tag
    * - `#5223`_
      - enhancement
      - medium
      - Allow setting variables with TEST scope in suite setup/teardown (not visible for tests or child suites)
    * - `#5235`_
      - enhancement
      - medium
      - Document that `Get Variable Value` and `Variable Should (Not) Exist` do not support named-argument syntax
    * - `#5242`_
      - enhancement
      - medium
      - Support inline flags for configuring custom embedded argument patterns
    * - `#5251`_
      - enhancement
      - medium
      - Allow listeners to remove log messages by setting them to `None`
    * - `#5252`_
      - enhancement
      - medium
      - Deprecate setting tags starting with a hyphen like `-tag` in `Test Tags`
    * - `#5259`_
      - enhancement
      - medium
      - Concatenating variables containing bytes should yield bytes
    * - `#5264`_
      - enhancement
      - medium
      - If test is skipped using `--skip` or `--skip-on-failure`, show used tags in test's message
    * - `#5272`_
      - enhancement
      - medium
      - Enhance recursion detection
    * - `#5292`_
      - enhancement
      - medium
      - `robot:skip` and `robot:exclude` tags do not support variables
    * - `#5296`_
      - enhancement
      - medium
      - Change source distribution format from deprecated `zip` to `tar.gz`
    * - `#5202`_
      - bug
      - low
      - Per-fle language configuration fails if there are two or more spaces after `Language:` prefix
    * - `#5267`_
      - bug
      - low
      - Message passed to `log_message` listener method has wrong type
    * - `#5276`_
      - bug
      - low
      - Templates should be explicitly prohibited with WHILE
    * - `#5283`_
      - bug
      - low
      - Documentation incorrectly claims that `--tagdoc` documentation supports HTML formatting
    * - `#5288`_
      - bug
      - low
      - `Message.id` broken if parent is not `Keyword` or `ExecutionErrors`
    * - `#5295`_
      - bug
      - low
      - Duplicate test name detection does not take variables into account
    * - `#5309`_
      - bug
      - low
      - Bug in `Return From Keyword If` documentation
    * - `#5312`_
      - bug
      - low
      - Confusing error message when using `rebot` and output file contains no tests
    * - `#5155`_
      - enhancement
      - low
      - Document where `log-<index>.js` files created by `--splitlog` are saved
    * - `#5216`_
      - enhancement
      - low
      - Include `Message.html` in JSON results only if it is `True`
    * - `#5238`_
      - enhancement
      - low
      - Document return codes in `--help`
    * - `#5286`_
      - enhancement
      - low
      - Add suite and test `id` to JSON result model
    * - `#5287`_
      - enhancement
      - low
      - Add `type` attribute to `TestSuite` and `TestCase` objects

Altogether 48 issues. View on the `issue tracker <https://github.com/robotframework/robotframework/issues?q=milestone%3Av7.2>`__.

.. _#3423: https://github.com/robotframework/robotframework/issues/3423
.. _#3676: https://github.com/robotframework/robotframework/issues/3676
.. _#4304: https://github.com/robotframework/robotframework/issues/4304
.. _#5052: https://github.com/robotframework/robotframework/issues/5052
.. _#5167: https://github.com/robotframework/robotframework/issues/5167
.. _#5255: https://github.com/robotframework/robotframework/issues/5255
.. _#4959: https://github.com/robotframework/robotframework/issues/4959
.. _#5053: https://github.com/robotframework/robotframework/issues/5053
.. _#5160: https://github.com/robotframework/robotframework/issues/5160
.. _#5257: https://github.com/robotframework/robotframework/issues/5257
.. _#5260: https://github.com/robotframework/robotframework/issues/5260
.. _#5170: https://github.com/robotframework/robotframework/issues/5170
.. _#5245: https://github.com/robotframework/robotframework/issues/5245
.. _#5254: https://github.com/robotframework/robotframework/issues/5254
.. _#5262: https://github.com/robotframework/robotframework/issues/5262
.. _#5266: https://github.com/robotframework/robotframework/issues/5266
.. _#5268: https://github.com/robotframework/robotframework/issues/5268
.. _#5269: https://github.com/robotframework/robotframework/issues/5269
.. _#5274: https://github.com/robotframework/robotframework/issues/5274
.. _#5282: https://github.com/robotframework/robotframework/issues/5282
.. _#5289: https://github.com/robotframework/robotframework/issues/5289
.. _#4426: https://github.com/robotframework/robotframework/issues/4426
.. _#5007: https://github.com/robotframework/robotframework/issues/5007
.. _#5215: https://github.com/robotframework/robotframework/issues/5215
.. _#5219: https://github.com/robotframework/robotframework/issues/5219
.. _#5223: https://github.com/robotframework/robotframework/issues/5223
.. _#5235: https://github.com/robotframework/robotframework/issues/5235
.. _#5242: https://github.com/robotframework/robotframework/issues/5242
.. _#5251: https://github.com/robotframework/robotframework/issues/5251
.. _#5252: https://github.com/robotframework/robotframework/issues/5252
.. _#5259: https://github.com/robotframework/robotframework/issues/5259
.. _#5264: https://github.com/robotframework/robotframework/issues/5264
.. _#5272: https://github.com/robotframework/robotframework/issues/5272
.. _#5292: https://github.com/robotframework/robotframework/issues/5292
.. _#5296: https://github.com/robotframework/robotframework/issues/5296
.. _#5202: https://github.com/robotframework/robotframework/issues/5202
.. _#5267: https://github.com/robotframework/robotframework/issues/5267
.. _#5276: https://github.com/robotframework/robotframework/issues/5276
.. _#5283: https://github.com/robotframework/robotframework/issues/5283
.. _#5288: https://github.com/robotframework/robotframework/issues/5288
.. _#5295: https://github.com/robotframework/robotframework/issues/5295
.. _#5309: https://github.com/robotframework/robotframework/issues/5309
.. _#5312: https://github.com/robotframework/robotframework/issues/5312
.. _#5155: https://github.com/robotframework/robotframework/issues/5155
.. _#5216: https://github.com/robotframework/robotframework/issues/5216
.. _#5238: https://github.com/robotframework/robotframework/issues/5238
.. _#5286: https://github.com/robotframework/robotframework/issues/5286
.. _#5287: https://github.com/robotframework/robotframework/issues/5287
