From a7eef5afefe62d23272de600243fcd10b9356c42 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 11:12:36 +0000 Subject: [PATCH] deploy: 72a372cbd739bafc62cf9c552f3bf5bd79f025ea --- 404.html | 4 ++-- assets/js/{192704f0.ef1e6e02.js => 192704f0.0e4052d1.js} | 2 +- .../{runtime~main.8ba8047d.js => runtime~main.53b60522.js} | 2 +- docs.html | 4 ++-- docs/about/about_us.html | 4 ++-- docs/about/contribute.html | 4 ++-- docs/different_libraries/appium.html | 4 ++-- docs/different_libraries/browser.html | 4 ++-- docs/different_libraries/database.html | 4 ++-- docs/different_libraries/how_to_find_library.html | 4 ++-- docs/different_libraries/overview.html | 4 ++-- docs/different_libraries/requests.html | 4 ++-- docs/different_libraries/rpa.html | 4 ++-- docs/different_libraries/selenium.html | 6 +++--- docs/different_libraries/standard.html | 4 ++-- docs/examples/insurance.html | 4 ++-- docs/examples/mfa_login.html | 4 ++-- docs/examples/overview.html | 4 ++-- docs/examples/project_structure.html | 4 ++-- docs/examples/restfulbooker.html | 4 ++-- docs/examples/todo.html | 4 ++-- .../custom-libraries/non-python_library.html | 4 ++-- .../custom-libraries/python_library.html | 4 ++-- .../custom-libraries/releasing_your_own_libraries.html | 4 ++-- .../listeners_prerun_api/listeners.html | 4 ++-- .../listeners_prerun_api/overview.html | 4 ++-- .../listeners_prerun_api/prerunmodifier.html | 4 ++-- .../listeners_prerun_api/rf-api.html | 4 ++-- docs/flaky_tests.html | 4 ++-- docs/getting_started/ide.html | 4 ++-- docs/getting_started/rpa.html | 4 ++-- docs/getting_started/testing.html | 4 ++-- docs/getting_started/videos.html | 4 ++-- docs/parallel.html | 4 ++-- docs/parsing_results.html | 4 ++-- docs/reporting_alternatives.html | 4 ++-- docs/style_guide.html | 4 ++-- docs/testcase_styles/bdd.html | 4 ++-- docs/testcase_styles/datadriven.html | 4 ++-- docs/using_rf_in_ci_systems/ci.html | 4 ++-- docs/using_rf_in_ci_systems/ci/azure-devops.html | 4 ++-- docs/using_rf_in_ci_systems/ci/github-actions.html | 4 ++-- docs/using_rf_in_ci_systems/ci/gitlab.html | 4 ++-- docs/using_rf_in_ci_systems/ci/jenkins.html | 4 ++-- docs/using_rf_in_ci_systems/ci/teamcity.html | 4 ++-- docs/using_rf_in_ci_systems/docker.html | 4 ++-- docs/using_rf_in_ci_systems/playground.html | 4 ++-- docs/variables.html | 4 ++-- index.html | 4 ++-- markdown-page.html | 4 ++-- search.html | 4 ++-- 51 files changed, 101 insertions(+), 101 deletions(-) rename assets/js/{192704f0.ef1e6e02.js => 192704f0.0e4052d1.js} (72%) rename assets/js/{runtime~main.8ba8047d.js => runtime~main.53b60522.js} (69%) diff --git a/404.html b/404.html index b31474d7..72160912 100644 --- a/404.html +++ b/404.html @@ -5,13 +5,13 @@ Page Not Found | ROBOT FRAMEWORK - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/192704f0.ef1e6e02.js b/assets/js/192704f0.0e4052d1.js similarity index 72% rename from assets/js/192704f0.ef1e6e02.js rename to assets/js/192704f0.0e4052d1.js index 55f1553f..f681f311 100644 --- a/assets/js/192704f0.ef1e6e02.js +++ b/assets/js/192704f0.0e4052d1.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5419],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>f});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),u=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},c=function(e){var t=u(e.components);return n.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),p=u(r),d=o,f=p["".concat(s,".").concat(d)]||p[d]||m[d]||a;return r?n.createElement(f,i(i({ref:t},c),{},{components:r})):n.createElement(f,i({ref:t},c))}));function f(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:o,i[1]=l;for(var u=2;u{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={sidebar_label:"Selenium Library",title:"Selenium Library"},i=void 0,l={unversionedId:"different_libraries/selenium",id:"different_libraries/selenium",title:"Selenium Library",description:"SeleniumLibrary is a web testing library for Robot Framework that utilizes the Selenium tool internally. The project is hosted on GitHub and downloads can be found from PyPI.",source:"@site/docs/different_libraries/selenium.md",sourceDirName:"different_libraries",slug:"/different_libraries/selenium",permalink:"/docs/different_libraries/selenium",draft:!1,editUrl:"https://github.com/MarketSquare/robotframeworkguides/edit/main/website/docs/different_libraries/selenium.md",tags:[],version:"current",frontMatter:{sidebar_label:"Selenium Library",title:"Selenium Library"},sidebar:"tutorialSidebar",previous:{title:"Requests Library",permalink:"/docs/different_libraries/requests"},next:{title:"Standard Library",permalink:"/docs/different_libraries/standard"}},s={},u=[{value:"Installation instructions",id:"installation-instructions",level:2}],c={toc:u};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://github.com/robotframework/SeleniumLibrary/"},"SeleniumLibrary")," is a web testing library for ",(0,o.kt)("a",{parentName:"p",href:"https://robotframework.org"},"Robot Framework")," that utilizes the ",(0,o.kt)("a",{parentName:"p",href:"https://www.seleniumhq.org/"},"Selenium")," tool internally. The project is hosted on ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/robotframework/SeleniumLibrary"},"GitHub")," and downloads can be found from ",(0,o.kt)("a",{parentName:"p",href:"https://pypi.python.org/pypi/robotframework-seleniumlibrary"},"PyPI"),"."),(0,o.kt)("p",null,"See ",(0,o.kt)("a",{parentName:"p",href:"https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html"},"Keyword Documentation")," for available keywords and more information about the library in general."),(0,o.kt)("h2",{id:"installation-instructions"},"Installation instructions"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"pip install --upgrade robotframework-seleniumlibrary\n")),(0,o.kt)("p",null,"Afterwards you can import the library into your test case or resource file."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-robotframework"},'*** Settings ***\nLibrary SeleniumLibrary\n\n*** Test Cases ***\nLogin with correct Username and Password\n Open Browser url=https://the-internet.herokuapp.com/login browser=chrome\n Input Text username tomsmith\n Input Text password SuperSecretPassword!\n Click Button class:radius\n Element Should Contain id=flash You logged into a secure area!\n Click Link Logout\n Close Browser\n\nAdd Tasks And Set To Complete\n Open Browser url=https://todomvc.com/examples/angularjs/#/ browser=chrome\n Input Text class:new-todo Complete Robot Framework Training\n Press Keys class:new-todo RETURN\n Input Text class:new-todo Write Automated Tests\n Press Keys class:new-todo RETURN\n Input Text class:new-todo Take a nap\n Press Keys class:new-todo RETURN\n Element Text Should Be class:todo-count 3 items left\n Click Element xpath: //*[contains(text(), "Complete Robot Framework Training")]/../input\n Element Text Should Be class:todo-count 2 items left\n Click Element xpath: //*[contains(text(), "Write Automated Tests")]/../input\n Element Text Should Be class:todo-count 1 item left\n Click Element xpath: //*[contains(text(), "Take a nap")]/../input\n Element Text Should Be class:todo-count 0 items left\n')))}p.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[5419],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>f});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),u=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},c=function(e){var t=u(e.components);return n.createElement(l.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),p=u(r),d=o,f=p["".concat(l,".").concat(d)]||p[d]||m[d]||a;return r?n.createElement(f,i(i({ref:t},c),{},{components:r})):n.createElement(f,i({ref:t},c))}));function f(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=d;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[p]="string"==typeof e?e:o,i[1]=s;for(var u=2;u{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>p,frontMatter:()=>a,metadata:()=>s,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={sidebar_label:"Selenium Library",title:"Selenium Library"},i=void 0,s={unversionedId:"different_libraries/selenium",id:"different_libraries/selenium",title:"Selenium Library",description:"SeleniumLibrary is a web testing library for Robot Framework that utilizes the Selenium tool internally. The project is hosted on GitHub and downloads can be found from PyPI.",source:"@site/docs/different_libraries/selenium.md",sourceDirName:"different_libraries",slug:"/different_libraries/selenium",permalink:"/docs/different_libraries/selenium",draft:!1,editUrl:"https://github.com/MarketSquare/robotframeworkguides/edit/main/website/docs/different_libraries/selenium.md",tags:[],version:"current",frontMatter:{sidebar_label:"Selenium Library",title:"Selenium Library"},sidebar:"tutorialSidebar",previous:{title:"Requests Library",permalink:"/docs/different_libraries/requests"},next:{title:"Standard Library",permalink:"/docs/different_libraries/standard"}},l={},u=[{value:"Installation instructions",id:"installation-instructions",level:2}],c={toc:u};function p(e){let{components:t,...r}=e;return(0,o.kt)("wrapper",(0,n.Z)({},c,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,(0,o.kt)("a",{parentName:"p",href:"https://github.com/robotframework/SeleniumLibrary/"},"SeleniumLibrary")," is a web testing library for ",(0,o.kt)("a",{parentName:"p",href:"https://robotframework.org"},"Robot Framework")," that utilizes the ",(0,o.kt)("a",{parentName:"p",href:"https://www.seleniumhq.org/"},"Selenium")," tool internally. The project is hosted on ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/robotframework/SeleniumLibrary"},"GitHub")," and downloads can be found from ",(0,o.kt)("a",{parentName:"p",href:"https://pypi.python.org/pypi/robotframework-seleniumlibrary"},"PyPI"),"."),(0,o.kt)("p",null,"See ",(0,o.kt)("a",{parentName:"p",href:"https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html"},"Keyword Documentation")," for available keywords and more information about the library in general."),(0,o.kt)("h2",{id:"installation-instructions"},"Installation instructions"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-shell"},"pip install --upgrade robotframework-seleniumlibrary\n")),(0,o.kt)("p",null,"Afterwards you can import the library into your test case or resource file."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-robotframework"},'*** Settings ***\nLibrary SeleniumLibrary\n\n*** Test Cases ***\nLogin with correct Username and Password\n Open Browser url=https://the-internet.herokuapp.com/login browser=chrome\n Input Text username tomsmith\n Input Text password SuperSecretPassword!\n Click Button class:radius\n Element Should Contain id=flash You logged into a secure area!\n Click Link Logout\n Close Browser\n\nAdd Tasks And Set To Complete\n Open Browser url=https://todomvc.com/examples/angular/dist/browser/# browser=chrome\n Input Text css:.new-todo Complete Robot Framework Training\n Press Keys css:.new-todo RETURN\n Input Text css:.new-todo Write Automated Tests\n Press Keys css:.new-todo RETURN\n Input Text css:.new-todo Take a nap\n Press Keys css:.new-todo RETURN\n Element Text Should Be class:todo-count 3 items left\n Click Element xpath: //*[contains(text(), "Complete Robot Framework Training")]/../input\n Element Text Should Be class:todo-count 2 items left\n Click Element xpath: //*[contains(text(), "Write Automated Tests")]/../input\n Element Text Should Be class:todo-count 1 item left\n Click Element xpath: //*[contains(text(), "Take a nap")]/../input\n Element Text Should Be class:todo-count 0 items left\n')))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.8ba8047d.js b/assets/js/runtime~main.53b60522.js similarity index 69% rename from assets/js/runtime~main.8ba8047d.js rename to assets/js/runtime~main.53b60522.js index 96f8427c..dd395195 100644 --- a/assets/js/runtime~main.8ba8047d.js +++ b/assets/js/runtime~main.53b60522.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,t,d,r,f={},b={};function c(e){var a=b[e];if(void 0!==a)return a.exports;var t=b[e]={exports:{}};return f[e].call(t.exports,t,t.exports,c),t.exports}c.m=f,e=[],c.O=(a,t,d,r)=>{if(!t){var f=1/0;for(i=0;i=r)&&Object.keys(c.O).every((e=>c.O[e](t[o])))?t.splice(o--,1):(b=!1,r0&&e[i-1][2]>r;i--)e[i]=e[i-1];e[i]=[t,d,r]},c.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return c.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,c.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var r=Object.create(null);c.r(r);var f={};a=a||[null,t({}),t([]),t(t)];for(var b=2&d&&e;"object"==typeof b&&!~a.indexOf(b);b=t(b))Object.getOwnPropertyNames(b).forEach((a=>f[a]=()=>e[a]));return f.default=()=>e,c.d(r,f),r},c.d=(e,a)=>{for(var t in a)c.o(a,t)&&!c.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},c.f={},c.e=e=>Promise.all(Object.keys(c.f).reduce(((a,t)=>(c.f[t](e,a),a)),[])),c.u=e=>"assets/js/"+({53:"935f2afb",353:"f041c855",562:"4a676520",633:"78b86cd7",804:"a35b9c0d",1096:"3966c8c2",1100:"85218b1d",1133:"7f054a2a",1285:"16d94906",1462:"a7077ceb",2141:"08b0fd35",2144:"08a7e062",2368:"f075db55",2375:"e6e478e3",2573:"095b8897",2865:"caefbe75",2973:"c0c65583",3085:"1f391b9e",3273:"03a26634",3389:"41b8106b",3727:"3dad4aae",4009:"15a8aaa8",4151:"3d107528",4173:"4edc808e",4195:"c4f5d8e4",4303:"d41c70b6",4410:"48956893",4804:"d335e700",4920:"bad50669",5036:"4397b8f1",5049:"2abe96bb",5368:"1e97172b",5419:"192704f0",5513:"06d554fa",5531:"e370ae18",5726:"629c335b",5851:"cffd46d3",5972:"8eaefd7d",6e3:"ed9667d2",6540:"c6452a81",6734:"2219eefb",6794:"379aa617",6829:"09bf824f",7133:"4974b2de",7414:"393be207",7456:"c948127d",7599:"71d14268",7688:"380dfa00",7918:"17896441",7920:"1a4e3797",8081:"a6354d69",8612:"88d9cf00",8917:"676949b8",9514:"1be78505",9910:"6bdacca9"}[e]||e)+"."+{53:"72638118",353:"50e64d7f",562:"fef05106",633:"3e234cb8",804:"b53e2ab2",817:"0fb1a9cf",883:"fe54c346",1096:"6a47ee84",1100:"1267d03a",1133:"5d8e6b07",1285:"40914ddb",1462:"820839da",2141:"8a2401d1",2144:"9d7eab1d",2368:"2e33d697",2375:"9197f4d2",2573:"1747c881",2865:"fd0ee329",2973:"be74d814",3085:"9b589a33",3273:"ee7b5931",3389:"7409ad97",3727:"3c119101",4009:"c5bdf611",4151:"b8147cfa",4173:"42dd3739",4195:"0036f44c",4303:"c63e6e35",4410:"75cdf8a8",4804:"6ee84642",4920:"d8c12bf2",4972:"617c8b99",5036:"75aadf85",5049:"c7aa1f44",5368:"4fec8c9e",5419:"ef1e6e02",5513:"e2fb7eff",5531:"5b6f38ec",5726:"eab22c94",5851:"194d41f7",5972:"2720623f",6e3:"7703dd47",6540:"28616925",6734:"fe350096",6780:"bfbf1a8a",6794:"2562f499",6829:"20af58ab",6945:"8e8e2060",7133:"5b742fdb",7414:"63c2c585",7456:"63382e50",7599:"0b3edbe7",7688:"2cd82bbd",7918:"2fac9ba8",7920:"6d4328fe",8081:"64c0c714",8555:"300056d0",8612:"e7ae5b70",8894:"46125374",8917:"83cf6653",9056:"7e3571b8",9514:"7b009ddc",9910:"056ba867"}[e]+".js",c.miniCssF=e=>{},c.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),c.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},r="website:",c.l=(e,a,t,f)=>{if(d[e])d[e].push(a);else{var b,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{b.onerror=b.onload=null,clearTimeout(s);var r=d[e];if(delete d[e],b.parentNode&&b.parentNode.removeChild(b),r&&r.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),o&&document.head.appendChild(b)}},c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.p="/",c.gca=function(e){return e={17896441:"7918",48956893:"4410","935f2afb":"53",f041c855:"353","4a676520":"562","78b86cd7":"633",a35b9c0d:"804","3966c8c2":"1096","85218b1d":"1100","7f054a2a":"1133","16d94906":"1285",a7077ceb:"1462","08b0fd35":"2141","08a7e062":"2144",f075db55:"2368",e6e478e3:"2375","095b8897":"2573",caefbe75:"2865",c0c65583:"2973","1f391b9e":"3085","03a26634":"3273","41b8106b":"3389","3dad4aae":"3727","15a8aaa8":"4009","3d107528":"4151","4edc808e":"4173",c4f5d8e4:"4195",d41c70b6:"4303",d335e700:"4804",bad50669:"4920","4397b8f1":"5036","2abe96bb":"5049","1e97172b":"5368","192704f0":"5419","06d554fa":"5513",e370ae18:"5531","629c335b":"5726",cffd46d3:"5851","8eaefd7d":"5972",ed9667d2:"6000",c6452a81:"6540","2219eefb":"6734","379aa617":"6794","09bf824f":"6829","4974b2de":"7133","393be207":"7414",c948127d:"7456","71d14268":"7599","380dfa00":"7688","1a4e3797":"7920",a6354d69:"8081","88d9cf00":"8612","676949b8":"8917","1be78505":"9514","6bdacca9":"9910"}[e]||e,c.p+c.u(e)},(()=>{var e={1303:0,532:0};c.f.j=(a,t)=>{var d=c.o(e,a)?e[a]:void 0;if(0!==d)if(d)t.push(d[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var r=new Promise(((t,r)=>d=e[a]=[t,r]));t.push(d[2]=r);var f=c.p+c.u(a),b=new Error;c.l(f,(t=>{if(c.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var r=t&&("load"===t.type?"missing":t.type),f=t&&t.target&&t.target.src;b.message="Loading chunk "+a+" failed.\n("+r+": "+f+")",b.name="ChunkLoadError",b.type=r,b.request=f,d[1](b)}}),"chunk-"+a,a)}},c.O.j=a=>0===e[a];var a=(a,t)=>{var d,r,f=t[0],b=t[1],o=t[2],n=0;if(f.some((a=>0!==e[a]))){for(d in b)c.o(b,d)&&(c.m[d]=b[d]);if(o)var i=o(c)}for(a&&a(t);n{"use strict";var e,a,t,d,f,r={},b={};function c(e){var a=b[e];if(void 0!==a)return a.exports;var t=b[e]={exports:{}};return r[e].call(t.exports,t,t.exports,c),t.exports}c.m=r,e=[],c.O=(a,t,d,f)=>{if(!t){var r=1/0;for(i=0;i=f)&&Object.keys(c.O).every((e=>c.O[e](t[o])))?t.splice(o--,1):(b=!1,f0&&e[i-1][2]>f;i--)e[i]=e[i-1];e[i]=[t,d,f]},c.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return c.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,c.t=function(e,d){if(1&d&&(e=this(e)),8&d)return e;if("object"==typeof e&&e){if(4&d&&e.__esModule)return e;if(16&d&&"function"==typeof e.then)return e}var f=Object.create(null);c.r(f);var r={};a=a||[null,t({}),t([]),t(t)];for(var b=2&d&&e;"object"==typeof b&&!~a.indexOf(b);b=t(b))Object.getOwnPropertyNames(b).forEach((a=>r[a]=()=>e[a]));return r.default=()=>e,c.d(f,r),f},c.d=(e,a)=>{for(var t in a)c.o(a,t)&&!c.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},c.f={},c.e=e=>Promise.all(Object.keys(c.f).reduce(((a,t)=>(c.f[t](e,a),a)),[])),c.u=e=>"assets/js/"+({53:"935f2afb",353:"f041c855",562:"4a676520",633:"78b86cd7",804:"a35b9c0d",1096:"3966c8c2",1100:"85218b1d",1133:"7f054a2a",1285:"16d94906",1462:"a7077ceb",2141:"08b0fd35",2144:"08a7e062",2368:"f075db55",2375:"e6e478e3",2573:"095b8897",2865:"caefbe75",2973:"c0c65583",3085:"1f391b9e",3273:"03a26634",3389:"41b8106b",3727:"3dad4aae",4009:"15a8aaa8",4151:"3d107528",4173:"4edc808e",4195:"c4f5d8e4",4303:"d41c70b6",4410:"48956893",4804:"d335e700",4920:"bad50669",5036:"4397b8f1",5049:"2abe96bb",5368:"1e97172b",5419:"192704f0",5513:"06d554fa",5531:"e370ae18",5726:"629c335b",5851:"cffd46d3",5972:"8eaefd7d",6e3:"ed9667d2",6540:"c6452a81",6734:"2219eefb",6794:"379aa617",6829:"09bf824f",7133:"4974b2de",7414:"393be207",7456:"c948127d",7599:"71d14268",7688:"380dfa00",7918:"17896441",7920:"1a4e3797",8081:"a6354d69",8612:"88d9cf00",8917:"676949b8",9514:"1be78505",9910:"6bdacca9"}[e]||e)+"."+{53:"72638118",353:"50e64d7f",562:"fef05106",633:"3e234cb8",804:"b53e2ab2",817:"0fb1a9cf",883:"fe54c346",1096:"6a47ee84",1100:"1267d03a",1133:"5d8e6b07",1285:"40914ddb",1462:"820839da",2141:"8a2401d1",2144:"9d7eab1d",2368:"2e33d697",2375:"9197f4d2",2573:"1747c881",2865:"fd0ee329",2973:"be74d814",3085:"9b589a33",3273:"ee7b5931",3389:"7409ad97",3727:"3c119101",4009:"c5bdf611",4151:"b8147cfa",4173:"42dd3739",4195:"0036f44c",4303:"c63e6e35",4410:"75cdf8a8",4804:"6ee84642",4920:"d8c12bf2",4972:"617c8b99",5036:"75aadf85",5049:"c7aa1f44",5368:"4fec8c9e",5419:"0e4052d1",5513:"e2fb7eff",5531:"5b6f38ec",5726:"eab22c94",5851:"194d41f7",5972:"2720623f",6e3:"7703dd47",6540:"28616925",6734:"fe350096",6780:"bfbf1a8a",6794:"2562f499",6829:"20af58ab",6945:"8e8e2060",7133:"5b742fdb",7414:"63c2c585",7456:"63382e50",7599:"0b3edbe7",7688:"2cd82bbd",7918:"2fac9ba8",7920:"6d4328fe",8081:"64c0c714",8555:"300056d0",8612:"e7ae5b70",8894:"46125374",8917:"83cf6653",9056:"7e3571b8",9514:"7b009ddc",9910:"056ba867"}[e]+".js",c.miniCssF=e=>{},c.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),c.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),d={},f="website:",c.l=(e,a,t,r)=>{if(d[e])d[e].push(a);else{var b,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{b.onerror=b.onload=null,clearTimeout(s);var f=d[e];if(delete d[e],b.parentNode&&b.parentNode.removeChild(b),f&&f.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),o&&document.head.appendChild(b)}},c.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},c.p="/",c.gca=function(e){return e={17896441:"7918",48956893:"4410","935f2afb":"53",f041c855:"353","4a676520":"562","78b86cd7":"633",a35b9c0d:"804","3966c8c2":"1096","85218b1d":"1100","7f054a2a":"1133","16d94906":"1285",a7077ceb:"1462","08b0fd35":"2141","08a7e062":"2144",f075db55:"2368",e6e478e3:"2375","095b8897":"2573",caefbe75:"2865",c0c65583:"2973","1f391b9e":"3085","03a26634":"3273","41b8106b":"3389","3dad4aae":"3727","15a8aaa8":"4009","3d107528":"4151","4edc808e":"4173",c4f5d8e4:"4195",d41c70b6:"4303",d335e700:"4804",bad50669:"4920","4397b8f1":"5036","2abe96bb":"5049","1e97172b":"5368","192704f0":"5419","06d554fa":"5513",e370ae18:"5531","629c335b":"5726",cffd46d3:"5851","8eaefd7d":"5972",ed9667d2:"6000",c6452a81:"6540","2219eefb":"6734","379aa617":"6794","09bf824f":"6829","4974b2de":"7133","393be207":"7414",c948127d:"7456","71d14268":"7599","380dfa00":"7688","1a4e3797":"7920",a6354d69:"8081","88d9cf00":"8612","676949b8":"8917","1be78505":"9514","6bdacca9":"9910"}[e]||e,c.p+c.u(e)},(()=>{var e={1303:0,532:0};c.f.j=(a,t)=>{var d=c.o(e,a)?e[a]:void 0;if(0!==d)if(d)t.push(d[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var f=new Promise(((t,f)=>d=e[a]=[t,f]));t.push(d[2]=f);var r=c.p+c.u(a),b=new Error;c.l(r,(t=>{if(c.o(e,a)&&(0!==(d=e[a])&&(e[a]=void 0),d)){var f=t&&("load"===t.type?"missing":t.type),r=t&&t.target&&t.target.src;b.message="Loading chunk "+a+" failed.\n("+f+": "+r+")",b.name="ChunkLoadError",b.type=f,b.request=r,d[1](b)}}),"chunk-"+a,a)}},c.O.j=a=>0===e[a];var a=(a,t)=>{var d,f,r=t[0],b=t[1],o=t[2],n=0;if(r.some((a=>0!==e[a]))){for(d in b)c.o(b,d)&&(c.m[d]=b[d]);if(o)var i=o(c)}for(a&&a(t);n Welcome to | ROBOT FRAMEWORK - + @@ -15,7 +15,7 @@ If you have any questions, please reach out to our awesome community on Slack.

Docker and CI

How to run Robot Framework in Containers and in CI Systems

About Robot Framework Guides

Something about us and how to support the project

How to contribute

The Robot Framework Guides project is always looking for contributors. If you want to share your knowledge and practices, please join us on GitHub. You can find more details about how to contribute on our contributing page.

- + \ No newline at end of file diff --git a/docs/about/about_us.html b/docs/about/about_us.html index e7a7305b..3c24324c 100644 --- a/docs/about/about_us.html +++ b/docs/about/about_us.html @@ -5,7 +5,7 @@ About RF Guides | ROBOT FRAMEWORK - + @@ -20,7 +20,7 @@ So we needed a different platform to conserve that information - allowing other users to find that information easily.
That's when Robot Framework Guides was born.

How we do this

We want to be sure, our guides are helpful to a lot of people.
But as people learn differently, we did not want to focus on one specific method or medium.

So you will find

  • some written guides
  • combined with links to existing videos
  • maybe some embedded code examples
  • links to recipes of the Robot Framework Cookbook
  • whatever else comes to our mind
- + \ No newline at end of file diff --git a/docs/about/contribute.html b/docs/about/contribute.html index c8e71843..28af37c9 100644 --- a/docs/about/contribute.html +++ b/docs/about/contribute.html @@ -5,7 +5,7 @@ How to contribute | ROBOT FRAMEWORK - + @@ -14,7 +14,7 @@ You can use a _category_.json file to customize the sidebar label and the position of the folder.

{
"label": "Getting Started",
"position": 3
}

Static Files (e.g. images)

Static files (like images) are stored in the website/static folder here
They will be automatically included in the built and will be accessible via the / path (e.g. images are accessible via /img/robotframeworkguides_logo.png)

Updating Documentation

Run the development server

  • Go to directory containing the package.json file
  • Download dependencies via npm install
  • Run the development server via npm run start
  • Open the browser and navigate to http://localhost:3000
  • Make changes to the documentation files and check the changes in real time

Changes are visible in real time in the browser.
Development Server

Create Build and Push

  • Run the build via npm run build
  • Test the build locally with npm run serve
  • Open the browser and navigate to http://localhost:3000 to see the build
  • Commit the changes to the repository
  • Push the changes to GitHub (only the changed .md files and other static files - Do Not push the built .html files)
- + \ No newline at end of file diff --git a/docs/different_libraries/appium.html b/docs/different_libraries/appium.html index 79ca8078..9eda57e0 100644 --- a/docs/different_libraries/appium.html +++ b/docs/different_libraries/appium.html @@ -5,7 +5,7 @@ Appium Library | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@

Appium Library

Introduction

AppiumLibrary is an appium testing library for Robot Framework. Library can be downloaded from PyPI.
It uses Appium to communicate with Android and iOS application similar to how Selenium WebDriver talks to web browser.
It is supporting Python 3.7+ (since Appium Python Client doesn't support Python 2.7 anymore)

Tutorial Videos about RF and Appium

Link to Playlist: https://youtube.com/playlist?list=PL4GZKvvcjS3vAPWLqWbKZogkL5cD71yrT

Keyword Documentation

See Keyword Documentation for available keywords and more information about the library in general.

Installation

Install with pip:

pip install robotframework-appiumlibrary

Device Setup

After installing the library, you still need to setup an simulator/emulator or real device to use in tests. iOS and Android have separate paths to follow, and those steps better explained in Appium Driver Setup Guide. Please follow the Driver-Specific Setup according to platform.

Example

*** Settings ***
Documentation Simple example using AppiumLibrary
Library AppiumLibrary

*** Variables ***
${ANDROID_AUTOMATION_NAME} UIAutomator2
${ANDROID_APP} ${CURDIR}/demoapp/ApiDemos-debug.apk
${ANDROID_PLATFORM_NAME} Android
${ANDROID_PLATFORM_VERSION} %{ANDROID_PLATFORM_VERSION=11}

*** Test Cases ***
Should send keys to search box and then check the value
Open Test Application
Input Search Query Hello World!
Submit Search
Search Query Should Be Matching Hello World!


*** Keywords ***
Open Test Application
Open Application http://127.0.0.1:4723/wd/hub automationName=${ANDROID_AUTOMATION_NAME}
... platformName=${ANDROID_PLATFORM_NAME} platformVersion=${ANDROID_PLATFORM_VERSION}
... app=${ANDROID_APP} appPackage=io.appium.android.apis appActivity=.app.SearchInvoke

Input Search Query
[Arguments] ${query}
Input Text txt_query_prefill ${query}

Submit Search
Click Element btn_start_search

Search Query Should Be Matching
[Arguments] ${text}
Wait Until Page Contains Element android:id/search_src_text
Element Text Should Be android:id/search_src_text ${text}
- + \ No newline at end of file diff --git a/docs/different_libraries/browser.html b/docs/different_libraries/browser.html index 6c53d4fc..a0de61ec 100644 --- a/docs/different_libraries/browser.html +++ b/docs/different_libraries/browser.html @@ -5,7 +5,7 @@ Browser Library | ROBOT FRAMEWORK - + @@ -14,7 +14,7 @@ web page for more details.

Installation instructions

Only Python 3.7 or newer is supported.

  1. Install node.js e.g. from https://nodejs.org/en/download/
  2. Update pip pip install -U pip to ensure latest version is used
  3. Install robotframework-browser from the commandline: pip install robotframework-browser
  4. Install the node dependencies: run rfbrowser init in your shell
  • if rfbrowser is not found, try python -m Browser.entry init
caution

Don't forget to install node.js
https://nodejs.org/en/download/
The LTS version is recommended.

You can check your node.js version with node --version and your npm version with npm --version.

$ node --version
v18.12.0
$ npm --version
8.19.2
$ pip install robotframework-browser

$ rfbrowser init
Installing playwright...
Installing playwright-chromium...
Installing playwright-firefox...
Installing playwright-webkit...
Done!

See examples for ToDo App, MFA Login and Vehice Insurance.

- + \ No newline at end of file diff --git a/docs/different_libraries/database.html b/docs/different_libraries/database.html index fd8a7e73..e0be33f9 100644 --- a/docs/different_libraries/database.html +++ b/docs/different_libraries/database.html @@ -5,7 +5,7 @@ Database Library | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@

Database Library

Database Library is a Robot Framework library that provides keywords for interacting with databases.
It offers keywords to e.g.

  • connect to a database
  • execute SQL queries
  • fetch results from the database
  • assert table contents and result sets

Installation

Install from PyPI

pip install robotframework-databaselibrary

To connect to a database, you also need to install a Python Module adhearing to the Python Database API Specification v2.0.
You can find a list of supported database modules here.

Examples are:

Examples

Check out the tests folder in the repository for examples.

Example for a PostgreSQL database:

*** Settings ***
Suite Setup Connect To Database psycopg2 ${DBName} ${DBUser} ${DBPass} ${DBHost} ${DBPort}
Suite Teardown Disconnect From Database
Library DatabaseLibrary
Library OperatingSystem
Library Collections

*** Variables ***
${DBHost} localhost
${DBName} travis_ci_test
${DBPass} ""
${DBPort} 5432
${DBUser} postgres

*** Test Cases ***
Create person table
${output} = Execute SQL String CREATE TABLE person (id integer unique,first_name varchar,last_name varchar);
Log ${output}
Should Be Equal As Strings ${output} None

Execute SQL Script - Insert Data person table
Comment ${output} = Execute SQL Script ./${DBName}_insertData.sql
${output} = Execute SQL Script ./my_db_test_insertData.sql
Log ${output}
Should Be Equal As Strings ${output} None

Execute SQL String - Create Table
${output} = Execute SQL String create table foobar (id integer primary key, firstname varchar unique)
Log ${output}
Should Be Equal As Strings ${output} None

Check If Exists In DB - Franz Allan
Check If Exists In Database SELECT id FROM person WHERE first_name = 'Franz Allan';

Check If Not Exists In DB - Joe
Check If Not Exists In Database SELECT id FROM person WHERE first_name = 'Joe';

Table Must Exist - person
Table Must Exist person

Verify Row Count is 0
Row Count is 0 SELECT * FROM person WHERE first_name = 'NotHere';

Verify Row Count is Equal to X
Row Count is Equal to X SELECT id FROM person; 2

Verify Row Count is Less Than X
Row Count is Less Than X SELECT id FROM person; 3

Verify Row Count is Greater Than X
Row Count is Greater Than X SELECT * FROM person; 1

Retrieve Row Count
${output} = Row Count SELECT id FROM person;
Log ${output}
Should Be Equal As Strings ${output} 2

Retrieve records from person table
${output} = Execute SQL String SELECT * FROM person;
Log ${output}
Should Be Equal As Strings ${output} None

Verify person Description
[Tags] db smoke
Comment Query db for table column descriptions
@{queryResults} = Description SELECT * FROM person LIMIT 1;
Log Many @{queryResults}
${output} = Set Variable ${queryResults[0]}
Should Be Equal As Strings ${output} Column(name='id', type_code=23, display_size=None, internal_size=4, precision=None, scale=None, null_ok=None)
${output} = Set Variable ${queryResults[1]}
Should Be Equal As Strings ${output} Column(name='first_name', type_code=1043, display_size=None, internal_size=-1, precision=None, scale=None, null_ok=None)
${output} = Set Variable ${queryResults[2]}
Should Be Equal As Strings ${output} Column(name='last_name', type_code=1043, display_size=None, internal_size=-1, precision=None, scale=None, null_ok=None)
${NumColumns} = Get Length ${queryResults}
Should Be Equal As Integers ${NumColumns} 3

Verify foobar Description
[Tags] db smoke
Comment Query db for table column descriptions
@{queryResults} = Description SELECT * FROM foobar LIMIT 1;
Log Many @{queryResults}
${output} = Set Variable ${queryResults[0]}
Should Be Equal As Strings ${output} Column(name='id', type_code=23, display_size=None, internal_size=4, precision=None, scale=None, null_ok=None)
${output} = Set Variable ${queryResults[1]}
Should Be Equal As Strings ${output} Column(name='firstname', type_code=1043, display_size=None, internal_size=-1, precision=None, scale=None, null_ok=None)
${NumColumns} = Get Length ${queryResults}
Should Be Equal As Integers ${NumColumns} 2

Verify Query - Row Count person table
${output} = Query SELECT COUNT(*) FROM person;
Log ${output}
${val}= Get from list ${output} 0
${val}= Convert to list ${val}
${val}= Get from list ${val} 0
Should be equal as Integers ${val} 2

Verify Query - Row Count foobar table
${output} = Query SELECT COUNT(*) FROM foobar;
Log ${output}
${val}= Get from list ${output} 0
${val}= Convert to list ${val}
${val}= Get from list ${val} 0
Should be equal as Integers ${val} 0

Verify Query - Get results as a list of dictionaries
[Tags] db smoke
${output} = Query SELECT * FROM person; \ True
Log ${output}
Should Be Equal As Strings &{output[0]}[first_name] Franz Allan
Should Be Equal As Strings &{output[1]}[first_name] Jerry

Verify Execute SQL String - Row Count person table
${output} = Execute SQL String SELECT COUNT(*) FROM person;
Log ${output}
Should Be Equal As Strings ${output} None

Verify Execute SQL String - Row Count foobar table
${output} = Execute SQL String SELECT COUNT(*) FROM foobar;
Log ${output}
Should Be Equal As Strings ${output} None

Insert Data Into Table foobar
${output} = Execute SQL String INSERT INTO foobar VALUES(1,'Jerry');
Log ${output}
Should Be Equal As Strings ${output} None

Verify Query - Row Count foobar table 1 row
${output} = Query SELECT COUNT(*) FROM foobar;
Log ${output}
${val}= Get from list ${output} 0
${val}= Convert to list ${val}
${val}= Get from list ${val} 0
Should be equal as Integers ${val} 1

Verify Delete All Rows From Table - foobar
Delete All Rows From Table foobar
Comment Sleep 2s

Verify Query - Row Count foobar table 0 row
Row Count Is 0 SELECT * FROM foobar;
Comment ${output} = Query SELECT COUNT(*) FROM foobar;
Comment Log ${output}
Comment Should Be Equal As Strings ${output} [(0,)]

Drop person and foobar tables
${output} = Execute SQL String DROP TABLE IF EXISTS person,foobar;
Log ${output}
Should Be Equal As Strings ${output} None
- + \ No newline at end of file diff --git a/docs/different_libraries/how_to_find_library.html b/docs/different_libraries/how_to_find_library.html index e9a47980..55907d04 100644 --- a/docs/different_libraries/how_to_find_library.html +++ b/docs/different_libraries/how_to_find_library.html @@ -5,7 +5,7 @@ How to find the right library | ROBOT FRAMEWORK - + @@ -15,7 +15,7 @@ But nothing beats a library which can steer your application natively via it's exposed interfaces.

Web Applications

Libraries steering the UI of a Web Application in a Web Browser

There are two main libraries which can automate web applications in a web browser:

Libraries that can automate Web Services and RESTful APIs

Desktop Applications

Does if offer a User Interface ?

Automation via the User Interface is a common approach, even though it can be very unstable, slow and heavy on the maintenance.
But if your Application offers a User Interface, there is also the possibility to automate it via that User Interface.
That's where the used technology becomes important.

General Windows Desktop UI Libraries

There are libraries out there for general windows desktop automation or image based automation.

But if you know that it's wiritten in Java - check out some SWING or SWT Libraries!

Java Specific UI Libraries

Some Libraries to steer the User Interface of your Java Application

- + \ No newline at end of file diff --git a/docs/different_libraries/overview.html b/docs/different_libraries/overview.html index c04745de..c54689a2 100644 --- a/docs/different_libraries/overview.html +++ b/docs/different_libraries/overview.html @@ -5,13 +5,13 @@ Library Overview | ROBOT FRAMEWORK - + - + \ No newline at end of file diff --git a/docs/different_libraries/requests.html b/docs/different_libraries/requests.html index 87929654..8621538f 100644 --- a/docs/different_libraries/requests.html +++ b/docs/different_libraries/requests.html @@ -5,14 +5,14 @@ Requests Library | ROBOT FRAMEWORK - +

Requests Library

🏠 RequestsLibrary is a Robot Framework library aimed to provide HTTP api testing functionalities by wrapping the well known Python Requests Library.

See Keyword Documentation for available keywords and more information about the library in general.

Install stable version

pip install robotframework-requests

🤖 Quick start

*** Settings ***
Library RequestsLibrary

*** Test Cases ***

Quick Get Request Test
${response}= GET https://www.google.com

Quick Get Request With Parameters Test
${response}= GET https://www.google.com/search params=query=ciao expected_status=200

Quick Get A JSON Body Test
${response}= GET https://jsonplaceholder.typicode.com/posts/1
Should Be Equal As Strings 1 ${response.json()}[id]

See examples for Restful Booker

- + \ No newline at end of file diff --git a/docs/different_libraries/rpa.html b/docs/different_libraries/rpa.html index 045522f1..f47e6284 100644 --- a/docs/different_libraries/rpa.html +++ b/docs/different_libraries/rpa.html @@ -5,7 +5,7 @@ RPA Framework | ROBOT FRAMEWORK - + @@ -14,7 +14,7 @@ Robotic Process Automation (RPA), and it is designed to be used with both Robot Framework and Python. The goal is to offer well-documented and actively maintained core libraries for Software Robot Developers.

Learn more about RPA at Robocorp Documentation.

The project is:

- + \ No newline at end of file diff --git a/docs/different_libraries/selenium.html b/docs/different_libraries/selenium.html index d344bd18..3441ca36 100644 --- a/docs/different_libraries/selenium.html +++ b/docs/different_libraries/selenium.html @@ -5,13 +5,13 @@ Selenium Library | ROBOT FRAMEWORK - +
-

Selenium Library

SeleniumLibrary is a web testing library for Robot Framework that utilizes the Selenium tool internally. The project is hosted on GitHub and downloads can be found from PyPI.

See Keyword Documentation for available keywords and more information about the library in general.

Installation instructions

pip install --upgrade robotframework-seleniumlibrary

Afterwards you can import the library into your test case or resource file.

*** Settings ***
Library SeleniumLibrary

*** Test Cases ***
Login with correct Username and Password
Open Browser url=https://the-internet.herokuapp.com/login browser=chrome
Input Text username tomsmith
Input Text password SuperSecretPassword!
Click Button class:radius
Element Should Contain id=flash You logged into a secure area!
Click Link Logout
Close Browser

Add Tasks And Set To Complete
Open Browser url=https://todomvc.com/examples/angularjs/#/ browser=chrome
Input Text class:new-todo Complete Robot Framework Training
Press Keys class:new-todo RETURN
Input Text class:new-todo Write Automated Tests
Press Keys class:new-todo RETURN
Input Text class:new-todo Take a nap
Press Keys class:new-todo RETURN
Element Text Should Be class:todo-count 3 items left
Click Element xpath: //*[contains(text(), "Complete Robot Framework Training")]/../input
Element Text Should Be class:todo-count 2 items left
Click Element xpath: //*[contains(text(), "Write Automated Tests")]/../input
Element Text Should Be class:todo-count 1 item left
Click Element xpath: //*[contains(text(), "Take a nap")]/../input
Element Text Should Be class:todo-count 0 items left
- +

Selenium Library

SeleniumLibrary is a web testing library for Robot Framework that utilizes the Selenium tool internally. The project is hosted on GitHub and downloads can be found from PyPI.

See Keyword Documentation for available keywords and more information about the library in general.

Installation instructions

pip install --upgrade robotframework-seleniumlibrary

Afterwards you can import the library into your test case or resource file.

*** Settings ***
Library SeleniumLibrary

*** Test Cases ***
Login with correct Username and Password
Open Browser url=https://the-internet.herokuapp.com/login browser=chrome
Input Text username tomsmith
Input Text password SuperSecretPassword!
Click Button class:radius
Element Should Contain id=flash You logged into a secure area!
Click Link Logout
Close Browser

Add Tasks And Set To Complete
Open Browser url=https://todomvc.com/examples/angular/dist/browser/# browser=chrome
Input Text css:.new-todo Complete Robot Framework Training
Press Keys css:.new-todo RETURN
Input Text css:.new-todo Write Automated Tests
Press Keys css:.new-todo RETURN
Input Text css:.new-todo Take a nap
Press Keys css:.new-todo RETURN
Element Text Should Be class:todo-count 3 items left
Click Element xpath: //*[contains(text(), "Complete Robot Framework Training")]/../input
Element Text Should Be class:todo-count 2 items left
Click Element xpath: //*[contains(text(), "Write Automated Tests")]/../input
Element Text Should Be class:todo-count 1 item left
Click Element xpath: //*[contains(text(), "Take a nap")]/../input
Element Text Should Be class:todo-count 0 items left
+ \ No newline at end of file diff --git a/docs/different_libraries/standard.html b/docs/different_libraries/standard.html index 95411cf5..d0450bb7 100644 --- a/docs/different_libraries/standard.html +++ b/docs/different_libraries/standard.html @@ -5,7 +5,7 @@ Standard Library | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@

Standard Library

The Libraries which are part of the Standard Library are distributed with Robot Framework Core.
The BuiltIn library is the most important library of the Standard Library and is available by default.
Other libraries are available by importing them.

Importing Libraries

*** Settings ***
Library Collections
Library OperatingSystem
Library Process
Library String
Library Telnet
Library XML

Examples

BuiltIn Library

Collections Library

DateTime

XML Library

Robot Framework 5 Syntax Examples

- + \ No newline at end of file diff --git a/docs/examples/insurance.html b/docs/examples/insurance.html index 22a4fa9b..ad554ca7 100644 --- a/docs/examples/insurance.html +++ b/docs/examples/insurance.html @@ -5,14 +5,14 @@ Vehicle Insurance App | ROBOT FRAMEWORK - +

Vehicle Insurance App

Webpage: http://sampleapp.tricentis.com/
Technology: Web Application

Insurance Calculator

Download the example from here.

*** Settings ***
Library Browser

*** Variables ***
${BROWSER} chromium
${HEADLESS} false

*** Test Cases ***
Create Quote for Car
Open Insurance Application
Enter Vehicle Data for Automobile
Enter Insurant Data
Enter Product Data
Select Price Option
Send Quote
End Test

*** Keywords ***
Open Insurance Application
New Browser browser=${BROWSER} headless=${HEADLESS}
New Context locale=en-GB
New Page http://sampleapp.tricentis.com/

Enter Vehicle Data for Automobile
Click div.main-navigation >> "Automobile"
Select Options By id=make text Audi
Fill Text id=engineperformance 110
Fill Text id=dateofmanufacture 06/12/1980
Select Options By id=numberofseats text 5
Select Options By id=fuel text Petrol
Fill Text id=listprice 30000
Fill Text id=licenseplatenumber DMK1234
Fill Text id=annualmileage 10000
Click section[style="display: block;"] >> text=Next »

Enter Insurant Data
[Arguments] ${firstname}=Max ${lastname}=Mustermann
Fill Text id=firstname Max
Fill Text id=lastname Mustermann
Fill Text id=birthdate 01/31/1980
Check Checkbox *css=label >> id=gendermale
Fill Text id=streetaddress Test Street
Select Options By id=country text Germany
Fill Text id=zipcode 40123
Fill Text id=city Essen
Select Options By id=occupation text Employee
Click text=Cliff Diving
Click section[style="display: block;"] >> text=Next »

Enter Product Data
Fill Text id=startdate 06/01/2023
Select Options By id=insurancesum text 7.000.000,00
Select Options By id=meritrating text Bonus 1
Select Options By id=damageinsurance text No Coverage
Check Checkbox *css=label >> id=EuroProtection
Select Options By id=courtesycar text Yes
Click section[style="display: block;"] >> text=Next »

Select Price Option
[Arguments] ${price_option}=Silver
Click *css=label >> css=[value=${price_option}]
Click section[style="display: block;"] >> text=Next »

Send Quote
Fill Text "E-Mail" >> .. >> input max.mustermann@example.com
Fill Text "Phone" >> .. >> input 0049201123456
Fill Text "Username" >> .. >> input max.mustermann
Fill Text "Password" >> .. >> input SecretPassword123!
Fill Text "Confirm Password" >> .. >> input SecretPassword123!
Fill Text "Comments" >> .. >> textarea Some comments
${promise}= Promise To Wait For Response matcher=http://sampleapp.tricentis.com/101/tcpdf/pdfs/quote.php timeout=10
Click "« Send »"
${body}= Wait For ${promise}
Log ${body}[status]
Log ${body}[body]
Wait For Elements State "Sending e-mail success!"
Click "OK"

End Test
Close Context
Close Browser
- + \ No newline at end of file diff --git a/docs/examples/mfa_login.html b/docs/examples/mfa_login.html index 8c10b433..d671a9bf 100644 --- a/docs/examples/mfa_login.html +++ b/docs/examples/mfa_login.html @@ -5,14 +5,14 @@ Login with Multi Factor Authentication | ROBOT FRAMEWORK - +

Login with Multi Factor Authentication

Webpage: https://seleniumbase.io/realworld/login
Technology: Web Application, MFA , TOTP

MFA loginMFA TOTP

Download the .robot example from here and the totp.py file from here.

*** Settings ***
Library Browser
Library totp.py
Suite Setup New Browser browser=${BROWSER} headless=${HEADLESS}
Test Setup New Context
Test Teardown Close Context
Suite Teardown Close Browser

*** Variables ***
${BROWSER} chromium
${HEADLESS} False

*** Test Cases ***
Login with MFA
New Page https://seleniumbase.io/realworld/login
Fill Text id=username demo_user
Fill Text id=password secret_pass
${totp} Get Totp GAXG2MTEOR3DMMDG
Fill Text id=totpcode ${totp}
Click "Sign in"
Get Text h1 == Welcome!
- + \ No newline at end of file diff --git a/docs/examples/overview.html b/docs/examples/overview.html index 77f846c6..5faff349 100644 --- a/docs/examples/overview.html +++ b/docs/examples/overview.html @@ -5,13 +5,13 @@ Examples Overview | ROBOT FRAMEWORK - + - + \ No newline at end of file diff --git a/docs/examples/project_structure.html b/docs/examples/project_structure.html index 2923be85..330b2119 100644 --- a/docs/examples/project_structure.html +++ b/docs/examples/project_structure.html @@ -5,7 +5,7 @@ Project Structure | ROBOT FRAMEWORK - + @@ -32,7 +32,7 @@ Because of that, it is recommended to use the --pythonpath command line argument instead of absolute paths.


Using --pythonpath command line argument and resources/ subfolder

Let's assume we have the following project structure:

my_project
├── tests
│ └── suiteA.robot
└── resources
└── general.resource

The tests/suiteA.robot file looks like this:

*** Settings ***
Resource resources/general.resource
...

To run the tests, we need to tell Robot Framework where to search for the libraries, resource and variable files. If we run it without any arguments, we will get an error:

$ robot tests/suiteA.robot
[Error] Error in file 'tests/suiteA.robot': ...
Resource file 'resources/general.resource' does not exist.
...

We can add the project root folder my_project/ folder to the --pythonpath command line argument:

$ robot --pythonpath . tests/suiteA.robot

Now the tests run successfully.

tip

You can also add the resources/ , lib/ or keyword/ folders to the --pythonpath setting:

$ robot --pythonpath .:./lib:./resources:./keywords tests/suiteA.robot

That way, you can import libraries, resources and variables from the resources/, lib/ and keyword/ folders without the resources/, lib/ or keyword/ prefix.

*** Settings ***
Resource general.resource
Resource auth/login.resource
Library auth/totp.py
...

Using PYTHONPATH environment variable

Alternatively, you can add the path to your project root folder to the PYTHONPATH environment variable.
Then you can run the tests without the --pythonpath command line argument (assuming you are in the project root folder my_project):

Bash

$ export PYTHONPATH=$PYTHONPATH:.
$ robot tests/suiteA.robot

PowerShell

> $env:PYTHONPATH += ";."
> robot tests/suiteA.robot
- + \ No newline at end of file diff --git a/docs/examples/restfulbooker.html b/docs/examples/restfulbooker.html index d41610e9..cb04252c 100644 --- a/docs/examples/restfulbooker.html +++ b/docs/examples/restfulbooker.html @@ -5,7 +5,7 @@ Restful Booker | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@

Restful Booker

Webpage: https://restful-booker.herokuapp.com/
GitHub: https://github.com/mwinteringham/restful-booker
Technology: Restful API, Web Service

Download the example from here.

*** Settings ***
Library RequestsLibrary
Library Collections
Suite Setup Authenticate as Admin

*** Test Cases ***
Get Bookings from Restful Booker
${body} Create Dictionary firstname=John
${response} GET https://restful-booker.herokuapp.com/booking ${body}
Status Should Be 200
Log List ${response.json()}
FOR ${booking} IN @{response.json()}
${response} GET https://restful-booker.herokuapp.com/booking/${booking}[bookingid]
TRY
Log ${response.json()}
EXCEPT
Log Cannot retrieve JSON due to invalid data
END
END

Create a Booking at Restful Booker
${booking_dates} Create Dictionary checkin=2022-12-31 checkout=2023-01-01
${body} Create Dictionary firstname=Hans lastname=Gruber totalprice=200 depositpaid=false bookingdates=${booking_dates}
${response} POST url=https://restful-booker.herokuapp.com/booking json=${body}
${id} Set Variable ${response.json()}[bookingid]
Set Suite Variable ${id}
${response} GET https://restful-booker.herokuapp.com/booking/${id}
Log ${response.json()}
Should Be Equal ${response.json()}[lastname] Gruber
Should Be Equal ${response.json()}[firstname] Hans
Should Be Equal As Numbers ${response.json()}[totalprice] 200
Dictionary Should Contain Value ${response.json()} Gruber

Delete Booking
${header} Create Dictionary Cookie=token\=${token}
${response} DELETE url=https://restful-booker.herokuapp.com/booking/${id} headers=${header}
Status Should Be 201 ${response}

*** Keywords ***
Authenticate as Admin
${body} Create Dictionary username=admin password=password123
${response} POST url=https://restful-booker.herokuapp.com/auth json=${body}
Log ${response.json()}
${token} Set Variable ${response.json()}[token]
Log ${token}
Set Suite Variable ${token}
- + \ No newline at end of file diff --git a/docs/examples/todo.html b/docs/examples/todo.html index 72bea769..2348d70a 100644 --- a/docs/examples/todo.html +++ b/docs/examples/todo.html @@ -5,7 +5,7 @@ TodoMVC | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@

TodoMVC

Webpage: https://todomvc.com/
GitHub: https://github.com/tastejs/todomvc
Technology: Web Application

TodoMVC

Download the example from here.

*** Settings ***
Library Browser
Library String
Suite Setup New Browser browser=${BROWSER} headless=${HEADLESS}
Test Setup New Context viewport={'width': 1920, 'height': 1080}
Test Teardown Close Context
Suite Teardown Close Browser

*** Variables ***
${BROWSER} chromium
${HEADLESS} False

*** Test Cases ***
Add Two ToDos And Check Items
[Documentation] Checks if ToDos can be added and ToDo count increases
[Tags] Add ToDo
Given ToDo App is open
When I Add A New ToDo "Learn Robot Framework"
And I Add A New ToDo "Write Test Cases"
Then Open ToDos should show "2 items left"

Add Two ToDos And Check Wrong Number Of Items
[Documentation] Checks if ToDos can be added and ToDo count increases
[Tags] Add ToDo
Given ToDo App is open
When I Add A New ToDo "Learn Robot Framework"
And I Add A New ToDo "Write Test Cases"
Then Open ToDos should show "1 items left"

Add ToDo And Mark Same ToDo
[Tags] Mark ToDo
Given ToDo App is open
When I Add A New ToDo "Learn Robot Framework"
And I Mark ToDo "Learn Robot Framework"
Then Open ToDos should show "0 items left"

Check If Marked ToDos are removed
Given ToDo App is open
And I Added Two ToDos
When I Mark One ToDo
Then Open ToDos should show "1 item left"

Split ToDos
Given ToDo App is open
When I Add New ToDos "Learn Robot Framework&Write Test Cases&Sleep"
Then Open ToDos should show "3 items left"

Add A Lot Of Todos
Given ToDo App is open
When I Add "100" ToDos
Then Open ToDos should show "100 items left"

Add A Lot Of Todos With WHILE
Given ToDo App is open
When I Add "100" ToDos With WHILE Loop
Then Open ToDos should show "100 items left"

*** Keywords ***
ToDo App is open
New Page https://todomvc.com/examples/react/

I Add A New ToDo "${todo}"
Fill Text .new-todo ${todo}
Press Keys .new-todo Enter

I Add New ToDos "${todo}"
IF "&" in $todo
@{todos} Split String ${todo} separator=&
FOR ${item} IN @{todos}
Fill Text .new-todo ${item}
Press Keys .new-todo Enter
END
ELSE
Fill Text .new-todo ${todo}
Press Keys .new-todo Enter
END

Open ToDos should show "${text}"
Get Text span.todo-count == ${text}

I Mark ToDo "${todo}"
Click "${todo}" >> .. >> input.toggle

I Added Two ToDos
I Add A New ToDo "Learn Robot Framework"
I Add A New ToDo "Write Test Cases"

I Mark One ToDo
Click li:first-child >> input.toggle

I Add "${count}" ToDos
FOR ${index} IN RANGE ${count}
I Add A New ToDo "My ToDo Number ${index}"
END

I Add "${count}" ToDos With WHILE Loop
${x}= Set Variable ${0}
WHILE ${x} < ${count}
${x}= Evaluate ${x} + 1
I Add A New ToDo "My ToDo Number ${x}"
END

- + \ No newline at end of file diff --git a/docs/extending_robot_framework/custom-libraries/non-python_library.html b/docs/extending_robot_framework/custom-libraries/non-python_library.html index fe3b0a44..c1329057 100644 --- a/docs/extending_robot_framework/custom-libraries/non-python_library.html +++ b/docs/extending_robot_framework/custom-libraries/non-python_library.html @@ -5,13 +5,13 @@ Non-Python Libraries | ROBOT FRAMEWORK - +

Non-Python Libraries

Rust

Create a dynamic system library (crate_type = "cdylib") from the following source code.

#![allow(non_snake_case)]

use std::collections::HashMap;

use pyo3::prelude::*;

#[pyfunction]
fn sum_as_string(a: i32, b: i32) -> PyResult<String> {
Ok((a + b).to_string())
}

#[pyfunction]
fn join_strings(a: Vec<String>) -> PyResult<String> {
Ok(a.join(","))
}

#[pyfunction]
fn sum_values(a: HashMap<String, i32>) -> PyResult<i32> {
let mut values_sum = 0;
for (_key, value) in &a {
values_sum += value;
}
Ok(values_sum)
}

#[pymodule]
fn RustyLibrary(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
m.add_function(wrap_pyfunction!(join_strings, m)?)?;
m.add_function(wrap_pyfunction!(sum_values, m)?)?;
Ok(())
}

The library can then be used as follows.

*** Settings ***
Library RustyLibrary

*** Test Cases ***
Integer Argument Conversion Test
${x} = Sum As String ${5} ${20}
Should Be Equal ${x} 25

List Argument Conversion Test
@{MY_LIST} = Create List spam eggs

${y} = Join Strings ${MY_LIST}
Should Be Equal ${y} spam,eggs

Dictionary Argument Conversion Test
&{MY_DICT} = Create Dictionary spam ${11} eggs ${22}

${z} = Sum Values ${MY_DICT}
Should Be Equal ${z} ${33}

A complete working example that includes all build files (e.g. Cargo.toml) can be found on GitHub / mneiferbag / robot-python-test-library.

- + \ No newline at end of file diff --git a/docs/extending_robot_framework/custom-libraries/python_library.html b/docs/extending_robot_framework/custom-libraries/python_library.html index 07c7e719..5935dde2 100644 --- a/docs/extending_robot_framework/custom-libraries/python_library.html +++ b/docs/extending_robot_framework/custom-libraries/python_library.html @@ -5,13 +5,13 @@ Python Libraries | ROBOT FRAMEWORK - +

Python Libraries

Talk Creating Libraries - Why and How from RoboCon 2021

Static Library

A static library has all of its robot framework keywords defined as python functions.

Static Library With a Class

class DemoLibrary:
def __init__(self, *args, **kwargs):
print(f"Sample Library initialized with args: {args} and kwargs: {kwargs}")

def my_keyword(self, *args, **kwargs):
print(f"Keyword got args: {args} and kwargs: {kwargs}")
return "Hello World"
*** Settings ***
Library DemoLibrary.py

*** Test Cases ***
Use a Keyword with multiple arguments
My Keyword Argument 1 Argument 2 Named Argument=One Value

Static Library withouth a Class

import base64

def encode_as_base64(string):
"""
Encode string as base64.
"""
return base64.b64encode(string.encode())

def decode_from_base64(string):
"""
Decode string from base64.
"""
return base64.b64decode(string).decode()
*** Settings ***
Library LibraryWithoutClass.py

*** Test Cases ***
Use Custom Keywords
${base64} Encode As Base64 This is a Test String
Log ${base64}
${decoded} Decode From Base64 ${base64}
Log ${decoded}

Decorators

You can add decorators like @keyword @not_keyword to mark your functions as keywords and e.g. provide another name for the keyword.

from robot.api.deco import keyword, not_keyword


@keyword('Login via user panel')
def login(username, password):
# ...

@not_keyword
def this_is_not_keyword():
pass

It can even be used to add tags or change the argument conversion.

from robot.api.deco import keyword


@keyword(tags=['tag1', 'tag2'])
def login(username, password):
# ...

@keyword('Custom name', ['tags', 'here'])
def another_example():
# ...

@keyword(types={'count': int, 'case_insensitive': bool})
def example_keyword(count, case_insensitive=True):
if case_insensitive:
# ...

@keyword(types=[int, bool])
def example_keyword(count, case_insensitive=True):
if case_insensitive:
# ...

A simple Calculate.py library with a single keyword that calculates a mathematical expression.

def calculate(term):
if term == "":
return 0
else:
return eval(term)
*** Settings ***
Library Calculate.py

*** Test Cases ***
Perform Calculations
${result} Calculate 1 + 2
Should Be Equal As Numbers ${result} 3
${result} Calculate 10 * 5
Should Be Equal As Numbers ${result} 50
${result} Calculate 8 / 4
Should Be Equal As Numbers ${result} 2
${result} Calculate 2 - 1
Should Be Equal As Numbers ${result} 1

Examples

- + \ No newline at end of file diff --git a/docs/extending_robot_framework/custom-libraries/releasing_your_own_libraries.html b/docs/extending_robot_framework/custom-libraries/releasing_your_own_libraries.html index 25070398..545d2bca 100644 --- a/docs/extending_robot_framework/custom-libraries/releasing_your_own_libraries.html +++ b/docs/extending_robot_framework/custom-libraries/releasing_your_own_libraries.html @@ -5,13 +5,13 @@ Package and Release Your Own Libraries | ROBOT FRAMEWORK - +

Package and Release Your Own Libraries

Check out the Robot Framework User Guide for more information.

Creating Python Keywords and Libraries

Talk Creating Libraries - Why and How from RoboCon 2021

Releasing your own Library

Talk “For the very first time” - Start to Code, Test, Package & Publish your first Library from RoboCon 2022

Using Poetry to manage your dependencies and publishing

Talk Project and package management: Poetry for robots from RoboCon 2022

- + \ No newline at end of file diff --git a/docs/extending_robot_framework/listeners_prerun_api/listeners.html b/docs/extending_robot_framework/listeners_prerun_api/listeners.html index 4d8cec91..421c0979 100644 --- a/docs/extending_robot_framework/listeners_prerun_api/listeners.html +++ b/docs/extending_robot_framework/listeners_prerun_api/listeners.html @@ -5,7 +5,7 @@ Listener Interface | ROBOT FRAMEWORK - + @@ -18,7 +18,7 @@ Just copy the code and paste it into a new file.
Add your own code to the methods you want to use.
Remove the methods you don't need.

Listener Template v2
RobotListenerV2.py
from robot.libraries.BuiltIn import BuiltIn

b = BuiltIn()

class RobotListenerV2:

ROBOT_LISTENER_API_VERSION = 2
ROBOT_LIBRARY_SCOPE = "GLOBAL"

def __init__(self):
self.ROBOT_LIBRARY_LISTENER = self
pass

def start_suite(self, name, attrs):
print(name)
print(attrs)
pass

def start_test(self, name, attrs):
print(name)
print(attrs)
pass

def start_keyword(self, name, attrs):
print(name)
print(attrs)
pass

def end_keyword(self, name, attrs):
print(name)
print(attrs)
pass

def end_test(self, name, attrs):
print(name)
print(attrs)
pass

def end_suite(self, name, attrs):
print(name)
print(attrs)
pass

def log_message(self, message):
print(message)
pass

def message(self, message):
print(message)

pass

def library_import(self, name, attrs):
print(name)
print(attrs)
pass

def resource_import(self, name, attrs):
print(name)
print(attrs)
pass

def variables_import(self, name, attrs):
print(name)
print(attrs)
pass

def output_file(self, path):
print(path)
pass

def log_file(self, path):
print(path)
pass

def report_file(self, path):
print(path)
pass

def xunit_file(self, path):
print(path)
pass

def debug_file(self, path):
print(path)
pass

def close(self):
pass
Listener Template v3
RobotListenerV3.py
from robot.libraries.BuiltIn import BuiltIn


class RobotListenerV3:

ROBOT_LIBRARY_SCOPE = "GLOBAL"
ROBOT_LISTENER_API_VERSION = 3

def __init__(self):
pass

def start_suite(self, suite, result):
pass

def start_test(self, test, result):
pass

def end_test(self, test, result):
pass

def end_suite(self, suite, result):
pass

def log_message(self, message):
pass

def message(self, message):
pass

def debug_file(self, path):
pass

def output_file(self, path):
pass

def xunit_file(self, path):
pass

def log_file(self, path):
pass

def report_file(self, path):
pass

def close(self):
pass

Example Listeners

Stop on Failure Listener

A Listener which stops the execution of the test suite if a test fails.

listener.py
"""Listener that stops execution if a test fails."""

ROBOT_LISTENER_API_VERSION = 3

def end_test(data, result):
if not result.passed:
print('Test "%s" failed: %s' % (result.name, result.message))
input('Press enter to continue.')

Report Listener

A Listener which writes the name and status of each test to a file.

ReportListener.py
class ReportListener:
ROBOT_LISTENER_API_VERSION = 3

def __init__(self, filename='report.md'):
self.filename = filename
self.fh = open(self.filename, 'w')
self.fh.write("# Robot Framework Report\n")
self.fh.write("|Test|Status|\n")
self.fh.write("|---|---|\n")

def close(self):
self.fh.close()

def end_test(self, data, result):
self.fh.write(f"|{result.name}|{result.status}|\n")
robot --listener ReportListener.py tests
- + \ No newline at end of file diff --git a/docs/extending_robot_framework/listeners_prerun_api/overview.html b/docs/extending_robot_framework/listeners_prerun_api/overview.html index 714c3289..9e451b98 100644 --- a/docs/extending_robot_framework/listeners_prerun_api/overview.html +++ b/docs/extending_robot_framework/listeners_prerun_api/overview.html @@ -5,7 +5,7 @@ Overview | ROBOT FRAMEWORK - + @@ -14,7 +14,7 @@ Listeners can be enabled by using the --listener option when running the test suite.

Example events on which the listener can react on are:

  • start/end of a test suite
  • start/end of a test case
  • start/end of a keyword
  • ...

Check out the Listener Chapter for more information.

PreRunModifier

A PreRunModifier can modify the test suite before it is actually executed.
It is like a "dry run" of the test suite with the possibility to modify the test suite before the actual execution. It can be enabled by using the --prerunmodifier option when running the test suite.

Check out the PreRunModifier Chapter for more information.

Robot Framework API

The Robot Framework API allows us to

  • Run commands like robot and rebot from Python scripts
  • Access and modify all kinds of Robot Framework objects before, during and after the execution of the test suite

Check out the Robot Framework API Chapter for more information.

- + \ No newline at end of file diff --git a/docs/extending_robot_framework/listeners_prerun_api/prerunmodifier.html b/docs/extending_robot_framework/listeners_prerun_api/prerunmodifier.html index 20d3f833..774f0f7d 100644 --- a/docs/extending_robot_framework/listeners_prerun_api/prerunmodifier.html +++ b/docs/extending_robot_framework/listeners_prerun_api/prerunmodifier.html @@ -5,7 +5,7 @@ PreRunModifier | ROBOT FRAMEWORK - + @@ -21,7 +21,7 @@ 8: Copy the test and add it to the end of the test suite
9: Add the tag "copy" to the copied test
10: Modify the name of the copied test

robot --prerunmodifier CopyTest.py tests
- + \ No newline at end of file diff --git a/docs/extending_robot_framework/listeners_prerun_api/rf-api.html b/docs/extending_robot_framework/listeners_prerun_api/rf-api.html index 6e510d81..913dc805 100644 --- a/docs/extending_robot_framework/listeners_prerun_api/rf-api.html +++ b/docs/extending_robot_framework/listeners_prerun_api/rf-api.html @@ -5,14 +5,14 @@ Robot Framework API | ROBOT FRAMEWORK - +

Robot Framework API

What is the Robot Framework API?

The Robot Framework API allows us to do two main things.

  • Run commands like robot and rebot from Python scripts
  • Access and modify all kinds of Robot Framework objects , e.g.
    • Execution Results
    • Test Suites
    • Parsers
    • Logger
    • Result Writer
    • ...

Check out the Public API and Entry Points for more information.

You can use the API to build your own tools or integrate Robot Framework with other tools.
Examples are

  • Integrating Robot Framework with (Test Management) Tools like Jira or TestRail
  • Building your own Test Runner in Python
  • Create tools for analyzing and refactoring Robot Framework Tests (like robotidy or robocop)
  • Create UIs for Robot Framework
  • Create Tools to distribute Robot Framework Tests
  • Create Web Services for Robot Framework
  • ...

Use your imagination 🦄

Run Robot Framework from Python

Usually, we run Robot Framework from the command line.

robot tests.robot

We often pass some arguments to the command, like --variable or --outputdir.

robot --variable BROWSER:chrome --outputdir results tests.robot

But we can also run Robot Framework from Python scripts.

from robot import run

run('tests.robot', variable=['BROWSER:chrome'], outputdir='results')

The run function takes the same arguments as the robot command.

Check out the command-line options in the Robot Framework User Guide for more information.

The only difference when using the run function is

  • we don't need to prefix the arguments with --
    • e.g. --variable becomes variable
  • boolean arguments like --dryrun or --exitonfailure need to be set to True(or False)
    • e.g. --dryrun becomes dryrun=True
  • options which can be specified multiple times (like --variable) need to be passed as a list
    • e.g. --variable BROWSER:chrome --variable URL:https://www.google.com becomes variable=['BROWSER:chrome', 'URL:https://www.google.com']

If you prefer the command line syntax, you can use the robot.run_cli function.

from robot import run_cli

rc = run_cli(['--variable', 'BROWSER:chrome', '--outputdir', 'results', 'tests.robot'])

Access and Modify Robot Framework Objects

Execution Results

Access Execution Results after a Test Run

After a test run, we can access the execution results with the ExecutionResult object.

The ExecutionResult object is returned by the run function or can be created from an output.xml file.

The example below shows how to print the number of passed and failed tests.

from robot.api import ExecutionResult
result = ExecutionResult('output.xml')
stats = result.statistics
print(f"Number of Failed Tests: {stats.failed}")
print(f"Total number of Tests: {stats.passed}")
Write the test name and status to a markdown file

You can combine the ExecutionResult object with the ResultVisitor class to access the results in a structured way.

The ResultVisitor class will allow you to "walk" through the results and react to certain events (similar to the Listener)

The example below will visit all tests and write the test name and status to a markdown file.

report.py
from robot.api import ExecutionResult, ResultVisitor
import sys

class MyResultVisitor(ResultVisitor):
def __init__(self, markdown_file='report.md'):
self.failed_tests = []
self.passed_tests = []
self.markdown_file = markdown_file

def visit_test(self, test):
if test.status == 'FAIL':
self.failed_tests.append(test.name)
elif test.status == 'PASS':
self.passed_tests.append(test.name)

def end_result(self, result):
# Create a new markdown file
with open(self.markdown_file, "w") as f:
f.write("# Robot Framework Report\n")
f.write("|Test|Status|\n")
f.write("|---|---|\n")
for test in self.passed_tests:
f.write(f"|{test}|PASS|\n")
for test in self.failed_tests:
f.write(f"|{test}|FAIL|\n")

if __name__ == '__main__':
try:
output_file = sys.argv[1]
except IndexError:
output_file = "output.xml"
try:
markdown_file = sys.argv[2]
except IndexError:
markdown_file = "report.md"
result = ExecutionResult(output_file)
result.visit(MyResultVisitor())
python report.py output.xml report.md

That's how the result will look like:

Robot Framework Report
TestStatus
My First Test CasePASS
My Second Test Case As KeywordPASS
Some Other Test CasePASS
A Failed Test CaseFAIL

Access Execution Results returned by the run function

The run function returns an ExecutionResult object.

from robot import run

result = run('tests.robot', variable=['BROWSER:chrome'], outputdir='results')

print(result.suite.name)
stats = result.statistics
print(f"Number of Failed Tests: {stats.failed}")
print(f"Total number of Tests: {stats.passed}")
- + \ No newline at end of file diff --git a/docs/flaky_tests.html b/docs/flaky_tests.html index fb8b5d43..92458d3a 100644 --- a/docs/flaky_tests.html +++ b/docs/flaky_tests.html @@ -5,7 +5,7 @@ Re-Execute failed tests | ROBOT FRAMEWORK - + @@ -14,7 +14,7 @@ You can find the required steps in the Robot Framework User Guide

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

RetryFailed Listener

The RetryFailed Listener can automatically retry tests or tasks based on tags.

Installation

Install with pip:

pip install robotframework-retryfailed

Usage

Add the listener to your robot execution, via command line arguments. When your tests do fail and you have tagged them with test:retry(2), it will retry the test 2 times. Retry can be also set globally as a parameter to the listener.

Attaching Listener

Example:

robot --listener RetryFailed <your robot suite>

robot --listener RetryFailed:1 <robot suite>

Second one will by default retry once every failing test.

Tagging Tests

Example:

*** Test Cases ***
Test Case
[Tags] test:retry(2)
Log This test will be retried 2 times if it fails

Tagging tasks by task:retry(3) should also work.

Wait Until Keyword Succeeds

Runs the specified keyword and retries if it fails.

Check out the Wait Until Keyword Succeeds keyword in the Robot Framework BuiltIn library.

Example:

*** Test Cases ***
Test Case
Wait Until Keyword Succeeds 2 min 5 sec My keyword argument
${result} Wait Until Keyword Succeeds 3x 200ms My keyword
${result} Wait Until Keyword Succeeds 3x strict: 200ms My keyword
- + \ No newline at end of file diff --git a/docs/getting_started/ide.html b/docs/getting_started/ide.html index 678d2841..5e70fe32 100644 --- a/docs/getting_started/ide.html +++ b/docs/getting_started/ide.html @@ -5,7 +5,7 @@ Set up your IDE | ROBOT FRAMEWORK - + @@ -25,7 +25,7 @@ Debug Console

PyCharm with Robot Framework Language Server

Run

Run current test suite Run Tests

Run current test case (via selected text) Run Tests

Debug

Debug Tests

- + \ No newline at end of file diff --git a/docs/getting_started/rpa.html b/docs/getting_started/rpa.html index 8d36c0b0..a5ed90b6 100644 --- a/docs/getting_started/rpa.html +++ b/docs/getting_started/rpa.html @@ -5,7 +5,7 @@ I'm looking for RPA | ROBOT FRAMEWORK - + @@ -21,7 +21,7 @@ it means you are OK with getting whatever version you get 😉

All this validates a separate getting started brief and a difference in tooling. The actual logic of calling out APIs and interacting with browsers and applications is still the same as in test automation.

🚀 So by this point, you should have run your first bot, have an editor / IDE up-n-and running, and have an idea of the slight differences between RPA and test automation using Robot Framework. You are raring to go, so go ahead and check out the resources and libraries -part.

RPA resources to get started

For the resources and libraries part you can check out the following pages:

The main point to remember is that with Robot Framework and Python, there are just about no limits to what you can do. There are a ton of libraries out there, but you can also make your own.

We always recommend giving back to the open-source community, as you usually get more back than you put in.

For example: It is quite rare that the business value of an RPA process is in the library that interacts with an application or an API, so why not publish the connectivity part as open-source and get others to chip in on the maintenance and improvements? This way, you can focus more on the actual RPA problem.

- + \ No newline at end of file diff --git a/docs/getting_started/testing.html b/docs/getting_started/testing.html index 8fb29b9f..c4373f92 100644 --- a/docs/getting_started/testing.html +++ b/docs/getting_started/testing.html @@ -5,7 +5,7 @@ I'm looking for testing | ROBOT FRAMEWORK - + @@ -23,7 +23,7 @@ Either globally

pyenv global 3.10.6

Or locally (for the current folder only)

pyenv local 3.10.6

Create and activate a new Virtual Environment and install robotframework

python -m venv .venv
source .venv/bin/activate
pip install robotframework
robot --version

You should see something like

Robot Framework 5.x.y (Python 3.x.y)

The virtual environment can be deactivated by typing source .venv/bin/deactivate.

Install Robot Framework in Virtual Environment

Other Recommendations

Managing Dependencies with poetry

Poetry is a tool for dependency management and packaging in Python.

It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.
You can use it when you start any new project python or robotframework project.

Install poetry by following the official instructions.

Open PowerShell and run the following command:

(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -

💡If you have installed Python through the Microsoft Store, replace py with python in the command above.

Run poetry once to check if it's installed.

poetry --version

Virtual Environments folder

Poetry will save the virtual enviromentson in the .poetry/envs folder. You can change that setting and store your virtual environment in the project folder by running

poetry config virtualenvs.in-project true

Initialize a new project

To initialize a new project, run the following command in your terminal:

poetry init

Poetry will ask you some questions about your project. You can leave the default values by pressing Enter or enter your own values.

Example:

This command will guide you through creating your pyproject.toml config.

Package name [your-project-name]:
Version [0.1.0]:
Description []:
Author [Your Name <your.email@example.com>, n to skip]:
License []:
Compatible Python versions [^3.10]:

Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your development dependencies interactively? (yes/no) [yes] no

After the initialization, you will see a new file called pyproject.toml in your project folder. This file contains all the information about your project and the dependencies.

Add dependencies

To add a dependency, run the following command in your terminal:

poetry add robotframework

You can also add multiple dependencies at once:

poetry add robotframework robotframework-browser robotframework-requests

On the first run, poetry will create a virtual environment for your project and install the dependencies.

Run Commands in the Virtual Environment

To run commands in the virtual environment, you can use the poetry run command.

poetry run robot --version

To e.g. install the playwright dependencies for robotframework-browser, you can run the following command:

poetry run rfbrowser init

You can also use the poetry shell command to open a shell in the virtual environment.
All commands you run in this shell will be executed in the virtual environment.

poetry shell
(.venv) robot --version

Check out the official documentation for more information.

There is also a great Lightning Talk Project and package management: Poetry for robots from RoboCon 2022

- + \ No newline at end of file diff --git a/docs/getting_started/videos.html b/docs/getting_started/videos.html index f131f53f..49c35a32 100644 --- a/docs/getting_started/videos.html +++ b/docs/getting_started/videos.html @@ -5,14 +5,14 @@ Videos and Tutorials | ROBOT FRAMEWORK - +

Videos and Tutorials

Official Robot Framework Tutorial

The official Robot Framework tutorial video presented by the Robot Framework creator Pekka Klärck.
New videos will be added to this playlist in the future.

Official Robot Framework Tutorial


Robot Framework Tutorials

This channel is dedicated to those who want to start automating with Robot Framework but also to those who are already using this tool and want to find out new tips and tricks they might have missed.

Robot Framework Tutorials Channel


Complete Robot Framework Tutorial


Web Automation With Robot Framework


Mobile Automation With Robot Framework And Appium


Test Automation University

Test Automation University is a free, online learning platform for software testers and developers. It is a community-driven project that is supported by the community. The goal of Test Automation University is to provide free, high-quality, and up-to-date training for software testers and developers.

Introduction To Robot Framework

- + \ No newline at end of file diff --git a/docs/parallel.html b/docs/parallel.html index dca901c0..7c26dc21 100644 --- a/docs/parallel.html +++ b/docs/parallel.html @@ -5,7 +5,7 @@ Running tests in parallel | ROBOT FRAMEWORK - + @@ -45,7 +45,7 @@ be used for distributing testing to multiple machines.

--chunk Optionally chunk tests to PROCESSES number of robot runs. This can save time because all the suites will share the same setups and teardowns.

Example usages:

 pabot test_directory
pabot --exclude FOO directory_to_tests
pabot --command java -jar robotframework.jar --end-command --include SMOKE tests
pabot --processes 10 tests
pabot --pabotlibhost 192.168.1.123 --pabotlibport 8271 --processes 10 tests
pabot --pabotlib --pabotlibhost 192.168.1.111 --pabotlibport 8272 --processes 10 tests
pabot --artifacts png,mp4,txt --artifactsinsubfolders directory_to_tests

Examples

Multiple Test Suites in a tests/ directory

tests/SuiteA.robot
*** Test Cases ***
Test Case 1
Log Test Case 1
Sleep 10s

Test Case 2
Log Test Case 2
Sleep 10s

Test Case 3
Log Test Case 3
Sleep 10s
tests/SuiteB.robot
*** Test Cases ***
Test Case A
Log Test Case A
Sleep 10s

Test Case B
Log Test Case B
Sleep 10s

Test Case C
Log Test Case D
Sleep 10s
 pabot tests

Will run both suites in parallel, but will execute test cases sequentially.

 pabot --testlevelsplit tests

Will run both suites in parallel and will execute test cases in parallel.

If Test Suite Setups and Test Suite Teardowns are used, they will be executed for each instance of the suite.

tests/SuiteA.robot
*** Settings ***
Test Suite Setup Log Suite A Setup
Test Suite Teardown Log Suite A Teardown
Test Setup Log Test Setup
Test Teardown Log Test Teardown

*** Test Cases ***
Test Case 1
Log Test Case 1
Sleep 10s

Test Case 2
Log Test Case 2
Sleep 10s

Test Case 3
Log Test Case 3
Sleep 10s

When executed with the --testlevelsplit option, the Test Suite Setup and Test Suite Teardown will also be executed once for each parallel instance of the suite. The Test Setup and Test Teardown will be executed for each test case.

 pabot --testlevelsplit tests
- + \ No newline at end of file diff --git a/docs/parsing_results.html b/docs/parsing_results.html index 285e8723..0957b34e 100644 --- a/docs/parsing_results.html +++ b/docs/parsing_results.html @@ -5,7 +5,7 @@ Parsing Test Results | ROBOT FRAMEWORK - + @@ -15,7 +15,7 @@ Especially the ResultVisitor will allow you to access and modify your results at different points in time, e.g. when

  • a test suite starts/ends
  • a test case starts/ends
  • a keyword starts/ends
  • ...

Check the documentation for more possible entry points.
While visiting the results, you will have full access to the Robot Framework Model and its objects. You can easily read the status of a test or keyword, read its arguments or the elapsed execution time. Basically all data which is written into the output.xml can be accessed via the model.

Reading results using the RF API

Example which reads the execution time per test and sets the test status to failed, in case the execution took longer than a defined value max_seconds.

ExecutionTimeChecker.py

import sys
from robot.api import ExecutionResult, ResultVisitor


class ExecutionTimeChecker(ResultVisitor):

def __init__(self, max_seconds):
self.max_milliseconds = max_seconds * 1000

def visit_test(self, test):
if test.status == 'PASS' and test.elapsedtime > self.max_milliseconds:
test.status = 'FAIL'
test.message = 'Test execution took too long.'


def check_tests(seconds, inpath, outpath=None):
result = ExecutionResult(inpath)
result.visit(ExecutionTimeChecker(float(seconds)))
result.save(outpath)


if __name__ == '__main__':
try:
check_tests(*sys.argv[1:])
except TypeError:
print(__doc__)

You can run the script from the terminal as shown below:

python ExecutionTimeChecker.py 10 output.xml checked_output.xml

Getting result statistics

Simple example to read number of passed and failed tests

from robot.api import ExecutionResult
result = ExecutionResult('output.xml')
stats = result.statistics
print(f"Number of Failed Tests: {stats.failed}")
print(f"Total number of Tests: {stats.passed}")

You can also create a table in a markdown file report.mdwith the results.

from robot.api import ExecutionResult, ResultVisitor
import sys

class MyResultVisitor(ResultVisitor):
def __init__(self, markdown_file='report.md'):
self.failed_tests = []
self.passed_tests = []
self.markdown_file = markdown_file

def visit_test(self, test):
if test.status == 'FAIL':
self.failed_tests.append(test.name)
elif test.status == 'PASS':
self.passed_tests.append(test.name)

def end_result(self, result):
# Create a new markdown file
with open(self.markdown_file, "w") as f:
f.write("# Robot Framework Report\n")
f.write("|Test|Status|\n")
f.write("|---|---|\n")
for test in self.passed_tests:
f.write(f"|{test}|PASS|\n")
for test in self.failed_tests:
f.write(f"|{test}|FAIL|\n")

if __name__ == '__main__':
try:
output_file = sys.argv[1]
except IndexError:
output_file = "output.xml"
try:
markdown_file = sys.argv[2]
except IndexError:
markdown_file = "report.md"
result = ExecutionResult(output_file)
result.visit(MyResultVisitor())

That's how the result will look like:

Robot Framework Report

TestStatus
My First Test CasePASS
My Second Test Case As KeywordPASS
Some Other Test CasePASS
A Failed Test CaseFAIL

More information

Check the documentation

- + \ No newline at end of file diff --git a/docs/reporting_alternatives.html b/docs/reporting_alternatives.html index df5a018c..78d8ecf6 100644 --- a/docs/reporting_alternatives.html +++ b/docs/reporting_alternatives.html @@ -5,7 +5,7 @@ Reporting Test Results | ROBOT FRAMEWORK - + @@ -17,7 +17,7 @@ https://cognitiveqe.com/robot-framework-test-results-in-grafana-postgresql/

Example with Robot Framework DBbot, MySQL and Grafana
https://cognitiveqe.com/robot-framework-grafana-dashboard/

Blog post about Robot Framework, Jenkins Plugin, InfluxDB and Grafana https://www.eficode.com/blog/rf-jenkins-grafana

Robot Framework Metrics

Robot Framework Metrics creates custom HTML report (dashboard view) by parsing robotframework output.xml file

- + \ No newline at end of file diff --git a/docs/style_guide.html b/docs/style_guide.html index db454560..3327bad6 100644 --- a/docs/style_guide.html +++ b/docs/style_guide.html @@ -5,7 +5,7 @@ Style Guide | ROBOT FRAMEWORK - + @@ -53,7 +53,7 @@ Setting Test Variables should be reserved to test cases if at all possible. In either case document non-local scoped variables.


Special Cases

Variable Files

Assume variables declared within variable files to be at minimum SUITE in scope. (i.e. Always UPPER CASED, UPPER_CASED)

The examples given are using variables with spaces.

.resource Variable Files

Assume variables declared within the Variable section of a resource files to be at minimum SUITE in scope. (i.e. Always UPPER CASED, UPPER_CASED)

*** Variables ***
${STRING VARIABLE} Hello I am a resource variable.
${INT VARIABLE} ${42}
@{LIST VARIABLE} one two
&{DICT VARIABLE} one=yksi two=kaksi with spaces=kolme
Python Variable Files

Assume variables declared within python variable files to be at minimum SUITE in scope. (i.e. Always UPPER CASED, UPPER_CASED)

Note that syntactically you cannot declare python variables with a space, but when you use them in Robot Framework you can use a space.

Python libraries that declare variables are handled according to use case.

STRING_VARIABLE = "Hello I am a python variable."
INT_VARIABLE = 42
LIST_VARIABLE = ["one", "two"]
DICT_VARIABLE = {"one": "yksi", "two": "kaksi", "with spaces": "kolme"}
Yaml Variable Files

Assume variables declared within yaml variable files to be at minimum SUITE in scope. (i.e. Always UPPER CASED, UPPER_CASED)

When using a Yaml file you should follow Yaml Specifications for the key and value formatting.

As with python variables when you use them in Robot Framework you can use a space.

STRING VARIABLE: Hello I am a yaml variable.
INT VARIABLE: 42
LIST VARIABLE:
- one
- two
DICT VARIABLE:
one: yksi
two: kaksi
with spaces: kolme

Json Variable Files

Assume variables declared within json variable files to be at minimum SUITE in scope. (i.e. Always UPPER CASED, UPPER_CASED)

{
"STRING VARIABLE": "Hello I am a json variable.",
"INTEGER VARIABLE": 42,
"LIST VARIABLE": [
"one",
"two"
],
"DICT VARIABLE": {
"one": "yksi",
"two": "kaksi",
"with spaces": "kolme"
}
}

Commandline Variables

Commandline Variables and by extension variable files should be treated as Global Variables. (i.e. Always UPPER CASED, UPPER_CASED)

Environment Variables

https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#environment-variables

Environment Variables should be treated as Global Variables. (i.e. Always UPPER CASED, UPPER_CASED)

It is also possible that the variable casing needs to match how the variable has been declared outside of Robot Framework's context.

Deviation When Context Is More Important

Sometimes variables should mimic the parameters of an API. This is especially true when interacting with REST API json bodies.

You have a couple of choices:

Given this example body:

{
"firstName": "value",
"lastName": "value"
}

Then choose either:

*** Keywords ***
Create Json Body Option One
[Documentation] This one is an 'OK' example.
[Arguments] ${first name} ${last name}
${json body} Create Dictionary firstName=${first name} lastName=${last name}
RETURN ${json body}

Embedded Variables

variables-inside-variables

Be careful to not embed more than one variable within a variable.

Keep it simple.

Readability becomes an issue with more than one embedded variable.

*** Keywords ***
Set Suite Variables
Set Suite Variable ${EMBED VAR} embedded
Set Suite Variable ${VARIABLE ${EMBED VAR}} good embedded variable
Set Suite Variable ${FOO} eggs
Set Suite Variable ${BAR} spam
Set Suite Variable ${VARIABLE ${FOO} ${BAR}} questionable variable
Set Suite Variable ${VAR} one
Set Suite Variable ${WITHIN ${VAR}} two
Set Suite Variable ${VARIABLES ${WITHIN ${VAR}}} three
Set Suite Variable ${INCEPTION ${VARIABLES ${WITHIN ${VAR}}}} do not do this

Variables with Attributes

extended-variable-assignment

Attributes to variables can be any casing and usually follow the use case. The variable itself should follow the casing rules of its scope.

Attribute Variables
${local variable.name} Set Variable this is a variable
${local variable.foo} Set Variable this is a local attribute
Set Suite Variable ${SUITE VARIABLE.name} this is a suite variable
${SUITE VARIABLE.bar} Set Variable this is a suite attribute
- + \ No newline at end of file diff --git a/docs/testcase_styles/bdd.html b/docs/testcase_styles/bdd.html index 95963e7b..e209756b 100644 --- a/docs/testcase_styles/bdd.html +++ b/docs/testcase_styles/bdd.html @@ -5,13 +5,13 @@ BDD (Behavior Driven Development) | ROBOT FRAMEWORK - +

BDD (Behavior Driven Development)

What is BDD?

The Given-When-Then syntax is a commonly used structure for writing user stories and acceptance criteria in behavior-driven development (BDD). It is used to describe the desired behavior of a system in a clear, concise, and consistent manner.

The structure is broken down into three parts:

  • Given: This section describes the initial state or context of the system. It sets the scene for the scenario being tested.
  • When: This section describes the action or event that occurs. It specifies the trigger for the scenario being tested.
  • Then: This section describes the expected outcome or result of the scenario. It defines the acceptance criteria for the scenario being tested.

Example:

Given a user is on the login page
When the user enters their username and password and clicks the login button
Then the user should be directed to the home page.
*** Test Cases ***
Login With Admin
Given I am on the login page
When I login with username "admin" and password "admin"
Then I should see the welcome page

Login With Invalid User
Given I am on the login page
When I login with username "invalid" and password "invalid"
Then I should see the error message
And I should be able to login again
Let me run it
- + \ No newline at end of file diff --git a/docs/testcase_styles/datadriven.html b/docs/testcase_styles/datadriven.html index f4f56900..f341b322 100644 --- a/docs/testcase_styles/datadriven.html +++ b/docs/testcase_styles/datadriven.html @@ -5,7 +5,7 @@ DataDriven Tests | ROBOT FRAMEWORK - + @@ -15,7 +15,7 @@ The Test Cases section just contains

  • the Test Case Name
  • the arguments for the Keyword defined in the Test Template setting
*** Settings ***
Test Template Login with invalid credentials should fail

*** Test Cases *** USERNAME PASSWORD
Invalid User Name invalid ${VALID PASSWORD}
Invalid Password ${VALID USER} invalid
Invalid User Name and Password invalid invalid
Empty User Name ${EMPTY} ${VALID PASSWORD}
Empty Password ${VALID USER} ${EMPTY}
Empty User Name and Password ${EMPTY} ${EMPTY}

*** Keywords ***
Login with invalid credentials should fail
[Arguments] ${username} ${password}
Log Many ${username} ${password}
Let me run it

Using DataDriver Library

The DataDriver library is an extension for Robot Framework®.
DataDriver 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.
The DataDriver library is not included in the Robot Framework distribution, but it can be installed using pip.

pip install robotframework-datadriver

A simple Test Suite which logs the username and password from the CSV file.

*** Settings ***
Library DataDriver
Test Template Login With User And Password

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

*** Keywords ***
Login With User And Password
[Arguments] ${username} ${password}
Log Many ${username} ${password}

The CSV file contains the test data.

*** 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
;${EMPTY};mode;1,2,3,4;This test case has a generated name based on template name.
;${EMPTY};${EMPTY};;
;${EMPTY};FooBar;;
;FooBar;mode;foo,1;
;FooBar;${EMPTY};foo;
;FooBar;FooBar;foo,2;

Check the DataDriver Library repository for more information.

Let me run it
- + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/ci.html b/docs/using_rf_in_ci_systems/ci.html index 43ceebc8..45c1e2f5 100644 --- a/docs/using_rf_in_ci_systems/ci.html +++ b/docs/using_rf_in_ci_systems/ci.html @@ -5,13 +5,13 @@ CI Systems | ROBOT FRAMEWORK - + - + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/ci/azure-devops.html b/docs/using_rf_in_ci_systems/ci/azure-devops.html index 28204690..19be7b1e 100644 --- a/docs/using_rf_in_ci_systems/ci/azure-devops.html +++ b/docs/using_rf_in_ci_systems/ci/azure-devops.html @@ -5,7 +5,7 @@ ⛔ Azure DevOps | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@ - + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/ci/github-actions.html b/docs/using_rf_in_ci_systems/ci/github-actions.html index 81a39ead..afb74eaa 100644 --- a/docs/using_rf_in_ci_systems/ci/github-actions.html +++ b/docs/using_rf_in_ci_systems/ci/github-actions.html @@ -5,7 +5,7 @@ ⛔ GitHub Actions | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@ - + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/ci/gitlab.html b/docs/using_rf_in_ci_systems/ci/gitlab.html index b7370028..79b824ba 100644 --- a/docs/using_rf_in_ci_systems/ci/gitlab.html +++ b/docs/using_rf_in_ci_systems/ci/gitlab.html @@ -5,7 +5,7 @@ GitLab | ROBOT FRAMEWORK - + @@ -24,7 +24,7 @@ That's possible, because the --outputdir in the robot command was set to reports.

robot --outputdir reports tests/smoke

Variables

.gitlab-ci.yml
variables:
ROBOT_OPTIONS: "--variable BROWSER:chrome"

run-smoke-tests:
stage: smoke
script:
- robot --outputdir reports $ROBOT_OPTIONS tests/smoke
artifacts:
paths:
- reports

It is possible to define variables in the configuration, either at the top of the file or in a job.
Also predefined GitLab variables or variables defined for your project settings can be used.
Especially for handling secrets, it is recommended to use CI Variables in your project settings.

Check out the GitLab CI Variables documentation for more information.

- + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/ci/jenkins.html b/docs/using_rf_in_ci_systems/ci/jenkins.html index 4cc9b6a4..a8125d54 100644 --- a/docs/using_rf_in_ci_systems/ci/jenkins.html +++ b/docs/using_rf_in_ci_systems/ci/jenkins.html @@ -5,7 +5,7 @@ Jenkins | ROBOT FRAMEWORK - + @@ -20,7 +20,7 @@ to change your CSP settings. However, please note that changing your CSP settings will potentially expose your Jenkins instance for security vulnerabilities.

Examples

Jenkinsfile with a stage Run Robot

pipeline {
agent { label "robot" } // run on an agent, which has Robot Framework installed

stages {
stage("Run Robot") {
steps {
// --nostatusrc prevents your job from failing automatically if any
// tests fail. This is then later handled with the RF plugin with
// pass thresholds
sh script: "robot --nostatusrc my_tests.robot", returnStatus: true
}
}
}

post {
always {
// `onlyCritical: false` is for RF 3.x compatibility. This will be deprecated
// and removed in the future.
robot outputPath: '.', passThreshold: 80.0, unstableThreshold: 70.0, onlyCritical: false
}
}
}

Jenkinsfile with parameters and multiple stages

pipeline {
properties([
parameters([
choice(choices: ['test','staging'], description: 'Environment to run the tests against', name: 'environment'),
string(name: 'INCLUDE', defaultValue: 'valid_loginORinvalid_login', description: 'Specify which tags you want to run (e.g. valid_login)'),
string(name: 'EXCLUDE', description: 'Specify if you want to exclude tests by category tags'),
string(name: 'FOLDER', defaultValue: 'tests', description: 'Specify the folder for tests (e.g. . for current dir'),
string(name: 'BRANCH', defaultValue: 'main', description: 'Specify the branch for tests (e.g. main')
])

// -- Script arguments --------------------------------
def include = "${params.INCLUDE}"
def exclude = "${params.EXCLUDE}"
def folder = "${params.FOLDER}"
def branch = "${params.BRANCH}"
def args = ""
// ----------------------------------------------------

agent { label 'robot'} // how is your Jenkins agent labeled, so that right kind of agent is used for execution

stages {
stage('Checkout') {
steps {
script {
// checkout your code here
}
}
}
stage('Define args') {
steps {
script {
if (!include.isEmpty()) {
args += " -i $include"
}
if (!exclude.isEmpty()) {
args += " -e $exclude"
}
if (!folder.isEmpty()) {
args += " $folder"
} else {
args += " ."
}
}
}
}
stage('Run Robot tests') {
steps {
sh """
// command to run your tests
"""
}
post {
always {
step([
$class : 'RobotPublisher',
outputPath : 'test_results',
outputFileName : "output.xml",
reportFileName : 'report.html',
logFileName : 'log.html',
disableArchiveOutput: false,
passThreshold : 95.0,
unstableThreshold : 95.0,
otherFiles : "**/*.png",
])
}
}

Special notes about running tests with Browser library behind firewall

This is related especially to the use of Browser library which requires installations and initialisation to be done before the tests can be executed.

Preparing the Jenkins agent

These are steps that needs to be done by the person administrating the Jenkins agents.

  • Install all the tools that are needed for running the tests: nodejs, python 3.x, Robot Framework, Browser library
  • Set PLAYWRIGHT_BROWSERS_PATH to point where you want to install browsers
  • Execute rfbrowser init to get the base setup for Browser library. Note that you still need to execute it with Jenkins user as well, see below.

Preparing the Jenkins configuration file

These are steps you need to have in your Jenkins configuration. I recommend putting those as commands in the same shell command set together with test execution ("command to run your tests")

  • npm config set registry https://local-site-for-node-modules <-- here you need a server that is providing all required node modules; if it doesn't exist proxy config might work as well
  • Additional commands that might be needed could be npm config set strict-ssl false or npm config set always-auth truedepending how the server is configured
  • Then run rfbrowser init --skip-browsers to avoid the installation of browsers that may appear hard over the firewall
  • ... and use instead the ones installed by root when the agent was initialised by pointing with ```PLAYWRIGHT_BROWSERS_PATH```` to the location defined

Now you should be ready to execute tests.

- + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/ci/teamcity.html b/docs/using_rf_in_ci_systems/ci/teamcity.html index 88f69228..29953a59 100644 --- a/docs/using_rf_in_ci_systems/ci/teamcity.html +++ b/docs/using_rf_in_ci_systems/ci/teamcity.html @@ -5,7 +5,7 @@ ⛔ TeamCity | ROBOT FRAMEWORK - + @@ -13,7 +13,7 @@ - + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/docker.html b/docs/using_rf_in_ci_systems/docker.html index 4a5d0ded..54262fa2 100644 --- a/docs/using_rf_in_ci_systems/docker.html +++ b/docs/using_rf_in_ci_systems/docker.html @@ -5,7 +5,7 @@ Docker Images for Robot Framework | ROBOT FRAMEWORK - + @@ -19,7 +19,7 @@ Let's assume the folder is located at /home/user/my-project/ on your local machine.

Folder structure
my-project/
├── Dockerfile
├── tests/
│ └── testsuite.robot
└── results/

The following command will run the container and mount the folders my-project/ into the container.
The tests in the folder my-project/tests will be executed and the results will be written into the folder my-project/results.

That way, you can easily run your tests in a container and have the results on your local machine.

docker run -it --rm -v /home/user/my-project:/my-project my-robotframework-dockerimage bash -c "robot --outputdir /project/results  /my-project/tests"

Simple Python Dockerimage with Robot Framework

A very simple python image, which only adds robotframework

Dockerfile
FROM python:3
RUN pip install robotframework

You can also add your python dependencies into a file requirements.txt and then install them using pip install -r requirements.txt.

Folder structure
.
├── Dockerfile
└── requirements.txt
requirements.txt
robotframework
robotframework-requests
robotframework-datadriver
Dockerfile
FROM python:3

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

Dockerimage with Robot Framework and Browser Library

An image containing robotframework and robotframework-browser.
It is based on playwright baseimage, as it contains necessary dependencies like nodejs and npm.

Dockerfile
FROM mcr.microsoft.com/playwright:focal
USER root
RUN apt-get update
RUN apt-get install -y python3-pip
USER pwuser
RUN pip3 install --user robotframework
RUN pip3 install --user robotframework-browser
RUN ~/.local/bin/rfbrowser init
ENV NODE_PATH=/usr/lib/node_modules
ENV PATH="/home/pwuser/.local/bin:${PATH}"

marketsquare/robotframework-browser

https://github.com/MarketSquare/robotframework-browser/tree/main/docker

docker pull marketsquare/robotframework-browser

The image comes with latest robotframework-browser and robotframework, and with pre-initialized browsers and other dependencies for running headful tests in the container.

Example usage:

docker run --rm -v $(pwd)/atest/test/:/test --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json marketsquare/robotframework-browser:latest bash -c "robot --outputdir /test/output /test"

docker run -v is used to mount the directory containing tests on the supervising machine. In this example robot output will also be output inside the test directory

ppodgorsek/robot-framework

https://github.com/ppodgorsek/docker-robot-framework

Check the list of included packages

This container can be run using the following command:

    docker run \
-v <local path to the reports' folder>:/opt/robotframework/reports:Z \
-v <local path to the test suites' folder>:/opt/robotframework/tests:Z \
ppodgorsek/robot-framework:<version>
- + \ No newline at end of file diff --git a/docs/using_rf_in_ci_systems/playground.html b/docs/using_rf_in_ci_systems/playground.html index 0f968677..d4db3bf2 100644 --- a/docs/using_rf_in_ci_systems/playground.html +++ b/docs/using_rf_in_ci_systems/playground.html @@ -5,7 +5,7 @@ Play With Docker | ROBOT FRAMEWORK - + @@ -19,7 +19,7 @@ That error happens, because there is no index.html file in the reports folder.

However, if you add a /log.html at the end of the URL, you will see the log.html file.
If you add a /report.html at the end of the URL, you will see the report.html file.

The url should look like this:
http://ip<some-ip>-<some-identifier>-80.direct.labs.play-with-docker.com/log.html

- + \ No newline at end of file diff --git a/docs/variables.html b/docs/variables.html index 025de810..6f5478c1 100644 --- a/docs/variables.html +++ b/docs/variables.html @@ -5,7 +5,7 @@ Variables | ROBOT FRAMEWORK - + @@ -25,7 +25,7 @@ With the syntax @{beer_crate} you get the bottles.
With the syntax ${beer_crate}[index] you get a specific bottle inside the crate.

Variable Files

It is possible to load variables from external files, like Python (.py) or .yaml files.
For Yaml files, the package pyyaml is required.

pip install pyyaml

.py files will be interpreted as Python Code, so you can create simple variables, lists or dictionaries and even complex objects like classes.

PythonVariables.py
class TestEnv:
ip = '123.4.5.6'
user = 'robot'
roles = ['admin', 'user']

my_var = 'Hello World'
my_list = ["Apple", "Banana", "Cherry"]
my_dict = {'name': 'John', 'age': 36}

Even dynamic variables using are possible by executing any Python code inside the variable file.

DynamicVariables.py
import os
import random
import time
import math

USER = os.getlogin() # current login name
RANDOM_INT = random.randint(0, 10) # random integer in range [0,10]
CURRENT_TIME = time.asctime() # timestamp like 'Thu Apr 6 12:45:21 2006'
if time.localtime()[3] > 12:
AFTERNOON = True
else:
AFTERNOON = False

def get_area(diameter):
radius = diameter / 2
area = math.pi * radius * radius
return area

AREA1 = get_area(1)
AREA2 = get_area(2)

.yaml (or .yml) files will be interpreted as a dictionary.

YamlVariables.yml
# These are scalars:
base_url: https://qaserver.mycompany.com:8080
admin_user: iAmAdMiN
admin_password: eieioscoobydoo1234
# Now, a list:
yaml_list:
- Item 1
- Item two
- 3
# Finally, a dictionary:
yaml_dict:
key_1: A string
key_2: 1 # an int
TestSuite.robot
*** Settings ***
Variables PythonVariables.py
Variables YamlVariables.yaml
Variables DynamicVariables.py

*** Test Cases ***
Access Python Variables
Log ${TestEnv.ip}
Log ${TestEnv.roles}
Log Many @{TestEnv.roles}
Log ${my_var}
Log Many @{my_list}
Log Many &{my_dict}
FOR ${item} IN @{my_list}
Log ${item}
END

Access Yaml Variables
Log ${base_url}
Log Many @{yaml_list}
Log ${yaml_dict}
Log ${yaml_dict}[key_1]

Access Dynamic Variables
Log ${USER}
Log ${RANDOM_INT}
Log ${CURRENT_TIME}
Log ${AFTERNOON}
Log ${AREA1}
Log ${AREA2}
Let me run it
- + \ No newline at end of file diff --git a/index.html b/index.html index b47751dc..27576af4 100644 --- a/index.html +++ b/index.html @@ -5,13 +5,13 @@ Hello from ROBOT FRAMEWORK | ROBOT FRAMEWORK - + - + \ No newline at end of file diff --git a/markdown-page.html b/markdown-page.html index 4dc3d4cb..5673e622 100644 --- a/markdown-page.html +++ b/markdown-page.html @@ -5,13 +5,13 @@ Markdown page example | ROBOT FRAMEWORK - +

Markdown page example

You don't need React to write simple standalone pages.

- + \ No newline at end of file diff --git a/search.html b/search.html index 5981c36d..11fbb0c2 100644 --- a/search.html +++ b/search.html @@ -5,13 +5,13 @@ Search the documentation | ROBOT FRAMEWORK - + - + \ No newline at end of file