Skip to content

Instantly share code, notes, and snippets.

@Tset-Noitamotua
Last active February 7, 2024 08:35
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save Tset-Noitamotua/75d15a2beb9ab6f1931d3871172ebbbf to your computer and use it in GitHub Desktop.
Save Tset-Noitamotua/75d15a2beb9ab6f1931d3871172ebbbf to your computer and use it in GitHub Desktop.
HOW-TO enable MarkDown support in RobotFramework

HOW-TO enable MarkDown support in RobotFramework

You want to execute robot test which are inside fenced code blocks of a markdown file (.md) like any normal robot test? Follow the steps below then you can run your tests as simple as robot your_test_suite.md with all robot command line execution options.

This will add support for .md files to RF

  1. Clone RobotFramework repository
  2. Save the code below as 'mdreader.py' in parsing folder of your local clone. It's based on restreader.py
  3. Add this from .mdreader import MarkDownReader here to your local clone.
  4. Add this , 'md': MarkDownReader here to your local clone. It should then look like this:
    READERS = {'html': HtmlReader, 'htm': HtmlReader, 'xhtml': HtmlReader,
            'tsv': TsvReader , 'rst': RestReader, 'rest': RestReader,
            'txt': TxtReader, 'robot': TxtReader, 'md': MarkDownReader}
  5. Now install RobotFramework from source of your local clone with python setup.py install.
  6. FINISH: you should now be able to execute tests in MarkDown file format (try robotframework_example.md below)

NOTE: You could also do all above modification to your already installed RobotFramework version without cloning the source. Usually you find your RF installation under Lib/site-packages/robot of your Python installation if you used PIP to intall RF.

from io import BytesIO
from io import StringIO
from .txtreader import TxtReader
def MarkDownReader():
class MarkDownReader(object):
def __init__(self):
self.robot_lines = []
self.robot_data = ''
def robotize(self, md_file):
print('\n========== INPUT :\n', md_file,':')
# uncomment next two lines if want to see raw input in console
# print('\n', md_file.read())
# md_file.seek(0)
f = StringIO(md_file.read().decode('UTF-8'))
print('\n========== TEMP :\n', f)
try:
include_line = False
for line in f.readlines():
if not include_line:
include_line = line.strip().lower() == "```robotframework"
elif line.strip() == "```":
include_line = False
else:
self.robot_lines.append(line)
self.robot_data = str(''.join(self.robot_lines))
finally:
f.close()
print('\n========== OUTPUT :\n', self.robot_data)
return self.robot_data
def read(self, md_file, rawdata):
return self._read_text(self.robotize(md_file), rawdata)
# return self._read_html(doctree, rawdata)
def _read_text(self, data, rawdata):
txtfile = BytesIO(data.encode('UTF-8'))
return TxtReader().read(txtfile, rawdata)
return MarkDownReader()

Executable Robot Framework Test Documenation

This is an example of executable Robot Framework test data/documentation in a MarkDown (.md) file format. Keep all your test automation assets in one place. This is almost real SSOF (Single Source of Truth), SPOT (Single Point of Truth) or call it what you like - it's just cool!

This example demonstrates how your executable RF test documentation looks like in MarkDowns's preview mode. It's pure joy to look at such documentation and - even more joy to work with it!

Of course you can use links to better navigate across this file (e.g. see Section III) or to link to other documents.

Section I

Let's start with a simple log test case.

# This is a Robot Framework specific MarkDown code block.
# Only such code blocks will be executed when running tests with Robot's test runner.
# Of course comments like this lines will be ignored by the runner!
# Same way as they are ignored in .robot files

*** Settings ***
Library    Collections

*** Test Cases ***
001 Simple Log Test Case
    Log    Hello Python!
    Log Many          Robot  Framework  Rules!!!

Section II

Let's organize our tasks, todos and what else ...

TODOs

  • Task 001
  • Task 002 (done)
  • Task 003 (totally done)

Ordered Lists

  1. Test Step äää ÄÄÄ üüü ÜÜÜÜ ßßß No problems with Umlauten thanks to UTF-8 encoding and Python 3
  2. Test Step
  3. Test Step

Unordered Lists

  • mkdocs new [dir-name] - Create a new project.
  • mkdocs serve - Start the live-reloading docs server.
  • mkdocs build - Build the documentation site.
  • mkdocs help - Print this help message.

Images

You can make beautiful documentation with images, screenshots, etc. ...

Python_Logo

(Python) Code Examples

Have you written a custom RF Library? Document code examples here!

def my_function(args):
    print('Damn Sexy Python Code!')

And don't be afraid your code examples won't be executed! Only Robot Framework code block will be executed - like the one we have already seen above and the one that follows below:

# Another Robot Framework code block which will be executed by Robot's test runner!
# RF code blocks may be destributed all over the .md file!
# They don't have to be at one peace / in one place!

*** Settings ***
Library    Collections

*** Test Cases ***
002 Easy Robot Test
    Log    Hello Python!
    Log Many          Robot  Framework  Rules!!!

Section III

some text some more text

*** Settings ***
Library    RequestsLibrary

*** Test Cases ***
003 GET (extern)
    [Documentation]   GET http://httpbin.org/headers
    [Tags]            extern
    Create Session    httpbin  http://httpbin.org
    ${response}=      Get Request   httpbin   /headers
    log              ${response}
*** Settings ***
Library   RequestsLibrary
Library   Collections
 
*** Test Cases ***
004 GET (extern)
  [Documentation]   GET http://httpbin.org/headers
  [Tags]            extern
  Create Session    httpbin  http://httpbin.org
  ${response}=      Get Request  httpbin  /headers
  log  ${response}
  log  ${response.raw}
  log  ${response.text}
  log  ${response.content}
  log  ${response.encoding}
  log  ${response.status_code}
  log  ${response.json()}
  log  @{response.json()}
  log  @{response.json()}[0]
  log  &{response.json()}[headers]
  &{headers}=  Set Variable  &{response.json()}[headers]
  log  &{headers}[Host]
  log  @{headers}[0]
  log  @{headers}[1]
  Should Contain    ${response.text}  User-Agent
  Should Contain    &{response.json()}[headers]  Host
  Should Be Equal   &{headers}[Host]  httpbin.org
  Should Be Equal As Strings   &{headers}[Host]  httpbin.org

005 POST (extern)
| | [Documentation] | https://www.hurl.it/
| | ...             | POST https://yourapihere.com/
| | [Tags]          | yourapihere
| | &{headers}=     | Create Dictionary | name=tset_noitamotua | WHO_AM_I=ROBOT
| | &{data}=        | Create Dictionary | mydata=foo | yourdata=bar
| | &{params}=      | Create Dictionary | myparams=yourparams
| | &{args}=        | Create Dictionary | myargs=yourargs
| | Create Session  | yourapihere | https://yourapihere.com/
| | ${response}=    | Post Request | yourapihere | / | headers=${headers}
| |  ...            | data=${data}
| |  ...            | params=${params}
| | log | ${response}
| | log | ${response.raw}
| | log | ${response.text}
| | log | ${response.content}
| | log | ${response.encoding}
| | log | ${response.status_code}
| | log | ${response.json()}
| | log many | @{response.json()}
| | log many | @{response.json()}[0]
| | log | &{response.json()}[headers]
| | &{headers}= | Set Variable | &{response.json()}[headers]
| | log | &{headers}[Host]
| | log | @{headers}[0]
| | log | @{headers}[1]
| | Should Contain  | ${response.text} | User-Agent
| | Should Contain  | &{response.json()}[headers] | Host
| | Should Be Equal | &{headers}[Host] | yourapihere.com
| | Should Contain  | &{response.json()}[headers] | Who-Am-I
| | Should Be Equal | &{headers}[Who-Am-I] | ROBOT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment