Giter VIP home page Giter VIP logo

robotframework-datadriver's Introduction

DataDriver for Robot Framework®

DataDriver is a Data-Driven extension for Robot Framework®. This document explains how to use the DataDriver library listener. For information about installation, support, and more, please visit the project page

For more information about Robot Framework®, see https://robotframework.org.

DataDriver is used/imported as Library but does not provide keywords which can be used in a test. DataDriver uses the Listener Interface Version 3 to manipulate the test cases and creates new test cases based on a Data-File that contains the data for Data-Driven Testing. These data file may be .csv , .xls or .xlsx files.

Data Driver is also able to cooperate with Microsoft PICT. An Open Source Windows tool for data combination testing. Pict is able to generate data combinations based on textual model definitions. https://github.com/Microsoft/pict

It is also possible to implement own DataReaders in Python to read your test data from some other sources, like databases or json files.

Installation

If you already have Python >= 3.6 with pip installed, you can simply run:

pip install --upgrade robotframework-datadriver

Excel Support

For file support of xls or xlsx file you need to install the extra XLS or the dependencies. It contains the dependencies of pandas, numpy and xlrd. Just add [XLS] to your installation. New since version 3.6.

pip install --upgrade robotframework-datadriver[XLS]

Python 2

or if you have Python 2 and 3 installed in parallel you may use

pip3 install --upgrade robotframework-datadriver

DataDriver is compatible with Python 2.7 only in Version 0.2.7.

pip install --upgrade robotframework-datadriver==0.2.7

Because Python 2.7 is deprecated, there are no new feature to python 2.7 compatible version.

Table of contents

What DataDriver Does

DataDriver is an alternative approach to create Data-Driven Tests with Robot Framework®. DataDriver creates multiple test cases based on a test template and data content of a csv or Excel file. All created tests share the same test sequence (keywords) and differ in the test data. Because these tests are created on runtime only the template has to be specified within the robot test specification and the used data are specified in an external data file.

RoboCon 2020 Talk

https://img.youtube.com/vi/RtEUr1i4x3s/0.jpg

Brief overview what DataDriver is and how it works at the RoboCon 2020 in Helsiki.

Alternative approach

DataDriver gives an alternative to the build in data driven approach like:

*** Settings ***
Resource    login_resources.robot

Suite Setup    Open my Browser
Suite Teardown    Close Browsers
Test Setup      Open Login Page
Test Template    Invalid login


*** Test Cases ***       User        Passwort
Right user empty pass    demo        ${EMPTY}
Right user wrong pass    demo        FooBar

Empty user right pass    ${EMPTY}    mode
Empty user empty pass    ${EMPTY}    ${EMPTY}
Empty user wrong pass    ${EMPTY}    FooBar

Wrong user right pass    FooBar      mode
Wrong user empty pass    FooBar      ${EMPTY}
Wrong user wrong pass    FooBar      FooBar

*** Keywords ***
Invalid login
    [Arguments]    ${username}    ${password}
    Input username    ${username}
    Input pwd    ${password}
    click login button
    Error page should be visible

This inbuilt approach is fine for a hand full of data and a hand full of test cases. If you have generated or calculated data and specially if you have a variable amount of test case / combinations these robot files become quite a pain. With DataDriver you may write the same test case syntax but only once and deliver the data from en external data file.

One of the rare reasons when Microsoft® Excel or LibreOffice Calc may be used in testing… ;-)

See example test suite

See example csv table

How DataDriver Works

When the DataDriver is used in a test suite it will be activated before the test suite starts. It uses the Listener Interface Version 3 of Robot Framework® to read and modify the test specification objects. After activation it searches for the Test Template -Keyword to analyze the [Arguments] it has. As a second step, it loads the data from the specified data source. Based on the Test Template -Keyword, DataDriver creates as much test cases as data sets are in the data source.

In the case that data source is csv (Default) As values for the arguments of the Test Template -Keyword, DataDriver reads values from the column of the CSV file with the matching name of the [Arguments]. For each line of the CSV data table, one test case will be created. It is also possible to specify test case names, tags and documentation for each test case in the specific test suite related CSV file.

Usage

Data Driver is a "Library Listener" but does not provide keywords. Because Data Driver is a listener and a library at the same time it sets itself as a listener when this library is imported into a test suite.

To use it, just use it as Library in your suite. You may use the first argument (option) which may set the file name or path to the data file.

Without any options set, it loads a .csv file which has the same name and path like the test suite .robot .

Example:

*** Settings ***
Library    DataDriver
Test Template    Invalid Logins

*** Keywords ***
Invalid Logins
    ...

Structure of Test Suite

Requirements

In the Moment there are some requirements how a test suite must be structured so that the DataDriver can get all the information it needs.

  • only the first test case will be used as a template. All other test cases will be deleted.
  • Test cases have to be defined with a Test Template in Settings secion. Reason for this is, that the DataDriver needs to know the names of the test case arguments. Test cases do not have named arguments. Keywords do.
  • The keyword which is used as Test Template must be defined within the test suite (in the same *.robot file). If the keyword which is used as Test Template is defined in a Resource the DataDriver has no access to its arguments names.

Example Test Suite

***Settings***
Library           DataDriver
Resource          login_resources.robot
Suite Setup       Open my Browser
Suite Teardown    Close Browsers
Test Setup        Open Login Page
Test Template     Invalid Login

*** Test Case ***
Login with user ${username} and password ${password}    Default    UserData

***** *Keywords* *****
Invalid login
    [Arguments]    ${username}    ${password}
    Input username    ${username}
    Input pwd    ${password}
    click login button
    Error page should be visible

In this example, the DataDriver is activated by using it as a Library. It is used with default settings. As Test Template the keyword Invalid Login is used. This keyword has two arguments. Argument names are ${username} and ${password}. These names have to be in the CSV file as column header. The test case has two variable names included in its name, which does not have any functionality in Robot Framework®. However, the Data Driver will use the test case name as a template name and replaces the variables with the specific value of the single generated test case. This template test will only be used as a template. The specified data Default and UserData would only be used if no CSV file has been found.

Structure of data file

min. required columns

  • *** Test Cases *** column has to be the first one.
  • Argument columns: For each argument of the Test Template keyword one column must be existing in the data file as data source. The name of this column must match the variable name and syntax.

optional columns

  • [Tags] column may be used to add specific tags to a test case. Tags may be comma separated.
  • [Documentation] column may be used to add specific test case documentation.

Example Data file

*** Test Cases *** ${username} ${password} [Tags] [Documentation]
Right user empty pass demo ${EMPTY} 1 This is a test case documentation of the first one.
Right user wrong pass demo FooBar 2,3,foo This test case has the Tags 2,3 and foo assigned.
  ${EMPTY} mode 1,2,3,4 This test case has a generated name based on template name.
  ${EMPTY} ${EMPTY}    
  ${EMPTY} FooBar    
  FooBar mode    
  FooBar ${EMPTY}    
  FooBar FooBar    

In this data file, eight test cases are defined. Each line specifies one test case. The first two test cases have specific names. The other six test cases will generate names based on template test cases name with the replacement of variables in this name. The order of columns is irrelevant except the first column, *** Test Cases ***

Supported Data Types

In general DataDriver supports any Object that is handed over from the DataReader. However the text based readers for csv, excel and so do support different types as well. DataDriver supports Robot Framework® Scalar variables as well as Dictionaries and Lists. It also support python literal evaluations.

Scalar Variables

The Prefix $ defines that the value in the cell is taken as in Robot Framework® Syntax. String is str, ${1} is int and ${None} is NoneType. The Prefix only defines the value typ. It can also be used to assign a scalar to a dictionary key. See example table: ${user}[id]

Dictionary Variables

Dictionaries can be created in different ways.

One option is, to use the prefix &. If a variable is defined that was (i.e. &{dict}) the cell value is interpreted the same way, the BuiltIn keyword Create Dictionary would do. The arguments here are comma (,) separated. See example table: &{dict}

The other option is to define scalar variables in dictionary syntax like ${user}[name] or ${user.name} That can be also nested dictionaries. DataDriver will create Robot Framework® (DotDict) Dictionaries, that can be accessed with ${user.name.first} See example table: ${user}[name][first]

List Variables

Lists can be created with the prefix @ as comma (,) separated list. See example table: @{list}

Be aware that a list with an empty string has to be the cell content ${Empty}.

Python Literals

DataDriver can evaluate Literals. It uses the prefix e for that. (i.e. e{list_eval}) For that it uses BuiltIn Evaluate

See example table: e{user.chk}

*** Test Cases *** ${scalar} @{list} e{list_eval} &{dict} e{dict_eval} e{eval} ${exp_eval} ${user}[id] ${user}[name][first] ${user.name.last} e{user.chk}
One Sum List 1,2,3,4 ["1","2","3","4"] key=value {'key': 'value'} [1,2,3,4] 10 1 Pekka Klärck {'id': '1', 'name': {'first': 'Pekka', 'last': 'Klärck'}}
Two Should be Equal a,b,c,d ["a","b","c","d"] key,value {'key': 'value'} True ${true} 2 Ed Manlove {'id': '2', 'name': {'first': 'Ed', 'last': 'Manlove'}}
Three Whos your Daddy !,",',$ ["!",'"',"'","$"] z,value,a,value2 {'a': 'value2', 'z': 'value'} {'Daddy' : 'René'} René 3 Tatu Aalto {'id': '3', 'name': {'first': 'Tatu', 'last': 'Aalto'}}
4 Should be Equal 1 ["1"] key=value {'key': 'value'} 1 ${1} 4 Jani Mikkonen {'id': '4', 'name': {'first': 'Jani', 'last': 'Mikkonen'}}
5 Should be Equal   [] a=${2} {'a':2} "string" string 5 Mikko Korpela {'id': '5', 'name': {'first': 'Mikko', 'last': 'Korpela'}}
6 Should be Equal [1,2] ["[1","2]"] key=value,key2=value2 {'key': 'value', 'key2': 'value2'} None ${none} 6 Ismo Aro {'id': '6', 'name': {'first': 'Ismo', 'last': 'Aro'}}

Accessing Test Data From Robot Variables

If neccesary it is possible to access the fetched data tables directly from a Robot Framework® variable. This could be helpfull in Test Setup or in Suite Setup.

There are three variables available within the Data-Driven Suite:

@{DataDriver_DATA_LIST}

A list as suite variable containing a robot dictionary for each test case that is selected for execution.

[
  {
    "test_case_name": "Right user empty pass",
    "arguments": {
      "${username}": "demo",
      "${password}": "${EMPTY}"
    },
    "tags": [
      "1"
    ],
    "documentation": "This is a test case documentation of the first one."
  },
  {
    "test_case_name": "Right user wrong pass",
    "arguments": {
      "${username}": "demo",
      "${password}": "FooBar"
    },
    "tags": [
      "2",
      "3",
      "foo"
    ],
    "documentation": "This test case has the Tags 2,3 and foo"
  },
  {
    "test_case_name": "Login with user '${EMPTY}' and password 'mode'",
    "arguments": {
      "${username}": "${EMPTY}",
      "${password}": "mode"
    },
    "tags": [
      "1",
      "2",
      "3",
      "4"
    ],
    "documentation": "This test case has a generated name based on template name."
  },
  {
    "test_case_name": "Login with user '${EMPTY}' and password '${EMPTY}'",
    "arguments": {
      "${username}": "${EMPTY}",
      "${password}": "${EMPTY}"
    },
    "tags": [
      ""
    ],
    "documentation": ""
  },
  {
    "test_case_name": "Login with user '${EMPTY}' and password 'FooBar'",
    "arguments": {
      "${username}": "${EMPTY}",
      "${password}": "FooBar"
    },
    "tags": [
      ""
    ],
    "documentation": ""
  },
  {
    "test_case_name": "Login with user 'FooBar' and password 'mode'",
    "arguments": {
      "${username}": "FooBar",
      "${password}": "mode"
    },
    "tags": [
      "foo",
      "1"
    ],
    "documentation": ""
  },
  {
    "test_case_name": "Login with user 'FooBar' and password '${EMPTY}'",
    "arguments": {
      "${username}": "FooBar",
      "${password}": "${EMPTY}"
    },
    "tags": [
      "foo"
    ],
    "documentation": ""
  },
  {
    "test_case_name": "Login with user 'FooBar' and password 'FooBar'",
    "arguments": {
      "${username}": "FooBar",
      "${password}": "FooBar"
    },
    "tags": [
      "foo",
      "2"
    ],
    "documentation": ""
  }
]

This can be accessed as usual in Robot Framework®.

${DataDriver_DATA_LIST}[2][arguments][\\${password}] would result in mode .

&{DataDriver_DATA_DICT}

A dictionary as suite variable that contains the same data as the list, with the test names as keys.

{
  "Right user empty pass": {
    "test_case_name": "Right user empty pass",
    "arguments": {
      "${username}": "demo",
      "${password}": "${EMPTY}"
    },
    "tags": [
      "1"
    ],
    "documentation": "This is a test case documentation of the first one."
  },
  "Right user wrong pass": {
    "test_case_name": "Right user wrong pass",
    "arguments": {
      "${username}": "demo",
      "${password}": "FooBar"
    },
    "tags": [
      "2",
      "3",
      "foo"
    ],
    "documentation": "This test case has the Tags 2,3 and foo"
  },
  "Login with user '${EMPTY}' and password 'mode'": {
    "test_case_name": "Login with user '${EMPTY}' and password 'mode'",
    "arguments": {
      "${username}": "${EMPTY}",
      "${password}": "mode"
    },
    "tags": [
      "1",
      "2",
      "3",
      "4"
    ],
    "documentation": "This test case has a generated name based on template name."
  },
  "Login with user '${EMPTY}' and password '${EMPTY}'": {
    "test_case_name": "Login with user '${EMPTY}' and password '${EMPTY}'",
    "arguments": {
      "${username}": "${EMPTY}",
      "${password}": "${EMPTY}"
    },
    "tags": [
      ""
    ],
    "documentation": ""
  },
  "Login with user '${EMPTY}' and password 'FooBar'": {
    "test_case_name": "Login with user '${EMPTY}' and password 'FooBar'",
    "arguments": {
      "${username}": "${EMPTY}",
      "${password}": "FooBar"
    },
    "tags": [
      ""
    ],
    "documentation": ""
  },
  "Login with user 'FooBar' and password 'mode'": {
    "test_case_name": "Login with user 'FooBar' and password 'mode'",
    "arguments": {
      "${username}": "FooBar",
      "${password}": "mode"
    },
    "tags": [
      "foo",
      "1"
    ],
    "documentation": ""
  },
  "Login with user 'FooBar' and password '${EMPTY}'": {
    "test_case_name": "Login with user 'FooBar' and password '${EMPTY}'",
    "arguments": {
      "${username}": "FooBar",
      "${password}": "${EMPTY}"
    },
    "tags": [
      "foo"
    ],
    "documentation": ""
  },
  "Login with user 'FooBar' and password 'FooBar'": {
    "test_case_name": "Login with user 'FooBar' and password 'FooBar'",
    "arguments": {
      "${username}": "FooBar",
      "${password}": "FooBar"
    },
    "tags": [
      "foo",
      "2"
    ],
    "documentation": ""
  }
}

&{DataDriver_TEST_DATA}

A dictionary as test variable that contains the test data of the current test case. This dictionary does also contain arguments that are not used in the Test Template keyword. This can be used in Test Setup and within a test case.

{
  "test_case_name": "Right user wrong pass",
  "arguments": {
    "${username}": "demo",
    "${password}": "FooBar"
  },
  "tags": [
    "2",
    "3",
    "foo"
  ],
  "documentation": "This test case has the Tags 2,3 and foo"
}

Data Sources

CSV / TSV (Character-separated values)

By default DataDriver reads csv files. With the Encoding and CSV Dialect settings you may configure which structure your data source has.

XLS / XLSX Files

To use Excel file types, you have to install DataDriver with the Extra XLS.

If you want to use Excel based data sources, you may just set the file to the extention or you may point to the correct file. If the extention is ".xls" or ".xlsx" DataDriver will interpret it as Excel file. You may select the sheet which will be read by the option sheet_name. By default it is set to 0 which will be the first table sheet. You may use sheet index (0 is first sheet) or sheet name(case sensitive). XLS interpreter will ignore all other options like encoding, delimiters etc.

*** Settings ***
Library    DataDriver    .xlsx

or:

*** Settings ***
Library    DataDriver    file=my_data_source.xlsx    sheet_name=2nd Sheet

MS Excel and typed cells

Microsoft Excel xls or xlsx file have the possibility to type thair data cells. Numbers are typically of the type float. If these data are not explicitly defined as text in Excel, pandas will read it as the type that is has in excel. Because we have to work with strings in Robot Framework® these data are converted to string. This leads to the situation that a European time value like "04.02.2019" (4th January 2019) is handed over to Robot Framework® in Iso time "2019-01-04 00:00:00". This may cause unwanted behavior. To mitigate this risk you should define Excel based files explicitly as text within Excel.

Alternatively you may deactivate that string conversion. To do so, you have to add the option preserve_xls_types to True. In that case, you will get str, float, boolean, int, datetime.time, datetime.datetime and some others.

*** Settings ***
Library    DataDriver    file=my_data_source.xlsx    preserve_xls_types=True

PICT (Pairwise Independent Combinatorial Testing)

Pict is able to generate data files based on a model file. https://github.com/Microsoft/pict

Documentation: https://github.com/Microsoft/pict/blob/master/doc/pict.md

Requirements of PICT

  • Path to pict.exe must be set in the %PATH% environment variable.
  • Data model file has the file extention ".pict"
  • Pict model file must be encoded in UTF-8

How it works

If the file option is set to a file with the extention pict, DataDriver will hand over this file to pict.exe and let it automatically generates a file with the extention ".pictout". This file will the be used as data source for the test generation. (It is tab seperated and UTF-8 encoded) Except the file option all other options of the library will be ignored.

*** Settings ***
Library    DataDriver    my_model_file.pict

It is possible to give options to pict with the import argument pict_options=.

*** Settings ***
Library    DataDriver    pict_arg.pict    pict_options=/o:3 /r

Glob File Pattern

This module implements a reader class that creates a test case for each file or folder that matches the given glob pattern.

With an optional argument "arg_name" you can modify the argument that will be set. See folder example.

Example with json files:

*** Settings ***
Library           DataDriver    file=${CURDIR}/DataFiles/*_File.json    reader_class=glob_reader
Library           OperatingSystem
Test Template     Test all Files


*** Test Cases ***
Glob_Reader_Test    Wrong_File.NoJson


*** Keywords ***
Test all Files
    [Arguments]    ${file_name}
    ${file_content}=    Get File    ${file_name}
    ${content}=    Evaluate    json.loads($file_content)["test_case"]
    Should Be Equal    ${TEST_NAME}    ${content}

Example with folders:

*** Settings ***
Library           DataDriver    file=${CURDIR}/FoldersToFind/*/    reader_class=glob_reader    arg_name=\\${folder_name}
Library           OperatingSystem
Test Template     Test all Files


*** Test Cases ***
Glob_Reader_Test    Wrong_File.NoJson


*** Keywords ***
Test all Files
    [Arguments]    ${folder_name}
    ${content}=    Get File    ${folder_name}/verify.txt
    Should Be Equal    ${TEST_NAME}    ${content}

File Encoding and CSV Dialect

While there are various specifications and implementations for the CSV format (see RFC 4180), there is no formal specification in existence, which allows for a wide variety of interpretations of CSV files. Therefore it is possible to define your own dialect or use predefined. The default is Excel-EU which is a semicolon separated file. These Settings are changeable as options of the Data Driver Library.

file=

*** Settings ***
Library         DataDriver    file=../data/my_data_source.csv
  • None(default): Data Driver will search in the test suites folder if a *.csv file with the same name than the test suite *.robot file exists
  • only file extention: if you just set a file extentions like ".xls" or ".xlsx" DataDriver will search
  • absolute path: If an absolute path to a file is set, DataDriver tries to find and open the given data file.
  • relative path: If the option does not point to a data file as an absolute path, Data Driver tries to find a data file relative to the folder where the test suite is located.

encoding=

encoding= must be set if it shall not be cp1252.

Examples:

cp1252, ascii, iso-8859-1, latin-1, utf_8, utf_16, utf_16_be, utf_16_le

cp1252 is:

  • Code Page 1252
  • Windows-1252
  • Windows Western European

Most characters are same between ISO-8859-1 (Latin-1) except for the code points 128-159 (0x80-0x9F). These Characters are available in cp1252 which are not present in Latin-1.

€ ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Ž ‘ ’ “ ” • – — ˜ ™ š › œ ž Ÿ

See Python Standard Encoding for more encodings

dialect=

You may change the CSV Dialect here. The dialect option can be one of the following: - Excel-EU - excel - excel-tab - unix - UserDefined

supported Dialects are:

"Excel-EU"
    delimiter=';',
    quotechar='"',
    escapechar='\\',
    doublequote=True,
    skipinitialspace=False,
    lineterminator="\\r\\n",
    quoting=csv.QUOTE_ALL

"excel"
    delimiter = ','
    quotechar = '"'
    doublequote = True
    skipinitialspace = False
    lineterminator = '\\r\\n'
    quoting = QUOTE_MINIMAL

"excel-tab"
    delimiter = '\\t'
    quotechar = '"'
    doublequote = True
    skipinitialspace = False
    lineterminator = '\\r\\n'
    quoting = QUOTE_MINIMAL

"unix"
    delimiter = ','
    quotechar = '"'
    doublequote = True
    skipinitialspace = False
    lineterminator = '\\n'
    quoting = QUOTE_ALL

Usage in Robot Framework®

*** Settings ***
Library    DataDriver    my_data_file.csv    dialect=excel
*** Settings ***
Library    DataDriver    my_data_file.csv    dialect=excel_tab
*** Settings ***
Library    DataDriver    my_data_file.csv    dialect=unix_dialect

Example User Defined

User may define the format completely free. If an option is not set, the default values are used. To register a userdefined format user have to set the option dialect to UserDefined

Usage in Robot Framework®

*** Settings ***
Library    DataDriver    my_data_file.csv
...    dialect=UserDefined
...    delimiter=.
...    lineterminator=\\n

Defaults:

file=None,
encoding='cp1252',
dialect='Excel-EU',
delimiter=';',
quotechar='"',
escapechar='\\\\',
doublequote=True,
skipinitialspace=False,
lineterminator='\\r\\n',
sheet_name=0

Custom DataReader Classes

It is possible to write your own DataReader Class as a plugin for DataDriver. DataReader Classes are called from DataDriver to return a list of TestCaseData.

Using Custom DataReader

DataReader classes are loaded dynamically into DataDriver while runtime. DataDriver identifies the DataReader to load by the file extantion of the data file or by the option reader_class.

Select Reader by File Extension:

*** Settings ***
Library    DataDriver    file=mydata.csv

This will load the class csv_reader from csv_reader.py from the same folder.

Select Reader by Option:

*** Settings ***
    Library    DataDriver   file=mydata.csv    reader_class=generic_csv_reader    dialect=userdefined   delimiter=\\t    encoding=UTF-8

This will load the class generic_csv_reader from generic_csv_reader.py from same folder.

Create Custom Reader

Recommendation:

Have a look to the Source Code of existing DataReader like csv_reader.py or generic_csv_reader.py .

To write your own reader, create a class inherited from AbstractReaderClass.

Your class will get all available configs from DataDriver as an object of ReaderConfig on __init__.

DataDriver will call the method get_data_from_source This method should then load your data from your custom source and stores them into list of object of TestCaseData. This List of TestCaseData will be returned to DataDriver.

AbstractReaderClass has also some optional helper methods that may be useful.

You can either place the custom reader with the others in DataDriver folder or anywhere on the disk. In the first case or if your custom reader is in python path just use it like the others by name:

*** Settings ***
Library          DataDriver    reader_class=my_reader

In case it is somewhere on the disk, it is possible to use an absolute or relative path to a custom Reader. Imports of custom readers follow the same rules like importing Robot Framework® libraries. Path can be relative to ${EXECDIR} or to DataDriver/__init__.py:

*** Settings ***
Library          DataDriver    reader_class=C:/data/my_reader.py    # set custom reader
...                            file_search_strategy=None            # set DataDriver to not check file
...                            min=0                                # kwargs arguments for custom reader
...                            max=62

This my_reader.py should implement a class inherited from AbstractReaderClass that is named my_reader.

from DataDriver.AbstractReaderClass import AbstractReaderClass  # inherit class from AbstractReaderClass
from DataDriver.ReaderConfig import TestCaseData  # return list of TestCaseData to DataDriver


class my_reader(AbstractReaderClass):

    def get_data_from_source(self):  # This method will be called from DataDriver to get the TestCaseData list.
        test_data = []
        for i in range(int(self.kwargs['min']), int(self.kwargs['max'])):  # Dummy code to just generate some data
            args = {'${var_1}': str(i), '${var_2}': str(i)}  # args is a dictionary. Variable name is the key, value is value.
            test_data.append(TestCaseData(f'test {i}', args, ['tag']))  # add a TestCaseData object to the list of tests.
        return test_data  # return the list of TestCaseData to DataDriver

See other readers as example.

Selection of Test Cases to Execute

Because test cases that are created by DataDriver after parsing while execution, it is not possible to use some Robot Framework® methods to select test cases.

Examples for options that have to be used differently:

robot option Description
--test Selects the test cases by name.
--task Alias for --test that can be used when executing tasks.
--rerunfailed Selects failed tests from an earlier output file to be re-executed.
--include Selects the test cases by tag.
--exclude Selects the test cases by tag.

Selection of test cases by name

Select a single test case:

To execute just a single test case by its exact name it is possible to execute the test suite and set the global variable ${DYNAMICTEST} with the name of the test case to execute as value. Pattern must be suitename.testcasename.

Example:

robot --variable "DYNAMICTEST:my suite name.test case to be executed" my_suite_name.robot

Pabot uses this feature to execute a single test case when using --testlevelsplit

Select a list of test cases:

It is possible to set a list of test case names by using the variable ${DYNAMICTESTS} (plural). This variable must be a string and the list of names must be pipe-seperated (|).

Example:

robot --variable DYNAMICTESTS:firstsuitename.testcase1|firstsuitename.testcase3|anothersuitename.othertestcase foldername

It is also possible to set the variable @{DYNAMICTESTS} as a list variable from i.e. python code.

Re-run failed test cases:

Because it is not possible to use the command line argument --rerunfailed from robot directly, DataDriver brings a Pre-Run-Modifier that handles this issue.

Normally reexecution of failed testcases has three steps.

  • original execution
  • re-execution the failed ones based on original execution output
  • merging original execution output with re-execution output

The DataDriver.rerunfailed Pre-Run-Modifier removes all passed test cases based on a former output.xml.

Example:

robot --output original.xml tests                                                    # first execute all tests
robot --prerunmodifier DataDriver.rerunfailed:original.xml --output rerun.xml tests  # then re-execute failing
rebot --merge original.xml rerun.xml                                                 # finally merge results

Be aware, that in this case it is not allowed to use ":" as character in the original output file path. If you want to set a full path on windows like e:\\myrobottest\\output.xml you have to use ";" as argument seperator.

Example:

robot --prerunmodifier DataDriver.rerunfailed;e:\\myrobottest\\output.xml --output e:\\myrobottest\\rerun.xml tests

Filtering with tags.

New in 0.3.1

It is possible to use tags to filter the data source. To use this, tags must be assigned to the test cases in data source.

Robot Framework® Command Line Arguments

To filter the source, the normal command line arguments of Robot Framework® can be used. See Robot Framework® Userguide for more information Be aware that the filtering of Robot Framework® itself is done before DataDriver is called. This means if the Template test is already filtered out by Robot Framework®, DataDriver can never be called. If you want to use --include the DataDriver TestSuite should have a DefaultTag or ForceTag that fulfills these requirements.

Example: robot --include 1OR2 --exclude foo DataDriven.robot

Filter based on Library Options

It is also possible to filter the data source by an init option of DataDriver. If these Options are set, Robot Framework® Filtering will be ignored.

Example:

*** Settings ***
Library    DataDriver    include=1OR2    exclude=foo

Configure DataDriver by Pre-Run Keyword

With config_keyword= it's possible to name a keyword that will be called from Data Driver before it starts the actual processing of the data file. One possible usage is if the data file itself shall be created by another keyword dynamically during the execution of the Data Driver test suite. The config_keyword= can be used to call that keyword and return the updated arguments (e.g. file) back to the Data Driver Library.

The config keyword

  • May be defined globally or inside each testsuite individually
  • Gets all the arguments, that Data Driver gets from Library import, as a Robot Dictionary
  • Shall return the (updated) Data Driver arguments as a Robot Dictionary

Usage in Robot Framework®

*** Settings ***
Library           OperatingSystem
Library           DataDriver    dialect=excel    encoding=utf_8   config_keyword=Config
Test Template     The Keyword

*** Test Cases ***
Test    aaa

*** Keywords ***
The Keyword
    [Arguments]    ${var}
    Log To Console    ${var}

Config
    [Arguments]    ${original_config}
    Log To Console    ${original_config.dialect}                # just a log of the original
    Create File    ${CURDIR}/test321.csv
    ...    *** Test Cases ***,\\${var},\\n123,111,\\n321,222,      # generating file
    ${new_config}=    Create Dictionary    file=test321.csv     # set file attribute in a dictionary
    [Return]    ${new_config}                                   # returns {'file': 'test321.csv'}

Pabot and DataDriver

You should use Pabot version 1.10.0 or newer.

DataDriver supports --testlevelsplit from pabot only if the PabotLib is in use. Use --pabotlib to enable that.

When using pabot like this, DataDriver automatically splits the amount of test cases into nearly same sized groups. Is uses the processes count from pabot to calculate the groups. When using 8 processes with 100 test cases you will get 8 groups of tests with the size of 12 to 13 tests. These 8 groups are then executed as one block with 8 processes. This reduces a lot of overhead with Suite Setup and Teardown.

You can switch between three modes:

  • Equal: means it creates equal sizes groups
  • Binary: is more complex. it created a decreasing size of containers to support better balancing.
  • Atomic: it does not group tests at all and runs really each test case in a separate thread.

This can be set by optimize_pabot in Library import.

Example:

*** Settings ***
Library          DataDriver    optimize_pabot=Binary

Binary creates with 40 test cases and 8 threads something like that:

P01: 01,02,03,04,05
P02: 06,07,08,09,10
P03: 11,12,13,14,15
P04: 16,17,18,19,20
P05: 21,22,23
P06: 24,25,26
P07: 27,28,29
P08: 30,31,32
P09: 33
P10: 34
P11: 35
P12: 36
P13: 37
P14: 38
P15: 39
P16: 40

robotframework-datadriver's People

Contributors

emanlove avatar lucagiove avatar manykasiriha avatar mardukbp avatar mkorpela avatar montsamu avatar robinmackaij avatar snooz82 avatar willywinkel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

robotframework-datadriver's Issues

Unable to install from the setup.py file

Hi Team,

I was tried this to install from setup.py files like below
python -m setup.py install
'
But getting below error:
Traceback (most recent call last):
File "C:\jython2.7.2\Lib\runpy.py", line 151, in _run_module_as_main
mod_name, loader, code, fname = _get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 151, in _run_module_as_main
mod_name, loader, code, fname = _get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 101, in _get_module_details
loader = get_loader(mod_name)
File "C:\jython2.7.2\Lib\pkgutil.py", line 478, in get_loader
return find_loader(fullname)
File "C:\jython2.7.2\Lib\pkgutil.py", line 488, in find_loader
for importer in iter_importers(fullname):
File "C:\jython2.7.2\Lib\pkgutil.py", line 439, in iter_importers
import(pkg)
File "", line None
SyntaxError: Non-ASCII character in file 'pyclasspath/setup.py', but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
PS D:\Trash\Robot\robotframework-datadriver-master>
PS D:\Trash\Robot\robotframework-datadriver-master>
PS D:\Trash\Robot\robotframework-datadriver-master>
PS D:\Trash\Robot\robotframework-datadriver-master> jython -m setup.py install
Traceback (most recent call last):
File "C:\jython2.7.2\Lib\runpy.py", line 151, in _run_module_as_main
mod_name, loader, code, fname = _get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 151, in run_module_as_main
mod_name, loader, code, fname = get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 101, in get_module_details
loader = get_loader(mod_name)
File "C:\jython2.7.2\Lib\pkgutil.py", line 478, in get_loader
return find_loader(fullname)
File "C:\jython2.7.2\Lib\pkgutil.py", line 488, in find_loader
for importer in iter_importers(fullname):
File "C:\jython2.7.2\Lib\pkgutil.py", line 439, in iter_importers
import(pkg)
File "", line None
SyntaxError: Non-ASCII character in file 'pyclasspath/setup.py', but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
PS D:\Trash\Robot\robotframework-datadriver-master> python -m setup.py install
running install
running bdist_egg
running egg_info
creating src\robotframework_datadriver.egg-info
writing src\robotframework_datadriver.egg-info\PKG-INFO
writing dependency_links to src\robotframework_datadriver.egg-info\dependency_links.txt
writing requirements to src\robotframework_datadriver.egg-info\requires.txt
writing top-level names to src\robotframework_datadriver.egg-info\top_level.txt
writing manifest file 'src\robotframework_datadriver.egg-info\SOURCES.txt'
reading manifest file 'src\robotframework_datadriver.egg-info\SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no files found matching '.pictout' under directory 'example'
warning: no files found matching '
.pictout' under directory 'atest'
writing manifest file 'src\robotframework_datadriver.egg-info\SOURCES.txt'
installing library code to build\bdist.win-amd64\egg
running install_lib
running build_py
creating build
creating build\lib
creating build\lib\DataDriver
copying src\DataDriver\AbstractReaderClass.py -> build\lib\DataDriver
copying src\DataDriver\csv_reader.py -> build\lib\DataDriver
copying src\DataDriver\DataDriver.py -> build\lib\DataDriver
copying src\DataDriver\generic_csv_reader.py -> build\lib\DataDriver
copying src\DataDriver\json_reader.py -> build\lib\DataDriver
copying src\DataDriver\pict_reader.py -> build\lib\DataDriver
copying src\DataDriver\ReaderConfig.py -> build\lib\DataDriver
copying src\DataDriver\rerunfailed.py -> build\lib\DataDriver
copying src\DataDriver\search.py -> build\lib\DataDriver
copying src\DataDriver\xlsx_reader.py -> build\lib\DataDriver
copying src\DataDriver\xls_reader.py -> build\lib\DataDriver
copying src\DataDriver_init
.py -> build\lib\DataDriver
creating build\bdist.win-amd64
creating build\bdist.win-amd64\egg
creating build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\AbstractReaderClass.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\csv_reader.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\DataDriver.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\generic_csv_reader.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\json_reader.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\pict_reader.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\ReaderConfig.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\rerunfailed.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\search.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\xlsx_reader.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver\xls_reader.py -> build\bdist.win-amd64\egg\DataDriver
copying build\lib\DataDriver_init
.py -> build\bdist.win-amd64\egg\DataDriver
byte-compiling build\bdist.win-amd64\egg\DataDriver\AbstractReaderClass.py to AbstractReaderClass.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\csv_reader.py to csv_reader.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\DataDriver.py to DataDriver.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\generic_csv_reader.py to generic_csv_reader.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\json_reader.py to json_reader.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\pict_reader.py to pict_reader.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\ReaderConfig.py to ReaderConfig.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\rerunfailed.py to rerunfailed.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\search.py to search.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\xlsx_reader.py to xlsx_reader.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver\xls_reader.py to xls_reader.cpython-38.pyc
byte-compiling build\bdist.win-amd64\egg\DataDriver_init
.py to init.cpython-38.pyc
creating build\bdist.win-amd64\egg\EGG-INFO
copying src\robotframework_datadriver.egg-info\PKG-INFO -> build\bdist.win-amd64\egg\EGG-INFO
copying src\robotframework_datadriver.egg-info\SOURCES.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying src\robotframework_datadriver.egg-info\dependency_links.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying src\robotframework_datadriver.egg-info\requires.txt -> build\bdist.win-amd64\egg\EGG-INFO
copying src\robotframework_datadriver.egg-info\top_level.txt -> build\bdist.win-amd64\egg\EGG-INFO
zip_safe flag not set; analyzing archive contents...
DataDriver.pycache.DataDriver.cpython-38: module references file
creating dist
creating 'dist\robotframework_datadriver-0.4.0b1-py3.8.egg' and adding 'build\bdist.win-amd64\egg' to it
removing 'build\bdist.win-amd64\egg' (and everything under it)
Processing robotframework_datadriver-0.4.0b1-py3.8.egg
removing 'c:\python\lib\site-packages\robotframework_datadriver-0.4.0b1-py3.8.egg' (and everything under it)
creating c:\python\lib\site-packages\robotframework_datadriver-0.4.0b1-py3.8.egg
Extracting robotframework_datadriver-0.4.0b1-py3.8.egg to c:\python\lib\site-packages
robotframework-datadriver 0.4.0b1 is already the active version in easy-install.pth

Installed c:\python\lib\site-packages\robotframework_datadriver-0.4.0b1-py3.8.egg
Processing dependencies for robotframework-datadriver==0.4.0b1
Searching for Pygments==2.6.1
Best match: Pygments 2.6.1
Adding Pygments 2.6.1 to easy-install.pth file
Installing pygmentize-script.py script to C:\Python\Scripts
Installing pygmentize.exe script to C:\Python\Scripts

Using c:\python\lib\site-packages
Searching for docutils==0.16
Best match: docutils 0.16
Adding docutils 0.16 to easy-install.pth file

Using c:\python\lib\site-packages
Searching for robotframework==3.2.1
Best match: robotframework 3.2.1
Processing robotframework-3.2.1-py3.8.egg
robotframework 3.2.1 is already the active version in easy-install.pth
Installing rebot-script.py script to C:\Python\Scripts
Installing rebot.exe script to C:\Python\Scripts
Installing robot-script.py script to C:\Python\Scripts
Installing robot.exe script to C:\Python\Scripts

Using c:\python\lib\site-packages\robotframework-3.2.1-py3.8.egg
Finished processing dependencies for robotframework-datadriver==0.4.0b1
C:\Python\python.exe: Error while finding module specification for 'setup.py' (ModuleNotFoundError: path attribute not found on 'setup' while trying to find 'setup.py')

jython -m setup.py install

Error:
Traceback (most recent call last):
File "C:\jython2.7.2\Lib\runpy.py", line 151, in _run_module_as_main
mod_name, loader, code, fname = _get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 151, in _run_module_as_main
mod_name, loader, code, fname = _get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 101, in _get_module_details
loader = get_loader(mod_name)
File "C:\jython2.7.2\Lib\pkgutil.py", line 478, in get_loader
return find_loader(fullname)
File "C:\jython2.7.2\Lib\pkgutil.py", line 488, in find_loader
for importer in iter_importers(fullname):
File "C:\jython2.7.2\Lib\pkgutil.py", line 439, in iter_importers
import(pkg)
File "", line None
SyntaxError: Non-ASCII character in file 'pyclasspath/setup.py', but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
PS D:\Trash\Robot\robotframework-datadriver-master>
PS D:\Trash\Robot\robotframework-datadriver-master>
PS D:\Trash\Robot\robotframework-datadriver-master>
PS D:\Trash\Robot\robotframework-datadriver-master> jython -m setup.py install
Traceback (most recent call last):
File "C:\jython2.7.2\Lib\runpy.py", line 151, in _run_module_as_main
mod_name, loader, code, fname = _get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 151, in _run_module_as_main
mod_name, loader, code, fname = _get_module_details(mod_name)
File "C:\jython2.7.2\Lib\runpy.py", line 101, in _get_module_details
loader = get_loader(mod_name)
File "C:\jython2.7.2\Lib\pkgutil.py", line 478, in get_loader
return find_loader(fullname)
File "C:\jython2.7.2\Lib\pkgutil.py", line 488, in find_loader
for importer in iter_importers(fullname):
File "C:\jython2.7.2\Lib\pkgutil.py", line 439, in iter_importers
import(pkg)
File "", line None
SyntaxError: Non-ASCII character in file 'pyclasspath/setup.py', but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

Datadriver support for python 2.7

I've been a long time using python 2.7 with robot framework, now I have to make an DDT automation, so I want to use this library, but its incompatible with my python version. Could you make a compatible version?

Error rerunning tests

I have rerun my test suite with the following command with a DevOps pipeline

robot --prerunmodifier DataDriver.rerunfailed:'$(Build.SourcesDirectory)/output.xml' --output rerun2output.xml --variable BROWSER:headlesschrome --variable DEVICE:Desktop '$(Build.SourcesDirectory)/testsuites/.'

I get the following error:
[ ERROR ] Importing model modifier 'DataDriver.rerunfailed' failed: Model modifier 'rerunfailed' expected 1 argument, got 2.

Instead of re-running only the failed tests, the whole suite is re-run then.

I don't understand the meaning of the error message. What is interpreted as the 2nd argument in my command line?

Variables imported with data-driver are not available to [Set Up] keywords

When datadriver creates variables, they are not available to the set up keyword. I am not sure if that's because the variables are scoped locally, or because the variables are not instantiated until after set up runs.

Many of our test needs require us to set up data in a DB in a specific format, and data-driver would be a perfect tool for this if we could pass datadriver variables to the set-up keyword.

As it stands now, we have to write every test manually and pass parameters to the [Set Up] keywords for every test and are not able to use robotframework-datadriver when [Set Up] is not completely identical in every case.

Using custom datareader with pabot tests are not executed in parallel

Adding to this issue tracker as well since I'm not sure which library is causing the issue. Issue on pabot mkorpela/pabot#262

pabot is not parallelizing tests with DataDriver when using a custom data reader. The tests are all created by DataDriver and are successfully executed but sequentially. I put together a simple test project. Directory structure:

  • resources
    • py3
      • test
        • datareader
          • customreader.py
          • simplemodule.py
  • robot
    • cases.xlsx
    • test.robot

Contents of customreader.py (Direct copy of the XLSX reader in DataDriver).

from test.datareader.simplemodule import aSillyFunction
from DataDriver.AbstractReaderClass import AbstractReaderClass
import pandas as pd
import numpy as np

class customreader(AbstractReaderClass):

    def get_data_from_source(self):
        data_frame = pd.read_excel(self.file, sheet_name=self.sheet_name, dtype=str).replace(np.nan, '', regex=True)
        self._analyse_header(list(data_frame))
        for row in data_frame.values.tolist():
            self._read_data_from_table(row)
        return self.data_table

Contents of simplemodule.py

def aSillyFunction(x):
    return 2*x

Contents of test.robot

*** Settings ***
Library       DataDriver  file=cases.xlsx  reader_class=../resources/py3/test/datareader/customreader.py

Test Template  Run Test

*** Test Cases ***
Dummy Run Test  ${x1}  ${x2}   ${1}  ${1}

*** Keywords ***
Run Test
    [Arguments]  ${x1}  ${x2}
    ${x1}  convert to number  ${x1}
    ${x2}  convert to number  ${x2}
    should be equal  ${x1}  ${x2}

Running with:
pabot --processes 3 --testlevelsplit --pythonpath ../resources/py3 test.robot

Now, if we change the import in customreader.py from:

from test.datareader.simplemodule import aSillyFunction
to
from simplemodule import aSillyFunction
pabot will parallelize the tests. Switching the import back though causes pabot to execute all tests sequentially again.
Note that we need to remove .pabotsuitenames after running with the full module path import and switching.

how to implement the data driver with different configuration

Hello.

I have a testObjectA.robot file with reading 1000 different parameters in a excel file, and it works very well with the robotframework-datadriver module by generate 1000 test cases.
Currently, we have to test the testObjectA.robot with 10 different pre-configuration. The way that we can do is add one column in the excel file for the 10 different configuration and copy & paste the 1000 parameters 10 times in excel file to generate 1000*10 test cases.

This way seems very low efficient and not easy to maintenance. Is any any better way than copy&past test parameters for the 10 different pre-configuration?

Thanks

cannot import DataDriver on Ride python 3.6.0

[ ERROR ] Calling method '_start_suite' of listener 'DataDriver' failed: FileNotFoundError: File attribute was empty. Tried to find D:\test-data\exel-test\login-test01.csv but file does not exist. If no file validation is required, set file_search_strategy=None.

image

please help me. thanks

Can't make DataDriver read variables from CSV file with more than one column

I have found that if I create a CSV file with a single column, headed e.g. ${key_id}, then it works like a charm. But if the CSV file contains multiple columns separated by commas, the whole line is read as a single value, leaving the ${key_id} undefined. I have even tried explicitly specifying the delimiter as a comma. The documentation (https://pypi.org/project/robotframework-datadriver/#structure-of-data-file) states that the first column must be named *** Test Cases *** and this is what I did, but I wonder whether that is actually what is confusing DataDriver? That heading doesn't look like a Robot variable.

Test Template can't get keyword from resource

I import resource file contains keywords, and want to use it as a test template.

however, I found that it can only get the keyword from current testsuite.

    def _get_template_keyword(self, suite):
        template = self.template_test.template
        if template:
            for keyword in suite.resource.keywords:
                if self._is_same_keyword(keyword.name, template):
                    return keyword
        raise AttributeError('No "Test Template" keyword found for first test case.')

suite.resource.keywords only get the current testsuite keyword.

can robotframework-datadriver support to use external keyword as template ?

Select a list of test cases not working with RobotFramework 4.0

After update to robotframework_datadriver-1.1.1 and robotframework 4.0 I get an error message when I try to use DYNAMICTESTS command line variable.
If I run the robot file without DYNAMICTESTS argument every test case will run correctly.

I attach a simple test.robot and test.csv which can be used to reproduce the problem.
test.zip

python3 -m robot --variable 'DYNAMICTESTS:Test.test1' test.robot
[ ERROR ] Calling method '_start_suite' of listener 'DataDriver' failed: AttributeError: 'NoneType' object has no attribute 'name'

Suite Tags are not assigned during filtering

Päivi K Jun 11th at 7:22 AM

What is the expected behavior of --exclude with the datadriver (v 1.2.0)?

I have dummy suite with 6 cases generated by a custom reader, half tagged 'flip' and half 'flop' by the reader. Additionally the suite has default tag 'default'.
So when I execute
robot --include default --include flip dummysuite
the 3 cases tagged 'flip' get executed (as I expected).
But when trying to
robot --include default --exclude flip dummysuite
this results in
[ ERROR ] Suite 'dummysuite' contains no tests after model modifiers.
(while I was expecting this would result in the execution of the 'flop' cases)
Same result also with
robot --include default --exclude NOTflop dummysuite

René 9 hours ago

Hi,
I think because you have included default, but default is not added to these test cases in your datareader.
Just --exclude flip should work.
Because --include default explicitly limit the tests to those who have default attached.
The tests in the end however do have the default tag. but not at the time the list is filtered.
Not sure how this would affect existing implementations in the field, if i change that…

How to retest the failed test case when using the robotframwork-datadriver

Hello,

The robotframework-datadriver is very helpful to generate test cases when reading different configuration params from .xlsx file.

With using the robotframework-datadriver and when some test cases failed. I want to retest the failed test cases.
The command: robot -R output.xml Test.robot will fail as it can't parse the failed test cases due to the test case is newly generated by robotframework datadriver.

So How can we retest the failed test cases when using the robotframework datadriver?

Not able to succeed run data-driven xlsx file in parallel (pabot)

Hello,
I have tried to execute my data-driven(xlsx) test case (25 processes) using this guidence. When I try to run pabot --testlevelsplit --pabotlib (...) open the same test case 12 times, I hoped it would divide the 25 processes in the xlsx file into 12.
I have made mistake somewhere or no way to run data-driven(xlsx) cases in parallel.
Thanks in advance.

When using Excel Source i would like to keep the types...

tl;dr: is there a way to apply a datadriver Excel input file's cell format to the variable's format that is conveyed to the robot test?

Moin René,

first of all let me say that my users love the option of providing test data via Excel sheets. Great job with designing the datadriver library. There is however an issue that I have not yet found a solution for - maybe, you have an idea on how to solve this issue.

My main use case for using the data driver are API tests. Read: I have tons of potential input parameters which I expose to the users via an excel sheet.

  • The end user populates all required parameters (read: Excel cells).
  • My Robot script checks on a test-specific basis which of the test-specific cells are populated.
  • If the cell is populated, its value is then added to a Robot dictionary
  • That dictionary is later on converted to a JSON object which then is sent to my API.

This whole process works like a charm. However, there is an edge case which I need to cover but have not yet found a viable solution for:

Some of the APIs that I use require numeric content to be provided as string data: Read: my Excel cell will contain a value of e.g. 3 but I need to add the STRING value of "3" to the robot dictionary so that when it gets converted to the final JSON object.

Let's assume that I have a data driver Excel input file which contains two variable columns with just one row of data:

${VAR1} --> numeric value of 1
${VAR2} --> string value of 2 (e.g. cell's format was set to string,  Input was '2 in order to enforce string format)

When I check the data type 'the Python way', both variable's data types are returned as 'string':

Check Variable Type New
   [Arguments]   ${object}
   ${VARTYPE}=   Evaluate  type($object).__name__
   [Return]      ${VARTYPE}

This crude yet somewhat effective approach does work for most cases but the one in question:

Check Variable Type
    [Arguments]    ${object}
 
    Return From Keyword If        not "${object}"  NONE  ${EMPTY}

    ${result}  ${number_value}=   Run Keyword And Ignore Error   Convert To Number  ${object}
    ${isnumber}=  Run Keyword And Return Status  Should Be Equal As Strings  ${object}  ${number_value}

    ${result}  ${integer_value}=  Run Keyword And Ignore Error   Convert To Integer  ${object}
    ${isinteger}=  Run Keyword And Return Status  Should Be Equal As Strings  ${object}  ${integer_value}

    ${result}  ${bool_value}=     Run Keyword And Ignore Error    Convert To Boolean    ${object}
    ${isbool}=  Run Keyword And Return Status   Should Be Equal As Strings  ${object}  ${bool_value}

    Return From Keyword If        ${isnumber}   NUMBER        ${number_value}
    Return From Keyword If        ${isinteger}    INTEGER       ${integer_value}
    Return From Keyword If        ${isbool}        BOOLEAN       ${bool_value}
    Return From Keyword                                    STRING        ${object}                       

If this crude detection is applied, both variable's values are not detected as string but as integer - which is correct for the first case but not desired for the 2nd case where that value's format was set to 'string'

Q: apart from detecting these edge cases' formats with the help of e.g. leading format descriptors in the cell's value, is there any way for the data driver to get the cell's format based on its Excel formatting - and then return that cell's value in its respective format?

Note that this does not only affect numeric data types but also boolean types. E.g.

TRUE (as boolean) and
'TRUE (as string)

are both conveyed to the Robot Test via data driver with a 'string' data type

Danke Dir:slight_smile:
Jörg

Pipeline Azure, file is not found

How can I correct this error, I am having problems to run a robot file using DataDriver

[ ERROR ] Calling method '_start_suite' of listener 'DataDriver' failed: FileNotFoundError: File attribute was not a full path. Tried to find D:\a\1\s./private.csv but file does not exist.


*** Setting ***
Library          SeleniumLibrary
Library          DataDriver            file=private.csv    dialect=unix

[ ERROR ] Calling method '_start_suite' of listener 'DataDriver' failed: ImportError: Pandas requires version '2.5.7' or newer of 'openpyxl' (version '2.5.1' currently installed).

Hi,

When run with test case simple like below

*** Settings ***
Library DataDriver data1.xlsx
Test Template Invalid Login

*** Test Case ***
Login with ${user}

*** Keywords ***
Invalid login
[Arguments] ${user}
Log ${user.password}

get error like

[ ERROR ] Calling method '_start_suite' of listener 'DataDriver' failed: ImportError: Pandas requires version '2.5.7' or newer of 'openpyxl' (version '2.5.1' currently installed).

what is means ?

datadriver support for dictionary

I have recently tried out your Data driver library with excel and its working like charm and it’s really a great solution for many people including me who relays on data driven testing a lot.
The Data source that I use is dictionaries and not excel. I was wondering Data driven Library can help me to sort this problem. I am reaching out to you since I couldn’t find any documentation of data driver with dictionary.
Given below is a sample program format that we are using internally if you can share some insight it would be a great help.

*** Settings ***
Test Template Example keyword

Variables
&{dictionary1} argument=first tag=first tag
&{dictionary2} argument=second tag=second tag
&{dictionary3} argument=third tag=third tag
&{dictionary4} argument=fourth tag=fourth tag

*Keywords
Example keyword
[Arguments] ${dictionary}
log ${dictionary.argument}
Set tags ${dictionary.tag}

*** Test Cases **
Templated test case
[Template] Example keyword
${dictionary1}
${dictionary2}
${dictionary3}
${dictionary4}

[feature request] Allow declaring a TestCaseData as skipped

Hello,

Pytest allows dynamically marking parameterized test as skipped, which has the benefit to clearly show which tests were skipped in the output.

There doesn't seem to be a way to do this with DataDriver, hence I'm opening this feature request (as requested on #datadriver in Slack)

Thank you!

Testcases do not get executed

Since version 0.3.1 my datadriver testcases are not being executed properly. The tests do not fail, they pass whilst simply not being executed. The strange thing is, DataDriver seems to run properly and even sees the testcases but is just skipping them.

Console Output (DEBUG):
...
[ DataDriver ] Initialized in xlsx-mode.
[ DataDriver ] Reader Module: <module 'DataDriver.xlsx_reader' from 'c:\program files (x86)\python36-32\lib\site-packages\DataDriver\xlsx_reader.py'>
[ DataDriver ] Opening file 'C:...\ ../nameChanged.xlsx'
[ DataDriver ] 11 Test Cases loaded...
Web App.Someapp.Load Something.Load Something :: Documentationstring, ... | PASS |
0 critical tests, 0 passed, 0 failed
0 tests total, 0 passed, 0 failed
...

Versions:
python 3.6.8 (32 bit)
robotframework 3.1.2
robotframework-datadriver 0.3.1

Add argument `add_tags` to DataDriver init

The current issue is that it is not clear what happens with tags of the template test to all generated tests.

Options:

  • The Tags of the template test could be added to all tests.
  • No Tags of template is added to all tests.
  • only Tags that are not used in the data source are added...

:-/

--prerunmodifier DataDriver.rerunfailed

I have installed Robotframework, using Python2.7 on a linux machine. I have try to re-execute the failed test cases using this command 'robot --prerunmodifier DataDriver.rerunfailed:output.xml --output rerun.xml'. I am getting the following error,

Importing model modifier 'DataDriver.rerunfailed' failed: Module 'DataDriver' does not contain 'rerunfailed'.

--include <tag> --exclude <tag> not working as expected

Having an issue with test filtering logic when trying to use both --include and --exclude options.

Using this dummy suite:

*** Settings ***
Documentation     Foo 1

Library           DataDriver
...    reader_class=tests\\foodriver\\foo_reader.py

Test Template    Foo Template

Default Tags    default
#Force Tags    forced

*** Variables ***

*** Test Cases ***
Execute Toolchain for ${fooarg}

*** Keywords ***
Foo Template
    [Arguments]    ${fooarg}
    Log    ${fooarg}

And custom driver:

from DataDriver.AbstractReaderClass import AbstractReaderClass
from DataDriver.ReaderConfig import TestCaseData


class foo_reader(AbstractReaderClass):

    def get_data_from_source(self):
        return self._read_file_to_data_table()

    def _read_file_to_data_table(self):
        test_data = []
        flipflop = True
        for i in range(6):
            args = {'${fooarg}': i}
            tags = ["flop"]
            if flipflop:
                tags = ["flip"]
                flipflop = False
            else:
                flipflop = True
            test_data.append(TestCaseData(f"Test {i}", args, tags))
        return test_data

robot --include default --include flipORflop tests\foodriver -> 6 cases
robot --include default --include flip tests\foodriver -> 3 cases
robot --include default --exclude flip tests\foodriver -> 0 cases (expected 3)
robot --include default --exclude NOTflip tests\foodriver -> 0 cases (expected 3)

(seems to be working similarly also when 'default' is forced)

The need to specify a test suite in ${DYNAMICTEST(S)} is somewhat cumbersome

Just imagine having to type this:

robot --variable "DYNAMICTESTS:MyDataDrivenTestSuiteWithParticularlyLongName.0101|MyDataDrivenTestSuiteWithParticularlyLongName.0102|MyDataDrivenTestSuiteWithParticularlyLongName.0103" MyDataDrivenTestSuiteWithParticularlyLongName.robot

Yeah you can copy'n'paste, but in a real world example you would want to copy'n'paste the test names as well, and having to insert the suite name in between test names is cumbersome (and in the frequent case that one specifies a single robot file on the command line, it's also redundant).

I think it would be great if the test suite part were optional.

I'd be willing to contribute a pull request.

DataDriver.rerunfailed executes Passed tests if there are no failures in the original test

When re-executing a test suite with a --prerunmodifier DataDriver.rerunfailed I see that it executes again all the tests if there are no failures in the original execution.

look at the attached 7zip file

When executing run_has_failure.bat I see that only the failed test is executed in the second and third attempt.
However, when executing run_all_passes.bat, the three passed tests are executed again in the two reruns.

This causes massive overheads in the execution of test pipelines.

I tried it with windows 10 pro and python version 3.7.4.
Versions of robotframework and robotframework-datadriver are in the requirements.txt file in the zip.

Note, I also tried it with robotframework-datadriver version 1.0.0 and got similar results.

Connection error in log file when using DataDriver with Browser library

I get this error message in the log file when I use DataDriver along with Browser library:

Error in library 'Browser': Calling method '_close' of listener 'Browser' failed: failed to connect to all addresses

I did not get a stack trace because the error does not interfere with test execution (yet). It is just displayed in the log file. My browser lib version is 1.3.0 and my DataDriver version is 0.3.3.
image

Custom reader from absolut path

I want to create a custom reader, which is located within my sources.
Therefore it would be neat to be able to pass an absolut path to the DataDriver settings and tell it where my custom reader is.
See push request #13

Escaping commas in dictionary variables

Hello. Could someone please tell me how to escape commas in dict variables?

I have dict varibale in xlsx file like below:

&{expected_message}
code=1,message=Date is a required field, but was not found...

Already tried adding ,\ or \\ before comma yet still getting error like

Invalid dictionary variable item "but was not found..."

Thank you

Test Teardown broken in DataDriver latest versions

Stumbled on this problem. Task/Test Teardown works on DataDriver version 1.0.0 but on the newer ones. Using RF version 3.2.2.
Attached is a sample test and log.html's for executions.

Teardown works if you add it to the Task/Test Template keyword.
datadriver.zip

Same thing as in #41

Excel input files: unable to execute tests by tag

I have this very simple Robot Test which uses an Excel sheet (datadriver.xlsx) as data source:

*** Settings ***
Library         DataDriver   file=datadriver.xlsx
Test Template	DataDriver Demo Test Main

*** Variables ***
${JSON_BODY}	${EMPTY}

*** Test Cases ***
DataDriver Demo Test Call '${API_CALL}'
	[Documentation]	Run the test cases for method ${API_CALL}

*** Keywords ***
DataDriver Demo Test Main
	[arguments]    ${API_CALL}  ${VAR1}  ${VAR2}
	Run Keyword  DataDriver_Demo_Test_${API_CALL}  ${API_CALL}  ${VAR1}  ${VAR2}

DataDriver_Demo_Test_Call_One
	[arguments]    ${API_CALL}   ${VAR1}  ${VAR2}
	Log To Console		Call One

DataDriver_Demo_Test_Call_Two
	[arguments]    ${API_CALL}   ${VAR1}  ${VAR2}
	Log To Console		Call Two

The Excel text file contains multiple tags per test case.
xls

RF recognises these tags and lists them correctly in the test's associated report file.
rf

However, if I try to run a single test based on its tags value, the test cannot be found.

C:\Test_Cases\interneTestsAPI\DataDriver_Tag_Test>robot -i world_domination datadriver.robot
[ ERROR ] Suite 'Datadriver' contains no tests matching tag 'world domination'.

Try --help for usage information.

C:\Test_Cases\interneTestsAPI\DataDriver_Tag_Test>

My assumption is that this is a limitation with the Excel input file digestion as the -i option is triggered before you can actually examine the Excel input file and get the tags from there. I have consulted this article but can't really see an error with my code. Am I missing something here?

Misnamed Readme.rst file fails Setuptools build

It fails like so, due to the different capitalization used:

running "python setup.py" with command "build" and parameters ()
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "setup.py", line 8, in <module>
    with open("README.rst", "r", encoding="utf-8") as fh:
FileNotFoundError: [Errno 2] No such file or directory: 'README.rst'

tags usage for robotframework-datadriver

Hello,

I'm using Robot Framework 3.2.1 (Python 3.7.7 on win32) with robotframework-datadriver Version: 0.3.6.
With this 0.3.6 version, I set the force Tags for test.robot file with Tag_1 and Tag_2, in the Excel data-driven table, I marked some lines with Tag_1 and some line with Tag_2.
When run the test.robot file with command
robot -e Tag_1 -i Tag_2 test.robot
It failed to show that
It contains no tests matching tag 'Tag_2' and not matching tag 'Tag_1'.

So how can I run the lines with marked Tag_2?

BTW, if we want to upgrade robotframework-datadriver to newer version with still keep using Robotframework 3.2.1, which version can I use?

Thanks in advance

basic example doesn't seem to work

Hi Rene,

I'm using RoboCloud Editor "Robocode Lab".

The basic example doesn't seem to work.

  1. I have to define the Template Keyword before the section Test Cases, or when running the robot complains it cannot find such keyword.

  2. It raises an exception when declaring the DataDriver Library, however I can get away by not declaring it, which seems a bit odd not having to declare the Library under settings.

  3. It skips the first argument

Please see attachments

Thanks,
Daniel
Screenshot 2020-07-03 at 12 48 37
Screenshot 2020-07-03 at 12 44 51

Create empty list in @{list}-cell

Empty cells are read as list with single-entry empty string [ '' ], not as empty list [ ].
Is this behavior intended and is it possible to create an empty list without using python literals?

Behavior tested with xls and csv input with both v1.2.0 and v1.3.0.

CSV to reproduce:

*** Test Cases ***;@{list1};e{list2}
CheckList1;not,empty,list;['not','empty','list']
CheckList2;;[]

Variable '${TEST STATUS}' not found

Robot framework has TEST STATUS variable which is set to current status of test case. This variable is available in non template test cases (without using data driver) but when tests are run using data driver, this variable is not available.

*** Settings ***
Library           DataDriver    1.csv    optimize_pabot=Atomic
Test Template     Data Driver Test

*** Keywords ***
Data Driver Test
    [Arguments]    ${var}
    ....
    [Teardown]    Log to console    ${TEST STATUS}

robot  --variable DYNAMICTEST:'xxx'  test.robot

Variable '${TEST STATUS}' not found. Did you mean:
    ${PREV_TEST_STATUS}

Enhancement: support AbstractReaderClass subclasses as reader_class argument value

Subclassing DataDriver when there is a need to use a custom reader_class is somewhat cumbersome at the moment since the init of DataDriver will try to resolve the reader_class based on filename. This can be improved by allowing AbstractReaderClass subclasses to be passed as the reader_class argument and having DataDriver check for subclass before trying to import the module from file path.

I can't setup data driver

I am trying to setup data driver and am getting the below error
ERROR: Could not find a version that satisfies the requirement robotframework-datadriver (from versions: none)

And I tried to search for this problem a lot and I couldn't resolve it, the below are the packages and python version what I have
Python 3.9.6
pip 21.1.3
robotframework 3.2.2
robotframework-databaselibrary 1.2.4
robotframework-pabot 1.10.1
robotframework-pythonlibcore 2.2.1
robotframework-selenium2library 3.0.0
robotframework-seleniumlibrary 5.0.0
selenium 3.141.0
setuptools 56.0.0
urllib3 1.26.3

When will you refactor the Data Model?

I'm using xlsx as data sources and would like to remove the variable pattern as current. If we can remove $ or @ so it will be more friendly with manual tester and the old files they had.
I love your lib but we need to improve more so the community can use easily.

Thanks,
Doanh Nguyen

How can we read data from multiple sheets in a single test suite file?

Scenario : In a single test case file, If we have two test cases and we have maintained test data for these two test cases in two separate sheets of same .xlsx file and we want to use sheet-1 in test-case-1 and sheet-2 in test-case2.

Question : Is it possible using data-driver?

Datadriver not picking up test case name from CSV

I thought I saw in tutorials that DataDriver would pick up test case names from the CSV file, but that doesn't seem to be happening for me. The tests are definitely running, and the [Documentation] data is being picked up. Here is my setup:
DATA

*** Test Cases ***,${username},${password},${email},${url_complete},[Tags],[Documentation]
Register New User,hgb55,xxxyyy,[email protected],${success_url},,Manually confirm this user does not exist already
Try and register existing user,hgb55,xxxzzz,[email protected],${registration_url},,
Try a password that is too simple,hb999,what,[email protected],${registration_url},,
Try another password that is too simple,hb999,whatever,[email protected],${registration_url},,

TASKS.ROBOT

*** Settings ***
Documentation     Main test suite for registering deals users.
Library           RPA.Browser.Selenium
Library           OperatingSystem
Library           DataDriver    Deals.csv    dialect=userdefined    delimiter=,    encoding='utf-8'
Resource          ../.env.robot
Test Template     Register as a deals user
Suite Teardown    Close all browsers

*** Variables ***
${registration_url}    ${HOST}/deals/registerusers/    # Don't change variable name - in CSV file too.
${success_url}    ${HOST}/accounts/register/complete/    # Don't change variable name - in CSV file too.

*** Test Cases ***
Register with user '${username}' and password '${password}'
    Default    UserData

followed by the "Register as a deals user" keyword - which does execute.

Am I missing something?

Test Teardown in DataDriver

Hello,

I have realised that in current version Test Teardown using Data driver Library is not working. Can you please take a look if it is an issue ?

Regards,

RF Variable Syntax not considered in columns for dictionary values

In my CSV/XLS file I have a column with name ${data.value} and the value for the testcases should always be an integer.
I tried to put in the number without RF Syntax (e.g. 12) and with RF syntax for int (e.g. ${12}).
In both cases the value is handled as string, this is the case for CSV and Excel files as well.
Log ${data} => {'value': '12}
Log ${data} => {'value': '${12}'}

I would expect in the second case: {'value': 12}

Create a possibility to execute Testsuites with the option "rerunfailed"

There should be a possibility to rerun failed DataDriven tests.

Stage 1: run robot with a list of failed tests:
robot --variable DYNAMICTESTS:suitename.testcase1|suitename.testcase4|suite2name.testcase2 mytests

The Variable DYNAMICTESTS may contain a list of test cases "|" (pipe) seperated.
Only test cases that matches one of these names will be executed.

Stage 2:
Create a PreRunModifier that fills the variable DYNAMICTESTS with failed Datadriven tests and deletes all passed testcases from the test model before execution.

Rerunfailed test cases in parallel with pabot

Hello,

With the latest update I'm having issue to rerun failed test cases in parallel with pabot.

I have an Excel sheet that contains 450 test cases and I'm using Datadriver in my robot file with:
Library DataDriver file=MyFile.xlsx sheet_name=Test cases optimize_pabot=Atomic

Here is the way I am launching it:

First run:
pabot.exe --testlevelsplit --pabotlib --pabotlibhost %PABOT_HOST% --pabotlibport %PABOT_PORT% --processes 40 -d %RESULTDIR% -o orig.xml -l orig_log.html -r orig_report.html -e %RF_EX_TAGS% %TESTS_FILE_PATH%

Everything runs in parallel but the outcome I have several failures (50/450 test cases) so I want to retry those 50 failed one but in parallel as well therefore I'm using:

pabot.exe --testlevelsplit --pabotlib --pabotlibhost %PABOT_HOST% --pabotlibport %PABOT_PORT% --processes 40 -d %RESULTDIR%/ -o rerun.xml -l rerun_log.html -r rerun_report.html -e %RF_EX_TAGS% --prerunmodifier DataDriver.rerunfailed;%RESULTDIR%/orig.xml %TESTS_FILE_PATH%

The outcome of the rerun is that it's running one by one the failed test cases and not in parallel :(

Am I doing it wrong for the rerun?

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.