Warm tip: This article is reproduced from stackoverflow.com, please click
robotframework

Robot FW : Collections library : "Copy Dictionary" : How to make a shallow copy of a compound dictio

发布于 2020-04-05 23:42:48

Consider the following code:

In Utils.py:

@keyword
def get_compound_dictionary():
    """
    https://docs.python.org/3/library/copy.html
    An example compound dictionary
    """
    return {'key1': 'value1', 'deep_dict': {'key2': 'value2'}}

In collection-library-tests.robot

*** Settings ***
Documentation    A test suite utilizing all collection library keywords
Library          Collections
Library          Utils.py

# To run:
# robot  --pythonpath Resources --noncritical failure-expected -d Results/  Tests/collection-    
  library-tests.robot

*** Test Cases ***
Use "Copy Dictionary" : Shallow Copy
    ${compound_python_dictionary} =     get compound dictionary
    &{shallow_copy} =   Copy Dictionary     ${compound_python_dictionary}       deepcopy=False

    # if we modify the contained objects (i.e. deep_dict) through the shallow_copy,
    # the original compound_python_dictionary will see the changes in the contained objects
    Set To Dictionary    ${shallow_copy}[deep_dict]     key2=modified
    Log     ${shallow_copy}
    Log     ${compound_python_dictionary}
    Should Be Equal      ${compound_python_dictionary}[deep_dict][key2]       modified  # fails, why?

The goal is stated in the test case as:

if we modify the contained objects (i.e. deep_dict) through the shallow_copy, the original compound_python_dictionary will see the changes in the contained objects

Expected Result

Should Be Equal      ${compound_python_dictionary}[deep_dict][key2]       modified  # passes

Observed Result enter image description here

Note that I am using Robot FW version: Robot Framework 3.1.2 (Python 3.7.4 on linux)

Acc.to the documentation about Copy Dictionary:

The deepcopy argument controls should the returned dictionary be a shallow or deep copy. By default returns a shallow copy, but that can be changed by giving deepcopy a true value (see Boolean arguments). This > is a new option in Robot Framework 3.1.2. Earlier versions always returned shallow copies.

Acc.to the documentation about Boolean Arguments:

Some keywords accept arguments that are handled as Boolean values true or false. If such an argument is given as a string, it is considered false if it is an empty string or equal to FALSE, NONE, NO, OFF or 0, case-insensitively. Other strings are considered true regardless their value.

Note also that i tried also deepcopy=${False}, which yielded the same observed result.

Questioner
HKN
Viewed
35
Todor Minakov 2020-02-01 01:00

The problem is not with the RF keyword (it very seldom is, they have extensive UT), but with the way you call it, namely this argument:

deepcopy=False

You may be thinking you are passing a boolean value, but in fact you are passing the string "False".
Inside the keyword's implementation there is this branching:

    if deepcopy:
        return copy.deepcopy(dictionary)

, and as a non-empty string evaluates to True, you are in fact getting a deep copy.

This is the way to pass a real False:

deepcopy=${False}