diff --git a/404.html b/404.html index cdd7c2d..6e28683 100644 --- a/404.html +++ b/404.html @@ -7,13 +7,13 @@ Page Not Found | Serenity BDD Users Manual - +
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/4d262bef.6ca21062.js b/assets/js/4d262bef.6ca21062.js new file mode 100644 index 0000000..6b070c5 --- /dev/null +++ b/assets/js/4d262bef.6ca21062.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkserenity_users_guide=self.webpackChunkserenity_users_guide||[]).push([[6539],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>d});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},s=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,c=e.parentName,s=u(e,["components","mdxType","originalType","parentName"]),m=l(n),d=a,f=m["".concat(c,".").concat(d)]||m[d]||p[d]||i;return n?r.createElement(f,o(o({ref:t},s),{},{components:n})):r.createElement(f,o({ref:t},s))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=m;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u.mdxType="string"==typeof e?e:a,o[1]=u;for(var l=2;l{n.r(t),n.d(t,{contentTitle:()=>o,default:()=>s,frontMatter:()=>i,metadata:()=>u,toc:()=>c});var r=n(7462),a=(n(7294),n(3905));const i={},o="Running Cucumber scenarios with Serenity",u={unversionedId:"guide/cucumber",id:"guide/cucumber",isDocsHomePage:!1,title:"Running Cucumber scenarios with Serenity",description:"To run Cucumber scenarios with Serenity, you need to create a Junit 5 test runner class like this:",source:"@site/docs/guide/cucumber.md",sourceDirName:"guide",slug:"/guide/cucumber",permalink:"/docs/guide/cucumber",editUrl:"https://github.com/serenity-bdd/serenity-bdd.github.io/blob/master/docs/guide/cucumber.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Configuring Selenium WebDriver",permalink:"/docs/guide/driver_config"},next:{title:"Screenplay Fundamentals",permalink:"/docs/screenplay/screenplay_fundamentals"}},c=[],l={toc:c};function s(e){let{components:t,...i}=e;return(0,a.kt)("wrapper",(0,r.Z)({},l,i,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h1",{id:"running-cucumber-scenarios-with-serenity"},"Running Cucumber scenarios with Serenity"),(0,a.kt)("p",null,"To run Cucumber scenarios with Serenity, you need to create a Junit 5 test runner class like this:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},' import org.junit.platform.suite.api.IncludeEngines;\n import org.junit.platform.suite.api.SelectClasspathResource;\n import org.junit.platform.suite.api.Suite;\n \n @Suite\n @IncludeEngines("cucumber")\n @SelectClasspathResource("/features")\n public class CucumberTestSuite {}\n')),(0,a.kt)("p",null,"Note that you need to specify at least the ",(0,a.kt)("inlineCode",{parentName:"p"},"features")," attribute, to define the directory containing your feature files."),(0,a.kt)("h1",{id:"feature-hierarchies"},"Feature hierarchies"),(0,a.kt)("p",null,"Serenity expects to find feature files in the ",(0,a.kt)("inlineCode",{parentName:"p"},"src/test/resources/features")," folder by default. You can organise your feature files in a hierarchy of folders underneath this one, as shown here:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"+ src\n|-- test\n| |-- resources\n| | |-- features\n| | | |-- authentication\n| | | | |-- login.feature\n| | | |-- cart\n| | | | |-- managing_the_cart.feature\n| | | |-- catalog\n| | | | |-- browse_catalog.feature\n| | | | |-- filtering_products.feature\n| | | |-- purchases\n| | | | |-- completing_a_purchase.feature\n| | | |-- sales_tax\n| | | | |-- calculating_sales_tax.feature\n")),(0,a.kt)("p",null,"The directory structure will be used to build the Serenity requirements hierarchy, like the one shown here:"),(0,a.kt)("p",null,(0,a.kt)("img",{src:n(4010).Z})),(0,a.kt)("h1",{id:"filtering-test-execution-in-cucumber"},"Filtering test execution in Cucumber"),(0,a.kt)("p",null,"The simplest way to control which scenarios you want to execute is to use tags and the ",(0,a.kt)("inlineCode",{parentName:"p"},"cucumber.filter.tags")," command line option. For example, to run only scenarios or features annotated with ",(0,a.kt)("inlineCode",{parentName:"p"},"@smoke"),", you would run the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},'mvn clean verify -Dcucumber.filter.tags="@smoke"\n')),(0,a.kt)("p",null,"You can use ",(0,a.kt)("a",{parentName:"p",href:"https://cucumber.io/docs/cucumber/api/#tag-expressions"},"Cucumber Tag Expressions")," to determine which scenarios to run. For example, to run only features with both the ",(0,a.kt)("inlineCode",{parentName:"p"},"@authentication")," tag and the ",(0,a.kt)("inlineCode",{parentName:"p"},"@smoke")," tag, you would run the following:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},' mvn clean verify -Dcucumber.filter.tags="@authentication and @smoke"\n')),(0,a.kt)("p",null,"To run scenarios with either the ",(0,a.kt)("inlineCode",{parentName:"p"},"@cart")," or the ",(0,a.kt)("inlineCode",{parentName:"p"},"@catalog")," tag, you could run the following:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},' mvn clean verify -Dcucumber.filter.tags="@cart or @catalog"\n')),(0,a.kt)("h1",{id:"running-cucumber-scenarios-with-serenity-in-parallel"},"Running Cucumber scenarios with Serenity in parallel"),(0,a.kt)("p",null,"Starting with version 3.6.0, is possible to run the Cucumber scenarios in parallel."),(0,a.kt)("p",null,"The following steps are necessary to activate the parallel execution: "),(0,a.kt)("ol",null,(0,a.kt)("li",{parentName:"ol"},"Add following dependencies in your application pom.xml:")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-xml"}," \n io.cucumber\n cucumber-junit-platform-engine\n 7.11.0\n test\n \n \n \n org.junit.platform\n junit-platform-suite\n 1.9.2\n test\n \n")),(0,a.kt)("ol",{start:2},(0,a.kt)("li",{parentName:"ol"},"Create a file named ",(0,a.kt)("inlineCode",{parentName:"li"},"junit-platform.properties")," under ",(0,a.kt)("inlineCode",{parentName:"li"},"test/resources"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre"},"cucumber.execution.parallel.enabled=true\ncucumber.execution.parallel.config.strategy=fixed\ncucumber.execution.parallel.config.fixed.parallelism=4\ncucumber.execution.parallel.config.fixed.max-pool-size=4\ncucumber.plugin=io.cucumber.core.plugin.SerenityReporterParallel\n")),(0,a.kt)("p",null,"More informations about the meaning of the properties can be found in ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/cucumber/cucumber-jvm/tree/main/cucumber-junit-platform-engine"},"Cucumber JUnit Platform Engine Documentation")),(0,a.kt)("ol",{start:3},(0,a.kt)("li",{parentName:"ol"},"Configure the classpath location of the scenarios to be executed in a Java class placed in a package under ",(0,a.kt)("inlineCode",{parentName:"li"},"test/java"))),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-java"},' import org.junit.platform.suite.api.IncludeEngines;\n import org.junit.platform.suite.api.SelectClasspathResource;\n import org.junit.platform.suite.api.Suite;\n \n @Suite\n @IncludeEngines("cucumber")\n @SelectClasspathResource("/features")\n public class CucumberTestSuite {}\n')))}s.isMDXComponent=!0},4010:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/cucumber-requirements-hierarchy-a21ffb057df85059e19480918c7c2d34.png"}}]); \ No newline at end of file diff --git a/assets/js/4d262bef.f8773f53.js b/assets/js/4d262bef.f8773f53.js deleted file mode 100644 index e646c80..0000000 --- a/assets/js/4d262bef.f8773f53.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkserenity_users_guide=self.webpackChunkserenity_users_guide||[]).push([[6539],{3905:(e,t,n)=>{n.d(t,{Zo:()=>s,kt:()=>d});var r=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function u(e){for(var t=1;t=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var c=r.createContext({}),l=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):u(u({},t),e)),n},s=function(e){var t=l(e.components);return r.createElement(c.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,i=e.mdxType,a=e.originalType,c=e.parentName,s=o(e,["components","mdxType","originalType","parentName"]),m=l(n),d=i,f=m["".concat(c,".").concat(d)]||m[d]||p[d]||a;return n?r.createElement(f,u(u({ref:t},s),{},{components:n})):r.createElement(f,u({ref:t},s))}));function d(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=n.length,u=new Array(a);u[0]=m;var o={};for(var c in t)hasOwnProperty.call(t,c)&&(o[c]=t[c]);o.originalType=e,o.mdxType="string"==typeof e?e:i,u[1]=o;for(var l=2;l{n.r(t),n.d(t,{contentTitle:()=>u,default:()=>s,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var r=n(7462),i=(n(7294),n(3905));const a={},u="Running Cucumber scenarios with Serenity",o={unversionedId:"guide/cucumber",id:"guide/cucumber",isDocsHomePage:!1,title:"Running Cucumber scenarios with Serenity",description:"To run Cucumber scenarios with Serenity, you need to create a Junit 4 test runner class and use @RunWith annotation in with the CucumberWithSerenity class, like this:",source:"@site/docs/guide/cucumber.md",sourceDirName:"guide",slug:"/guide/cucumber",permalink:"/docs/guide/cucumber",editUrl:"https://github.com/serenity-bdd/serenity-bdd.github.io/blob/master/docs/guide/cucumber.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Configuring Selenium WebDriver",permalink:"/docs/guide/driver_config"},next:{title:"Screenplay Fundamentals",permalink:"/docs/screenplay/screenplay_fundamentals"}},c=[],l={toc:c};function s(e){let{components:t,...a}=e;return(0,i.kt)("wrapper",(0,r.Z)({},l,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"running-cucumber-scenarios-with-serenity"},"Running Cucumber scenarios with Serenity"),(0,i.kt)("p",null,"To run Cucumber scenarios with Serenity, you need to create a Junit 4 test runner class and use ",(0,i.kt)("inlineCode",{parentName:"p"},"@RunWith")," annotation in with the ",(0,i.kt)("inlineCode",{parentName:"p"},"CucumberWithSerenity")," class, like this:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},'import io.cucumber.junit.CucumberOptions;\nimport net.serenitybdd.cucumber.CucumberWithSerenity;\nimport org.junit.runner.RunWith;\n\n@RunWith(CucumberWithSerenity.class)\n@CucumberOptions(\n plugin = {"pretty"},\n features = "src/test/resources/features"\n)\npublic class AcceptanceTestSuite {}\n')),(0,i.kt)("p",null,"Note that you need to specify at least the ",(0,i.kt)("inlineCode",{parentName:"p"},"features")," attribute, to define the directory containing your feature files."),(0,i.kt)("h1",{id:"feature-hierarchies"},"Feature hierarchies"),(0,i.kt)("p",null,"Serenity expects to find feature files in the ",(0,i.kt)("inlineCode",{parentName:"p"},"src/test/resources/features")," folder by default. You can organise your feature files in a hierarchy of folders underneath this one, as shown here:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"+ src\n|-- test\n| |-- resources\n| | |-- features\n| | | |-- authentication\n| | | | |-- login.feature\n| | | |-- cart\n| | | | |-- managing_the_cart.feature\n| | | |-- catalog\n| | | | |-- browse_catalog.feature\n| | | | |-- filtering_products.feature\n| | | |-- purchases\n| | | | |-- completing_a_purchase.feature\n| | | |-- sales_tax\n| | | | |-- calculating_sales_tax.feature\n")),(0,i.kt)("p",null,"The directory structure will be used to build the Serenity requirements hierarchy, like the one shown here:"),(0,i.kt)("p",null,(0,i.kt)("img",{src:n(4010).Z})),(0,i.kt)("h1",{id:"filtering-test-execution-in-cucumber"},"Filtering test execution in Cucumber"),(0,i.kt)("p",null,"The simplest way to control which scenarios you want to execute is to use tags and the ",(0,i.kt)("inlineCode",{parentName:"p"},"cucumber.filter.tags")," command line option. For example, to run only scenarios or features annotated with ",(0,i.kt)("inlineCode",{parentName:"p"},"@smoke"),", you would run the following command:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},'mvn clean verify -Dcucumber.filter.tags="@smoke"\n')),(0,i.kt)("p",null,"You can use ",(0,i.kt)("a",{parentName:"p",href:"https://cucumber.io/docs/cucumber/api/#tag-expressions"},"Cucumber Tag Expressions")," to determine which scenarios to run. For example, to run only features with both the ",(0,i.kt)("inlineCode",{parentName:"p"},"@authentication")," tag and the ",(0,i.kt)("inlineCode",{parentName:"p"},"@smoke")," tag, you would run the following:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},' mvn clean verify -Dcucumber.filter.tags="@authentication and @smoke"\n')),(0,i.kt)("p",null,"To run scenarios with either the ",(0,i.kt)("inlineCode",{parentName:"p"},"@cart")," or the ",(0,i.kt)("inlineCode",{parentName:"p"},"@catalog")," tag, you could run the following:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},' mvn clean verify -Dcucumber.filter.tags="@cart or @catalog"\n')),(0,i.kt)("h1",{id:"running-cucumber-scenarios-with-serenity-in-parallel"},"Running Cucumber scenarios with Serenity in parallel"),(0,i.kt)("p",null,"Starting with version 3.6.0, is possible to run the Cucumber scenarios in parallel."),(0,i.kt)("p",null,"The following steps are necessary to activate the parallel execution: "),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"Add following dependencies in your application pom.xml:")),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml"}," \n io.cucumber\n cucumber-junit-platform-engine\n 7.11.0\n test\n \n \n \n org.junit.platform\n junit-platform-suite\n 1.9.2\n test\n \n")),(0,i.kt)("ol",{start:2},(0,i.kt)("li",{parentName:"ol"},"Create a file named ",(0,i.kt)("inlineCode",{parentName:"li"},"junit-platform.properties")," under ",(0,i.kt)("inlineCode",{parentName:"li"},"test/resources"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre"},"cucumber.execution.parallel.enabled=true\ncucumber.execution.parallel.config.strategy=fixed\ncucumber.execution.parallel.config.fixed.parallelism=4\ncucumber.execution.parallel.config.fixed.max-pool-size=4\ncucumber.plugin=io.cucumber.core.plugin.SerenityReporterParallel\n")),(0,i.kt)("p",null,"More informations about the meaning of the properties can be found in ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/cucumber/cucumber-jvm/tree/main/cucumber-junit-platform-engine"},"Cucumber JUnit Platform Engine Documentation")),(0,i.kt)("ol",{start:3},(0,i.kt)("li",{parentName:"ol"},"Configure the classpath location of the scenarios to be executed in a Java class placed in a package under ",(0,i.kt)("inlineCode",{parentName:"li"},"test/java"))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-java"},' import org.junit.platform.suite.api.IncludeEngines;\n import org.junit.platform.suite.api.SelectClasspathResource;\n import org.junit.platform.suite.api.Suite;\n \n @Suite\n @IncludeEngines("cucumber")\n @SelectClasspathResource("/features")\n public class CucumberTestSuite {}\n')))}s.isMDXComponent=!0},4010:(e,t,n)=>{n.d(t,{Z:()=>r});const r=n.p+"assets/images/cucumber-requirements-hierarchy-a21ffb057df85059e19480918c7c2d34.png"}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.84f772bf.js b/assets/js/runtime~main.41b10e88.js similarity index 99% rename from assets/js/runtime~main.84f772bf.js rename to assets/js/runtime~main.41b10e88.js index 9d222b0..01e284f 100644 --- a/assets/js/runtime~main.84f772bf.js +++ b/assets/js/runtime~main.41b10e88.js @@ -1 +1 @@ -(()=>{"use strict";var e,c,f,a,b,t={},r={};function d(e){var c=r[e];if(void 0!==c)return c.exports;var f=r[e]={exports:{}};return t[e].call(f.exports,f,f.exports,d),f.exports}d.m=t,e=[],d.O=(c,f,a,b)=>{if(!f){var t=1/0;for(i=0;i=b)&&Object.keys(d.O).every((e=>d.O[e](f[o])))?f.splice(o--,1):(r=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[f,a,b]},d.n=e=>{var c=e&&e.__esModule?()=>e.default:()=>e;return d.d(c,{a:c}),c},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var b=Object.create(null);d.r(b);var t={};c=c||[null,f({}),f([]),f(f)];for(var r=2&a&&e;"object"==typeof r&&!~c.indexOf(r);r=f(r))Object.getOwnPropertyNames(r).forEach((c=>t[c]=()=>e[c]));return t.default=()=>e,d.d(b,t),b},d.d=(e,c)=>{for(var f in c)d.o(c,f)&&!d.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:c[f]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((c,f)=>(d.f[f](e,c),c)),[])),d.u=e=>"assets/js/"+({53:"935f2afb",533:"b2b675dd",626:"9aeb17c1",657:"9855f4f4",1196:"d8224fc8",1477:"b2f554cd",1713:"a7023ddc",2258:"7b7bf1f9",2274:"500cccec",2535:"814f3328",2857:"83b05699",2929:"9b0b478f",3045:"dfbef622",3065:"2e7f4390",3085:"1f391b9e",3089:"a6aa9e1f",3283:"b49e0726",3316:"4944066c",3537:"5c4f0d90",3608:"9e4087bc",3751:"3720c009",3804:"8753baeb",3809:"5cdba952",4013:"01a85c17",4121:"55960ee5",4195:"c4f5d8e4",4541:"2a7ee7b4",5069:"e9b89100",5087:"f355ac6c",5478:"50e7f874",5506:"364e68ca",5576:"cb9cecfd",5627:"5613c9ed",5892:"52eff6c9",6094:"e24bb847",6103:"ccc49370",6389:"a1a68211",6539:"4d262bef",6542:"27688537",6561:"44bbcc1c",6588:"8c15a673",6912:"16ebfebc",6917:"82c6c1dc",7258:"28a1442d",7414:"393be207",7417:"64223023",7447:"40b7e58f",7483:"a50e347c",7506:"9cee31f8",7671:"cf53798e",7915:"4a3a5cb1",7918:"17896441",8299:"78f2a083",8360:"d21ba92f",8368:"c6f47719",8388:"68c46c38",8610:"6875c492",9151:"d078d492",9347:"63441a2d",9499:"802c8227",9514:"1be78505",9518:"2f96067e",9562:"7cd378c7"}[e]||e)+"."+{53:"7e4b06a8",533:"b0a45e3e",626:"e512db79",657:"cb9fe74f",1196:"e4565ea7",1477:"f7c04ebd",1713:"94156c60",2258:"22325216",2274:"df5e98cd",2431:"f269ddc8",2535:"d0b43302",2857:"0db740ec",2929:"b6108c55",3045:"c575f7b2",3065:"edb06604",3085:"627baa95",3089:"b95e3896",3283:"c3a9c377",3316:"4b8d7a22",3537:"a5904f41",3608:"b79baad0",3751:"41eaf847",3804:"0d8b234e",3809:"611c8064",4013:"1bffd8b2",4121:"08078751",4195:"bb22baad",4541:"faf03b08",4608:"6643b6da",5069:"26edbaf5",5087:"f9820a6d",5256:"5c9ae4aa",5478:"e3090c17",5506:"e93326f8",5576:"c9bf62b6",5627:"967c5af6",5892:"a71dff21",6094:"1794caeb",6103:"7d7b9341",6159:"4cdfb506",6254:"b41f5763",6389:"6f97b350",6539:"f8773f53",6542:"a102f6e8",6561:"726eb4a2",6588:"b079d97e",6912:"0bb23cfa",6917:"86d69d9c",6945:"b10995d3",7258:"d13dc076",7414:"effafed3",7417:"14cbafc6",7447:"7ae9f69e",7483:"e2f6f8d4",7506:"ddee2d5a",7671:"f8223977",7915:"f787da07",7918:"9519ba81",8299:"44f390d7",8360:"d46b35a7",8368:"52a5fca2",8388:"4d7d326c",8610:"c8f1563a",9151:"d5b16957",9347:"c7997b89",9499:"6dd419ea",9514:"7bc792d8",9518:"4ed2a4c4",9562:"a7cc4966",9727:"abfea59d"}[e]+".js",d.miniCssF=e=>"assets/css/styles.4fb1788f.css",d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,c)=>Object.prototype.hasOwnProperty.call(e,c),a={},b="serenity-users-guide:",d.l=(e,c,f,t)=>{if(a[e])a[e].push(c);else{var r,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{r.onerror=r.onload=null,clearTimeout(l);var b=a[e];if(delete a[e],r.parentNode&&r.parentNode.removeChild(r),b&&b.forEach((e=>e(f))),c)return c(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=u.bind(null,r.onerror),r.onload=u.bind(null,r.onload),o&&document.head.appendChild(r)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"7918",27688537:"6542",64223023:"7417","935f2afb":"53",b2b675dd:"533","9aeb17c1":"626","9855f4f4":"657",d8224fc8:"1196",b2f554cd:"1477",a7023ddc:"1713","7b7bf1f9":"2258","500cccec":"2274","814f3328":"2535","83b05699":"2857","9b0b478f":"2929",dfbef622:"3045","2e7f4390":"3065","1f391b9e":"3085",a6aa9e1f:"3089",b49e0726:"3283","4944066c":"3316","5c4f0d90":"3537","9e4087bc":"3608","3720c009":"3751","8753baeb":"3804","5cdba952":"3809","01a85c17":"4013","55960ee5":"4121",c4f5d8e4:"4195","2a7ee7b4":"4541",e9b89100:"5069",f355ac6c:"5087","50e7f874":"5478","364e68ca":"5506",cb9cecfd:"5576","5613c9ed":"5627","52eff6c9":"5892",e24bb847:"6094",ccc49370:"6103",a1a68211:"6389","4d262bef":"6539","44bbcc1c":"6561","8c15a673":"6588","16ebfebc":"6912","82c6c1dc":"6917","28a1442d":"7258","393be207":"7414","40b7e58f":"7447",a50e347c:"7483","9cee31f8":"7506",cf53798e:"7671","4a3a5cb1":"7915","78f2a083":"8299",d21ba92f:"8360",c6f47719:"8368","68c46c38":"8388","6875c492":"8610",d078d492:"9151","63441a2d":"9347","802c8227":"9499","1be78505":"9514","2f96067e":"9518","7cd378c7":"9562"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(c,f)=>{var a=d.o(e,c)?e[c]:void 0;if(0!==a)if(a)f.push(a[2]);else if(/^(1303|532)$/.test(c))e[c]=0;else{var b=new Promise(((f,b)=>a=e[c]=[f,b]));f.push(a[2]=b);var t=d.p+d.u(c),r=new Error;d.l(t,(f=>{if(d.o(e,c)&&(0!==(a=e[c])&&(e[c]=void 0),a)){var b=f&&("load"===f.type?"missing":f.type),t=f&&f.target&&f.target.src;r.message="Loading chunk "+c+" failed.\n("+b+": "+t+")",r.name="ChunkLoadError",r.type=b,r.request=t,a[1](r)}}),"chunk-"+c,c)}},d.O.j=c=>0===e[c];var c=(c,f)=>{var a,b,t=f[0],r=f[1],o=f[2],n=0;if(t.some((c=>0!==e[c]))){for(a in r)d.o(r,a)&&(d.m[a]=r[a]);if(o)var i=o(d)}for(c&&c(f);n{"use strict";var e,c,f,a,b,t={},r={};function d(e){var c=r[e];if(void 0!==c)return c.exports;var f=r[e]={exports:{}};return t[e].call(f.exports,f,f.exports,d),f.exports}d.m=t,e=[],d.O=(c,f,a,b)=>{if(!f){var t=1/0;for(i=0;i=b)&&Object.keys(d.O).every((e=>d.O[e](f[o])))?f.splice(o--,1):(r=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[f,a,b]},d.n=e=>{var c=e&&e.__esModule?()=>e.default:()=>e;return d.d(c,{a:c}),c},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var b=Object.create(null);d.r(b);var t={};c=c||[null,f({}),f([]),f(f)];for(var r=2&a&&e;"object"==typeof r&&!~c.indexOf(r);r=f(r))Object.getOwnPropertyNames(r).forEach((c=>t[c]=()=>e[c]));return t.default=()=>e,d.d(b,t),b},d.d=(e,c)=>{for(var f in c)d.o(c,f)&&!d.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:c[f]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((c,f)=>(d.f[f](e,c),c)),[])),d.u=e=>"assets/js/"+({53:"935f2afb",533:"b2b675dd",626:"9aeb17c1",657:"9855f4f4",1196:"d8224fc8",1477:"b2f554cd",1713:"a7023ddc",2258:"7b7bf1f9",2274:"500cccec",2535:"814f3328",2857:"83b05699",2929:"9b0b478f",3045:"dfbef622",3065:"2e7f4390",3085:"1f391b9e",3089:"a6aa9e1f",3283:"b49e0726",3316:"4944066c",3537:"5c4f0d90",3608:"9e4087bc",3751:"3720c009",3804:"8753baeb",3809:"5cdba952",4013:"01a85c17",4121:"55960ee5",4195:"c4f5d8e4",4541:"2a7ee7b4",5069:"e9b89100",5087:"f355ac6c",5478:"50e7f874",5506:"364e68ca",5576:"cb9cecfd",5627:"5613c9ed",5892:"52eff6c9",6094:"e24bb847",6103:"ccc49370",6389:"a1a68211",6539:"4d262bef",6542:"27688537",6561:"44bbcc1c",6588:"8c15a673",6912:"16ebfebc",6917:"82c6c1dc",7258:"28a1442d",7414:"393be207",7417:"64223023",7447:"40b7e58f",7483:"a50e347c",7506:"9cee31f8",7671:"cf53798e",7915:"4a3a5cb1",7918:"17896441",8299:"78f2a083",8360:"d21ba92f",8368:"c6f47719",8388:"68c46c38",8610:"6875c492",9151:"d078d492",9347:"63441a2d",9499:"802c8227",9514:"1be78505",9518:"2f96067e",9562:"7cd378c7"}[e]||e)+"."+{53:"7e4b06a8",533:"b0a45e3e",626:"e512db79",657:"cb9fe74f",1196:"e4565ea7",1477:"f7c04ebd",1713:"94156c60",2258:"22325216",2274:"df5e98cd",2431:"f269ddc8",2535:"d0b43302",2857:"0db740ec",2929:"b6108c55",3045:"c575f7b2",3065:"edb06604",3085:"627baa95",3089:"b95e3896",3283:"c3a9c377",3316:"4b8d7a22",3537:"a5904f41",3608:"b79baad0",3751:"41eaf847",3804:"0d8b234e",3809:"611c8064",4013:"1bffd8b2",4121:"08078751",4195:"bb22baad",4541:"faf03b08",4608:"6643b6da",5069:"26edbaf5",5087:"f9820a6d",5256:"5c9ae4aa",5478:"e3090c17",5506:"e93326f8",5576:"c9bf62b6",5627:"967c5af6",5892:"a71dff21",6094:"1794caeb",6103:"7d7b9341",6159:"4cdfb506",6254:"b41f5763",6389:"6f97b350",6539:"6ca21062",6542:"a102f6e8",6561:"726eb4a2",6588:"b079d97e",6912:"0bb23cfa",6917:"86d69d9c",6945:"b10995d3",7258:"d13dc076",7414:"effafed3",7417:"14cbafc6",7447:"7ae9f69e",7483:"e2f6f8d4",7506:"ddee2d5a",7671:"f8223977",7915:"f787da07",7918:"9519ba81",8299:"44f390d7",8360:"d46b35a7",8368:"52a5fca2",8388:"4d7d326c",8610:"c8f1563a",9151:"d5b16957",9347:"c7997b89",9499:"6dd419ea",9514:"7bc792d8",9518:"4ed2a4c4",9562:"a7cc4966",9727:"abfea59d"}[e]+".js",d.miniCssF=e=>"assets/css/styles.4fb1788f.css",d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,c)=>Object.prototype.hasOwnProperty.call(e,c),a={},b="serenity-users-guide:",d.l=(e,c,f,t)=>{if(a[e])a[e].push(c);else{var r,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{r.onerror=r.onload=null,clearTimeout(l);var b=a[e];if(delete a[e],r.parentNode&&r.parentNode.removeChild(r),b&&b.forEach((e=>e(f))),c)return c(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:r}),12e4);r.onerror=u.bind(null,r.onerror),r.onload=u.bind(null,r.onload),o&&document.head.appendChild(r)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"7918",27688537:"6542",64223023:"7417","935f2afb":"53",b2b675dd:"533","9aeb17c1":"626","9855f4f4":"657",d8224fc8:"1196",b2f554cd:"1477",a7023ddc:"1713","7b7bf1f9":"2258","500cccec":"2274","814f3328":"2535","83b05699":"2857","9b0b478f":"2929",dfbef622:"3045","2e7f4390":"3065","1f391b9e":"3085",a6aa9e1f:"3089",b49e0726:"3283","4944066c":"3316","5c4f0d90":"3537","9e4087bc":"3608","3720c009":"3751","8753baeb":"3804","5cdba952":"3809","01a85c17":"4013","55960ee5":"4121",c4f5d8e4:"4195","2a7ee7b4":"4541",e9b89100:"5069",f355ac6c:"5087","50e7f874":"5478","364e68ca":"5506",cb9cecfd:"5576","5613c9ed":"5627","52eff6c9":"5892",e24bb847:"6094",ccc49370:"6103",a1a68211:"6389","4d262bef":"6539","44bbcc1c":"6561","8c15a673":"6588","16ebfebc":"6912","82c6c1dc":"6917","28a1442d":"7258","393be207":"7414","40b7e58f":"7447",a50e347c:"7483","9cee31f8":"7506",cf53798e:"7671","4a3a5cb1":"7915","78f2a083":"8299",d21ba92f:"8360",c6f47719:"8368","68c46c38":"8388","6875c492":"8610",d078d492:"9151","63441a2d":"9347","802c8227":"9499","1be78505":"9514","2f96067e":"9518","7cd378c7":"9562"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(c,f)=>{var a=d.o(e,c)?e[c]:void 0;if(0!==a)if(a)f.push(a[2]);else if(/^(1303|532)$/.test(c))e[c]=0;else{var b=new Promise(((f,b)=>a=e[c]=[f,b]));f.push(a[2]=b);var t=d.p+d.u(c),r=new Error;d.l(t,(f=>{if(d.o(e,c)&&(0!==(a=e[c])&&(e[c]=void 0),a)){var b=f&&("load"===f.type?"missing":f.type),t=f&&f.target&&f.target.src;r.message="Loading chunk "+c+" failed.\n("+b+": "+t+")",r.name="ChunkLoadError",r.type=b,r.request=t,a[1](r)}}),"chunk-"+c,c)}},d.O.j=c=>0===e[c];var c=(c,f)=>{var a,b,t=f[0],r=f[1],o=f[2],n=0;if(t.some((c=>0!==e[c]))){for(a in r)d.o(r,a)&&(d.m[a]=r[a]);if(o)var i=o(d)}for(c&&c(f);n Blog | Serenity BDD Users Manual - + @@ -23,7 +23,7 @@ prefs { default_content_settings.popups = 0, default_content_settings.geolocation = 2, credentials_enable_service = false, password_manager_enabled = false } excludeSwitches = ["enable-automation","load-extension"], } timeouts { implicit = 15000 pageLoad = 300000 } } wait.for.timeout = 20000 }

ยท 2 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.4.2.

ยท 6 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.1.0.

- + \ No newline at end of file diff --git a/blog/2023/02/02/index.html b/blog/2023/02/02/index.html index 7bba3f3..fd1d41d 100644 --- a/blog/2023/02/02/index.html +++ b/blog/2023/02/02/index.html @@ -7,7 +7,7 @@ How To Configure Chrome In Serenity BDD | Serenity BDD Users Manual - + @@ -23,7 +23,7 @@ prefs { default_content_settings.popups = 0, default_content_settings.geolocation = 2, credentials_enable_service = false, password_manager_enabled = false } excludeSwitches = ["enable-automation","load-extension"], } timeouts { implicit = 15000 pageLoad = 300000 } } wait.for.timeout = 20000 } - + \ No newline at end of file diff --git a/blog/archive.html b/blog/archive.html index f08be93..0860689 100644 --- a/blog/archive.html +++ b/blog/archive.html @@ -7,13 +7,13 @@ Archive | Serenity BDD Users Manual - + - + \ No newline at end of file diff --git a/blog/serenity-3.4.1-release.html b/blog/serenity-3.4.1-release.html index 4850b2f..aad65cb 100644 --- a/blog/serenity-3.4.1-release.html +++ b/blog/serenity-3.4.1-release.html @@ -7,13 +7,13 @@ Serenity 3.4.1 Is Out! | Serenity BDD Users Manual - +

Serenity 3.4.1 Is Out!

ยท 2 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.4.2.

Selenium 4.6.0 Integration#

Serenity 3.4.2 integrates with Selenium 4.6.0, which includes a number of new features. One of the more interesting is it's ability to automatically download the correct driver binaries for whatever browser you are using. Serenity currently does this using WebDriverManager, but as this feature is now build into Selenium, the Serenity WebDriverManager integration is now disabled by default and will be removed in a future version.

Improved Reporting For Data-Driven Tests#

Test results for data-driven tests (parameterized tests in JUnit and Scenario Outlines in Cucumber) are now reported individually, giving a more precise view of the test status:

Standardised naming#

To avoid confusion in the summary views, the reports now adopt a more conventional definition of scenarios and test cases for data-driven tests. Scenario refers to the scenario outline or overall test, whereas Test Case refers to a specific execution of a scenario with a specific set of test data.

Want to learn more?#

There are several courses on Serenity BDD in the Serenity Dojo Training Library, including

- + \ No newline at end of file diff --git a/blog/tags.html b/blog/tags.html index 98025a4..bee5fad 100644 --- a/blog/tags.html +++ b/blog/tags.html @@ -7,13 +7,13 @@ Tags | Serenity BDD Users Manual - + - + \ No newline at end of file diff --git a/blog/tags/locatorless-elements.html b/blog/tags/locatorless-elements.html index 280579d..0c0f68f 100644 --- a/blog/tags/locatorless-elements.html +++ b/blog/tags/locatorless-elements.html @@ -7,13 +7,13 @@ 2 posts tagged with "locatorless-elements" | Serenity BDD Users Manual - +

2 posts tagged with "locatorless-elements"

View All Tags

ยท 2 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.4.2.

ยท 6 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.1.0.

- + \ No newline at end of file diff --git a/blog/tags/reporting.html b/blog/tags/reporting.html index 379ab11..92d575c 100644 --- a/blog/tags/reporting.html +++ b/blog/tags/reporting.html @@ -7,13 +7,13 @@ 2 posts tagged with "reporting" | Serenity BDD Users Manual - +

2 posts tagged with "reporting"

View All Tags

ยท 2 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.4.2.

ยท 6 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.1.0.

- + \ No newline at end of file diff --git a/blog/tags/selenium-4.html b/blog/tags/selenium-4.html index 3bb9852..c7be119 100644 --- a/blog/tags/selenium-4.html +++ b/blog/tags/selenium-4.html @@ -7,13 +7,13 @@ 2 posts tagged with "selenium-4" | Serenity BDD Users Manual - +

2 posts tagged with "selenium-4"

View All Tags

ยท 2 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.4.2.

ยท 6 min read
John Ferguson Smart

Serenity BDD is one of the most popular Java test automation libraries, and for good reason!

If you are writing automated web tests in Java, using Serenity BDD correctly can reduce the amount of code you need to write by well over 50%, slashing the amount of code you need to maintain yourself. Serenity BDD produces powerful test reports that you can use both as as evidence of your testing activities and documentation of your application. And with over a million downloads a month, regular releases and a vibrant open source community, it's a solid bet for your test automation framework!

In this article, we look at some of the new features in Serenity BDD version 3.1.0.

- + \ No newline at end of file diff --git a/blog/whats-new-in-serenity-3.1.0.html b/blog/whats-new-in-serenity-3.1.0.html index 96dd330..1d8db9e 100644 --- a/blog/whats-new-in-serenity-3.1.0.html +++ b/blog/whats-new-in-serenity-3.1.0.html @@ -7,7 +7,7 @@ What's New In Serenity 3.1.0 | Serenity BDD Users Manual - + @@ -25,7 +25,7 @@ @Managed(options = "headless") WebDriver driver; @CastMember Actor charles; @ParameterizedTest(name = "{index}: {2}") @CsvSource(value = { " ,secret_sauce , Username is required", "standard_user , , Password is required", " , , Username is required", "standard_user , wrong_password , Username and password do not match any user in this service", "wrong_user , secret_sauce , Username and password do not match any user in this service", }) public void withInvalidCredentials(String username, String password, String errorMessage) { charles.attemptsTo( Login.withCredentials(username, password), Ensure.that(LoginForm.ERROR_MESSAGE).text().contains(errorMessage) ); }}

Want to learn more?#

There are several courses on Serenity BDD in the Serenity Dojo Training Library, including

- + \ No newline at end of file diff --git a/docs/cloud/bitbar.html b/docs/cloud/bitbar.html index 262dd9f..7ad2fd2 100644 --- a/docs/cloud/bitbar.html +++ b/docs/cloud/bitbar.html @@ -7,13 +7,13 @@ BitBar | Serenity BDD Users Manual - +

Serenity BDD BitBar Integration

BitBar is the cloud for all your testing needs. With BitBar, Serenity users have instant access to scale their cross-browser tests to real iOS and Android devices, as well as the latest and most popular browsers on macOS, Windows, and Linux.

The serenity-bitbar plugin ensures seamless integration with the BitBar online test automation platform.

Adding the BitBar plugin#

To add the integrated support for BitBar to your project, add the serenity-bitbar dependency to your project dependencies as follows:

  • for Maven
<dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-bitbar</artifactId>    <version>${serenity.version}</version></dependency>
  • for Gradle:
testImplementation "net.serenity-bdd:serenity-bitbar:${serenityVersion}"

Specifying your BitBar credentials and grid URL#

Next, you need a BitBar account.

You can add your BitBar credentials in two ways:

  • Define the following system property

BITBAR_API_KEY - BitBar API Key

  • Define your API Key using the bitbar.apiKey property in your serenity.conf file
bitbar.apiKey=XXXXXXXX

Configuring the BitBar driver#

Serenity interacts with BitBar via the RemoteDriver driver. You need to specify the remote URL for the geographical region you want to use in the webdriver.remote.url property as follows:

webdriver {  driver = remote  remote.url = "https://eu-mobile-hub.bitbar.com/wd/hub"}

Alternatively, you can define a hub and the remote.url will be set automatically:

bitbar.hub = "eu-desktop-hub"

Activating the BitBar plugin#

The Serenity BitBar plugin is invoked if Serenity finds a bitbar:options section in your serenity.conf file, or if you specify a remote.webdriver.url that points to a BitBar server. If you have no BitBar-specific capabilities, simply set the bitbar.active property to true as follows:

bitbar {  active = true}

Defining BitBar Capabilities#

You can specify the operating system and browser on which you want to run your tests by customizing the capabilities in your serenity.conf file. Do this in the bitbar:options section of the serenity.conf file, for example:

webdriver {  driver = "remote"  capabilities {    browserName = "chrome"    version = "latest"    platform = "Windows"    "bitbar:options" {      osVersion = "10"      screenResolution = "1920x1200"    }  }}
- + \ No newline at end of file diff --git a/docs/cloud/browserstack.html b/docs/cloud/browserstack.html index 40625a5..96106fc 100644 --- a/docs/cloud/browserstack.html +++ b/docs/cloud/browserstack.html @@ -7,13 +7,13 @@ BrowserStack | Serenity BDD Users Manual - +

Introduction

Browserstack is an online platform that allows you to run cross-browser tests in parallel at scale. In this section, we will see how it integrates with Serenity.

Adding the Browserstack plugin to your project#

Serenity comes with a dedicated BrowserStack plugin that makes it much easier to run your tests on this platform. To use it, first add the serenity-browserstack dependency to your project. In Maven, that would look like the following:

        <dependency>            <groupId>net.serenity-bdd</groupId>            <artifactId>serenity-browserstack</artifactId>            <version>${serenity.version}</version>        </dependency>

Or in Gradle:

    testImplementation "net.serenity-bdd:serenity-browserstack:${serenityVersion}"

Specifying your BrowserStack credentials and grid URL#

Next, you will need a BrowserStack account.

You can add your BrowserStack credentials in two ways. The simplest is to define the following system properties:

  • BROWSERSTACK_USER - BrowserStack user name
  • BROWSERSTACK_KEY- BrowserStack access key

Alternatively, you can define your username and accesskey using the browserstack.user and browserstack.key properties respectively in your serenity.conf file:

browserstack.user=myuserbrowserstack.key=XXXXXXXX

Configuring the BrowserStack driver#

Serenity interacts with BrowserStack via the RemoteDriver driver. You can specify the remote URL explicitly, or let the serenity-browserstack library do it for you. For example, to configure the URL explicitly you could use a serenity.conf configuration like this:

webdriver {  driver = remote  remote.url =  "https://"${BROWSERSTACK_USER}":"${BROWSERSTACK_KEY}"@hub.browserstack.com/wd/hub"}

If the webdriver.remote.url property is not defined, Serenity will use these values to build one for you if the BrowserStack plugin is active (see below).

Defining BrowserStack Capabilities#

You can specify the operating system and browser you want to run your tests on by customising the Selenium Capabilities in your serenity.conf file. You do this in the "bstack:options" section of the serenity.conf file, e.g.

webdriver {  driver = "remote"  capabilities {    browserName = "Chrome"    #    # Any BrowserStack-specific options go in the 'bstack:options' section    #    "bstack:options" {      os = "Windows"      osVersion = "11"      browserVersion = "latest"      local = false      resolution = "1920x1200"      seleniumVersion = "4.6.0"      video = true      idleTimeout = 300 // Make sure to set this to a high number if running tests in parallel    }  }}

If you're running the tests in parallel, make sure to set the idleTimeout value to a high number (longer than the total duration of your tests). This will prevent the BrowserStack connection from timing out before it's updated with the test results.

- + \ No newline at end of file diff --git a/docs/cloud/lambdatest.html b/docs/cloud/lambdatest.html index 2c5b85d..c616ee1 100644 --- a/docs/cloud/lambdatest.html +++ b/docs/cloud/lambdatest.html @@ -7,14 +7,14 @@ LambdaTest | Serenity BDD Users Manual - +

Serenity BDD LambdaTest Integration

LambdaTest is a cloud platform for test execution and test orchestration. With LambdaTest, Serenity users can extend their automation test coverage of their web and mobile apps on 3000+ real devices, browsers, and operating systems.

The serenity-lambdatest plugin provides seamless integration with the LambdaTest online test automation platform.

Adding the LambdaTest plugin#

To add the integrated support for LambdaTest to your project, you will need to add the serenity-lambdatest dependency to your project dependencies. For Maven, you would add the following:

    <dependency>        <groupId>net.serenity-bdd</groupId>        <artifactId>serenity-lambdatest</artifactId>        <version>${serenity.version}</version>    </dependency>

And for Gradle:

    testImplementation "net.serenity-bdd:serenity-lambdatest:${serenityVersion}"

Specifying your LambdaTest credentials and grid URL#

Next, you will need a LambdaTest account (If you don't already have one you can set up a free lifetime account to experiment).

You can add your LambdaTest credentials in two ways. The simplest is to define the following system properties:

  • LT_USERNAME - LambdaTest user name
  • LT_ACCESS_KEY- LambdaTest access key

Alternatively, you can define your username and accesskey using the lt.user and lt.key properties respectively in your serenity.conf file:

lt.user=myuserlt.key=XXXXXXXX

By default the standard LambdaTest grid URL ("hub.lambdatest.com") will be used to connect to the LambdaTest servers, but you can override this by setting the lt.grid property:

lt.grid = "mycustomhub.lambdatest.com"

Configuring the LambdaTest driver#

Serenity interacts with LambdaTest via the RemoteDriver driver. You can specify the remote URL explicitly, or let the serenity-lambdatest library do it for you. For example, to configure the URL explicitly you could use a serenity.conf configuration like this:

webdriver {  driver = remote  remote.url = "https://"${LT_USERNAME}":"${LT_ACCESS_KEY}"@hub.lambdatest.com/wd/hub"}

If the webdriver.remote.url property is not defined, Serenity will use these values to build one for you if the LambdaTest plugin is active (see below).

Activating the LambdaTest plugin#

The Serenity LambdaTest plugin will be invoked if Serenity can find a "LT:Options" section in your serenity.conf file, or if you specify a remote.webdriver.url that points to a LambdaTest server. If you have no LambdaTest-specific capabilities, simply set the lambdatest.active property to true like this:

lambdatest {  active = true}

Defining LambdaTest Capabilities#

You can specify the operating system and browser you want to run your tests on by customising the Selenium Capabilities in your serenity.conf file. You do this in the "LT:Options" section of the serenity.conf file, e.g.

    webdriver {      driver = "remote"      capabilities {        browserName = "chrome"        version = "104.0"        platform = "Windows 10"        #        # Any LambdaTest-specific options go in the 'LT:Options' section        #        "LT:Options" {          resolution", "1280x800"          network = true // To enable network logs          visual = true // To enable step by step screenshot          video = true // To enable video recording          console = true // To capture console logs        }      }    }

Note that the w3c option will be set to true by default, as this is the default protocol for the Selenium version integrated with Serenity.

The LambdaTest test name will be assigned automatically. You can also set the build name by assigning the lambdatest.build property. For example the following example shows how to create a build name from the Jenkins job name and build number environment variables:

lambdatest {  build = "${JOB_NAME} - build ${BUILD_NUMBER}"}

These properties will be placed in the LT:Options capability.

tip

LambdaTest provides a convenient Capabilities Generator that gives an idea of what options are available.

- + \ No newline at end of file diff --git a/docs/cloud/saucelabs.html b/docs/cloud/saucelabs.html index 5241825..20bf378 100644 --- a/docs/cloud/saucelabs.html +++ b/docs/cloud/saucelabs.html @@ -7,13 +7,13 @@ SauceLabs | Serenity BDD Users Manual - +

Serenity BDD SauceLabs Integration

The serenity-saucelabs plugin provides seamless integration with the SauceLabs online test automation platform.

Adding the SauceLabs plugin#

To add the integrated support for SauceLabs to your project, you will need to add the serenity-saucelabs dependency to your project dependencies. For Maven, you would add the following:

    <dependency>        <groupId>net.serenity-bdd</groupId>        <artifactId>serenity-saucelabs</artifactId>        <version>${serenity.version}</version>    </dependency>

And for Gradle:

    testImplementation "net.serenity-bdd:serenity-saucelabs:${serenityVersion}"

Specifying your SauceLabs credentials and grid URL#

Next, you will need a SauceLabs account.

Next you will need to configure your SauceLabs credentials (if you are logged on to the Saucelabs Dashboard [you can find these on this page]. The simplest way to do this is to define the following system properties:

  • SAUCE_USERNAME- SauceLabs user name
  • SAUCE_ACCESS_KEY - SauceLabs access key

Alternatively, you can define your username and accesskey using the sauce.username and sauce.key properties respectively in your serenity.conf file:

sauce.username=myusersauce.key=XXXXXXXX

Configuring the SauceLabs driver#

Serenity interacts with SauceLabs via the RemoteDriver driver. You will need to specify the remote URL for the geographical region you want to use in the webdriver.remote.url property, like this:

webdriver {  driver = remote  remote.url = "https://ondemand.us-west-1.saucelabs.com/wd/hub"}

Activating the SauceLabs plugin#

The Serenity SauceLabs plugin will be invoked if Serenity can find a "sauce:options" section in your serenity.conf file, or if you specify a remote.webdriver.url that points to a SauceLabs server. If you have no Saucelabs-specific capabilities, simply set the sauce.active property to true like this:

sauce {  active = true}

Defining Saucelabs Capabilities#

You can specify the operating system and browser you want to run your tests on by customising the Selenium Capabilities in your serenity.conf file. You do this in the "sauce:options" section of the serenity.conf file, e.g.

    webdriver {      driver = "remote"      capabilities {        browserName = "chrome"        version = "104.0"        platform = "Windows 10"        "sauce:options" {          tags = ["smoketest","billing"]          recordVideo = true          recordLogs = false        }      }    }
- + \ No newline at end of file diff --git a/docs/cloud/selenium-grid.html b/docs/cloud/selenium-grid.html index 63088d0..ec29164 100644 --- a/docs/cloud/selenium-grid.html +++ b/docs/cloud/selenium-grid.html @@ -7,13 +7,13 @@ Selenium Grid | Serenity BDD Users Manual - +

Introduction

Selenium Grid allows the execution of WebDriver scripts on remote machines (virtual or real) by routing commands sent by the client to remote browser instances. It aims to provide an easy way to run tests in parallel on multiple machines.

Selenium Grid 4 takes advantage of a number of new technologies in order to facilitate scaling up while allowing local execution.

You can also use Serenity to run your WebDriver tests on a remote machine, such as a Selenium Grid or a remote service such as provided by BrowserStack or LambdaTest. This allows you to run your web tests against a variety of different browsers and operating systems, and also benefit from faster test execution when running the tests in parallel. We will look at how to do this in detail later on in the chapter.

Running Selenium Grid locally#

The simplest way to start with Selenium Grid is to run a standalone instance on your local machine. This allows you to make sure your Serenity configuration has been correctly set up to use the Selenim grid.

To try this own, download the latest selenium-server jar file from the Selenium website. Then start up the server with the following command:

java -jar selenium-server-<version>.jar standalone

This will start up the local instance of the Selenium Grid server. You can check out the dashboard on http://localhost:4444/ui.

You can configure your tests to run against this server by setting three properties:

  • Set the webdriver.driver property to remote
  • Set the webdriver.remote.url property to the address of your Selenium Grid instance (http://localhost:4444 by default)
  • Set the webdriver.remote.driver property to the name of the driver you want to run (e.g. "chrome")
webdriver {  driver = remote  remote {    url="http://localhost:4444"    driver=chrome  } }

You can also provide additional properties about the target browser or environment, including:

  • webdriver.remote.browser.version: What version of the remote browser to use
  • webdriver.remote.os: What operating system the tests should be run on.

For example, if you were running a Selenium Hub locally on port 4444 (the default) on a Windows machine, you could run the following command:

mvn verify -Dwebdriver.remote.url=http://localhost:4444/wd/hub -Dwebdriver.remote.driver=chrome -Dwebdriver.remote.os=WINDOWS

You can also pass the usual driver-specific capabilities to the remote browser, e.g.

mvn verify -Dwebdriver.remote.url=http://localhost:4444/wd/hub -Dwebdriver.remote.driver=chrome -Dwebdriver.remote.os=WINDOWS -Dchrome.switches="--no-sandbox,--ignore-certificate-errors,--homepage=about:blank,--no-first-run"
- + \ No newline at end of file diff --git a/docs/cloud/selenoid.html b/docs/cloud/selenoid.html index de52f26..7928884 100644 --- a/docs/cloud/selenoid.html +++ b/docs/cloud/selenoid.html @@ -7,7 +7,7 @@ selenoid | Serenity BDD Users Manual - + @@ -25,7 +25,7 @@

If you use serenity.properties:


 selenoid.options.videoLinkPrefix=https://s3.amazonaws.com/my-bucket
 
- + \ No newline at end of file diff --git a/docs/guide/cucumber.html b/docs/guide/cucumber.html index 130ddff..89b2a78 100644 --- a/docs/guide/cucumber.html +++ b/docs/guide/cucumber.html @@ -6,15 +6,14 @@ -Running Cucumber scenarios with Serenity | Serenity BDD Users Manual - +Running Cucumber scenarios with Serenity | Serenity BDD Users Manual +
-

Running Cucumber scenarios with Serenity

To run Cucumber scenarios with Serenity, you need to create a Junit 4 test runner class and use @RunWith annotation in with the CucumberWithSerenity class, like this:

import io.cucumber.junit.CucumberOptions;import net.serenitybdd.cucumber.CucumberWithSerenity;import org.junit.runner.RunWith;
-@RunWith(CucumberWithSerenity.class)@CucumberOptions(        plugin = {"pretty"},        features = "src/test/resources/features")public class AcceptanceTestSuite {}

Note that you need to specify at least the features attribute, to define the directory containing your feature files.

Feature hierarchies

Serenity expects to find feature files in the src/test/resources/features folder by default. You can organise your feature files in a hierarchy of folders underneath this one, as shown here:

+ src|-- test|   |-- resources|   |  |-- features|   |  |   |-- authentication|   |  |   |   |-- login.feature|   |  |   |-- cart|   |  |   |   |-- managing_the_cart.feature|   |  |   |-- catalog|   |  |   |   |-- browse_catalog.feature|   |  |   |   |-- filtering_products.feature|   |  |   |-- purchases|   |  |   |   |-- completing_a_purchase.feature|   |  |   |-- sales_tax|   |  |   |   |-- calculating_sales_tax.feature

The directory structure will be used to build the Serenity requirements hierarchy, like the one shown here:

Filtering test execution in Cucumber

The simplest way to control which scenarios you want to execute is to use tags and the cucumber.filter.tags command line option. For example, to run only scenarios or features annotated with @smoke, you would run the following command:

mvn clean verify -Dcucumber.filter.tags="@smoke"

You can use Cucumber Tag Expressions to determine which scenarios to run. For example, to run only features with both the @authentication tag and the @smoke tag, you would run the following:

 mvn clean verify -Dcucumber.filter.tags="@authentication and @smoke"

To run scenarios with either the @cart or the @catalog tag, you could run the following:

 mvn clean verify -Dcucumber.filter.tags="@cart or @catalog"

Running Cucumber scenarios with Serenity in parallel

Starting with version 3.6.0, is possible to run the Cucumber scenarios in parallel.

The following steps are necessary to activate the parallel execution:

  1. Add following dependencies in your application pom.xml:
    <dependency>        <groupId>io.cucumber</groupId>        <artifactId>cucumber-junit-platform-engine</artifactId>        <version>7.11.0</version>        <scope>test</scope>    </dependency>        <dependency>        <groupId>org.junit.platform</groupId>        <artifactId>junit-platform-suite</artifactId>        <version>1.9.2</version>        <scope>test</scope>    </dependency>
  1. Create a file named junit-platform.properties under test/resources
cucumber.execution.parallel.enabled=truecucumber.execution.parallel.config.strategy=fixedcucumber.execution.parallel.config.fixed.parallelism=4cucumber.execution.parallel.config.fixed.max-pool-size=4cucumber.plugin=io.cucumber.core.plugin.SerenityReporterParallel

More informations about the meaning of the properties can be found in Cucumber JUnit Platform Engine Documentation

  1. Configure the classpath location of the scenarios to be executed in a Java class placed in a package under test/java
   import org.junit.platform.suite.api.IncludeEngines;   import org.junit.platform.suite.api.SelectClasspathResource;   import org.junit.platform.suite.api.Suite;      @Suite   @IncludeEngines("cucumber")   @SelectClasspathResource("/features")   public class CucumberTestSuite {}
- +

Running Cucumber scenarios with Serenity

To run Cucumber scenarios with Serenity, you need to create a Junit 5 test runner class like this:

   import org.junit.platform.suite.api.IncludeEngines;   import org.junit.platform.suite.api.SelectClasspathResource;   import org.junit.platform.suite.api.Suite;      @Suite   @IncludeEngines("cucumber")   @SelectClasspathResource("/features")   public class CucumberTestSuite {}

Note that you need to specify at least the features attribute, to define the directory containing your feature files.

Feature hierarchies

Serenity expects to find feature files in the src/test/resources/features folder by default. You can organise your feature files in a hierarchy of folders underneath this one, as shown here:

+ src|-- test|   |-- resources|   |  |-- features|   |  |   |-- authentication|   |  |   |   |-- login.feature|   |  |   |-- cart|   |  |   |   |-- managing_the_cart.feature|   |  |   |-- catalog|   |  |   |   |-- browse_catalog.feature|   |  |   |   |-- filtering_products.feature|   |  |   |-- purchases|   |  |   |   |-- completing_a_purchase.feature|   |  |   |-- sales_tax|   |  |   |   |-- calculating_sales_tax.feature

The directory structure will be used to build the Serenity requirements hierarchy, like the one shown here:

Filtering test execution in Cucumber

The simplest way to control which scenarios you want to execute is to use tags and the cucumber.filter.tags command line option. For example, to run only scenarios or features annotated with @smoke, you would run the following command:

mvn clean verify -Dcucumber.filter.tags="@smoke"

You can use Cucumber Tag Expressions to determine which scenarios to run. For example, to run only features with both the @authentication tag and the @smoke tag, you would run the following:

 mvn clean verify -Dcucumber.filter.tags="@authentication and @smoke"

To run scenarios with either the @cart or the @catalog tag, you could run the following:

 mvn clean verify -Dcucumber.filter.tags="@cart or @catalog"

Running Cucumber scenarios with Serenity in parallel

Starting with version 3.6.0, is possible to run the Cucumber scenarios in parallel.

The following steps are necessary to activate the parallel execution:

  1. Add following dependencies in your application pom.xml:
    <dependency>        <groupId>io.cucumber</groupId>        <artifactId>cucumber-junit-platform-engine</artifactId>        <version>7.11.0</version>        <scope>test</scope>    </dependency>        <dependency>        <groupId>org.junit.platform</groupId>        <artifactId>junit-platform-suite</artifactId>        <version>1.9.2</version>        <scope>test</scope>    </dependency>
  1. Create a file named junit-platform.properties under test/resources
cucumber.execution.parallel.enabled=truecucumber.execution.parallel.config.strategy=fixedcucumber.execution.parallel.config.fixed.parallelism=4cucumber.execution.parallel.config.fixed.max-pool-size=4cucumber.plugin=io.cucumber.core.plugin.SerenityReporterParallel

More informations about the meaning of the properties can be found in Cucumber JUnit Platform Engine Documentation

  1. Configure the classpath location of the scenarios to be executed in a Java class placed in a package under test/java
   import org.junit.platform.suite.api.IncludeEngines;   import org.junit.platform.suite.api.SelectClasspathResource;   import org.junit.platform.suite.api.Suite;      @Suite   @IncludeEngines("cucumber")   @SelectClasspathResource("/features")   public class CucumberTestSuite {}
+ \ No newline at end of file diff --git a/docs/guide/driver_config.html b/docs/guide/driver_config.html index b8c2f8b..148c426 100644 --- a/docs/guide/driver_config.html +++ b/docs/guide/driver_config.html @@ -7,7 +7,7 @@ Configuring Selenium WebDriver | Serenity BDD Users Manual - + @@ -18,7 +18,7 @@ timeouts { implicit = 1000 script = 1000 pageLoad = 1000 } pageLoadStrategy = "normal" acceptInsecureCerts = true unhandledPromptBehavior = "dismiss" strictFileInteractability = true "moz:firefoxOptions" { args = ["-headless"], prefs { "javascript.options.showInConsole": false }, log {"level": "info"}, } }}

Configuring multiple environments

You can configure multiple driver configurations by using the environments section, as shown below. Then simply set the environment system property to the corresponding environment to use these settings, e.g.

mvn clean verify -Denvironment=chrome

A sample environments section is shown here:

environments {  chrome {    webdriver {      driver = chrome      autodownload = true      capabilities {        browserName = "chrome"        acceptInsecureCerts = true        "goog:chromeOptions" {          args = ["test-type", "ignore-certificate-errors", "headless", "--window-size=1000,800"            "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking"]        }      }    }  }  edge {    webdriver {      capabilities {        browserName = "MicrosoftEdge"        "ms:edgeOptions" {          args = ["test-type", "ignore-certificate-errors", "headless",            "incognito", "disable-infobars", "disable-gpu", "disable-default-apps", "disable-popup-blocking"]        }      }    }  }  firefox {    webdriver {      capabilities {        browserName = "firefox"        pageLoadStrategy = "normal"        acceptInsecureCerts = true        unhandledPromptBehavior = "dismiss"        strictFileInteractability = true
         "moz:firefoxOptions" {          args = ["-headless"],          prefs {            "javascript.options.showInConsole": false          },          log {"level": "info"},        }      }    }  }}
- + \ No newline at end of file diff --git a/docs/guide/getting_started.html b/docs/guide/getting_started.html index c6ad8c6..b712894 100644 --- a/docs/guide/getting_started.html +++ b/docs/guide/getting_started.html @@ -7,13 +7,13 @@ Creating A New Project | Serenity BDD Users Manual - +

Getting Started

Creating A New Project With The Serenity BDD Templates#

The quickest way to get started with a Serenity BDD project is to use one of the starter projects. These are template projects available on Github, that contain a basic Serenity BDD skeleton project and a single test implementation. These template projects are kept up-to-date with the most recent stable version of Serenity BDD.

The main available starter projects are the following:

TemplateDescriptionGet Started
Serenity BDD with JUnitA simple project structure using Serenity BDD, JUnit 5 and an Action Classes/Page Objects architecture.Use This Template
Serenity BDD with JUnit and ScreenplayA project built around the Screenplay Pattern using Serenity BDD, JUnit 5 and Serenity ScreenplayUse This Template
Serenity BDD with Cucumber and ScreenplayA BDD-style test suite using Cucumber and Serenity ScreenplayUse This Template

To create a new project, go to the project template you want to use, and click on the "Use this template" button. This will allow you to create a new project in your own Github repository.

If you are working on an internal project, you can also download the template project by clicking on the "Code" button.

- + \ No newline at end of file diff --git a/docs/guide/maven.html b/docs/guide/maven.html index 9cdd827..a5eba35 100644 --- a/docs/guide/maven.html +++ b/docs/guide/maven.html @@ -7,13 +7,13 @@ Using Maven with Serenity | Serenity BDD Users Manual - +

Integrating Serenity BDD into a Maven project

Maven is the recommended build tool for Serenity BDD.

You can add Serenity BDD to an existing Maven project by adding the corresponding dependencies to your pom.xml file. All Serenity BDD projects need the following core dependency:

<dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-core</artifactId>    <version>${serenity.version}</version>    <scope>test</scope></dependency>

You will also need a test runner, which will usually be either JUnit 4, JUnit 5 or Cucumber.

Serenity JUnit 4 Dependencies#

To use JUnit 4 you will need the following dependency:

<dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-junit</artifactId>    <version>${serenity.version}</version>    <scope>test</scope></dependency>

Serenity JUnit 5 Dependencies#

To use JUnit 5 you will need the following dependency:

<dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-junit5</artifactId>    <version>${serenity.version}</version>    <scope>test</scope></dependency>

You will also need the JUnit 5 dependencies, e.g.

<dependency>    <groupId>org.junit.jupiter</groupId>    <artifactId>junit-jupiter-api</artifactId>    <version>${junit5.version}</version>    <scope>test</scope></dependency><dependency>    <groupId>org.junit.jupiter</groupId>    <artifactId>junit-jupiter-engine</artifactId>    <version>${junit5.version}</version>    <scope>test</scope></dependency>

Serenity Cucumber Dependencies#

For Cucumber you will need the following dependency:

<dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-cucumber</artifactId>    <version>${serenity.version}</version>    <scope>test</scope></dependency>

Since Serenity relies on a specific version of the Cucumber APIs, we recommend using the same version of the Cucumber libraries.

Cucumber requires a test runner, either JUnit 4 or JUnit 5.

Cucumber with JUnit 4 Dependencies#

To use JUnit 4 you will need the following dependency:

<dependency>    <groupId>io.cucumber</groupId>    <artifactId>cucumber-junit</artifactId>    <version>${cucumber.version}</version>    <scope>test</scope></dependency><dependency>    <groupId>org.junit.platform</groupId>    <artifactId>junit-vintage-engine</artifactId>    <version>${junit5.version}</version>    <scope>test</scope></dependency>

Cucumber with JUnit 5 Dependencies#

To use JUnit 5 you will need the following dependency:

<dependency>    <groupId>io.cucumber</groupId>    <artifactId>cucumber-junit-platform-engine</artifactId>    <version>${cucumber.version}</version>    <scope>test</scope></dependency><dependency>    <groupId>org.junit.platform</groupId>    <artifactId>junit-platform-suite</artifactId>    <version>${junit-platform.version}</version>    <scope>test</scope></dependency>

See cucumber-junit-platform-engine documentation on using junit-platform-suite to pilot cucumber: https://github.com/cucumber/cucumber-jvm/tree/main/junit-platform-engine#suites-with-different-configurations, and https://github.com/serenity-bdd/serenity-cucumber-starter for a running example.

Screenplay#

If you are using the Screenplay pattern, you will also need the Screenplay dependencies:

<dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-screenplay</artifactId>    <version>${serenity.version}</version>    <scope>test</scope></dependency><dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-rest-assured</artifactId>    <version>${serenity.version}</version></dependency><dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-ensure</artifactId>    <version>${serenity.version}</version>    <scope>test</scope></dependency><dependency>    <groupId>net.serenity-bdd</groupId>    <artifactId>serenity-screenplay-webdriver</artifactId>    <version>${serenity.version}</version>    <scope>test</scope></dependency>

The Serenity Maven Plugin#

If you want to generate the Serenity reports whenever you run mvn verify, you can use the serenity-maven-plugin to do that:

<plugin>    <groupId>net.serenity-bdd.maven.plugins</groupId>    <artifactId>serenity-maven-plugin</artifactId>    <version>${serenity.version}</version>    <configuration>      <tags>${tags}</tags>    </configuration>    <executions>        <execution>            <id>serenity-reports</id>            <phase>post-integration-test</phase>            <goals>                <goal>aggregate</goal>                <goal>check</goal>            </goals>        </execution>    </executions></plugin>

By default, the aggregate goal will NOT fail the build if there are test failures - it will simply generate the reports. This way you can aggregate multiple report sets and then check for failures at the end using mvn serenity:check.

Checking Gherkin feature files#

Some errors in Gherkin feature files can cause the Serenity reports to behave unpredictably. For this reason, the following rules should be followed when working with Cucumber and Serenity:

  • Scenario names should be unique within a feature file

  • Scenario, Rule and Feature names should not be blank

  • Feature names should be unique wherever possible. In particular features with the same name, inside directories with identical names, will not appear correctly in the Serenity reports.

    You can check these rules before you run the full test by calling the check-gherkin goal, e.g.

mvn serenity:check-gherkin  

You can ensure that your feature files are correctly configured before kicking off your tests by binding the check-gherkin goal to the process-test-resources lifecycle phase, as shown here:

<plugin>    <groupId>net.serenity-bdd.maven.plugins</groupId>    <artifactId>serenity-maven-plugin</artifactId>    <version>${serenity.version}</version>    <configuration>      <tags>${tags}</tags>    </configuration>    <executions>        <execution>            <id>check-feature-files</id>            <phase>process-test-resources</phase>            <goals>                <goal>check-gherkin</goal>            </goals>        </execution>        <execution>            <id>serenity-reports</id>            <phase>post-integration-test</phase>            <goals>                <goal>aggregate</goal>            </goals>        </execution>    </executions></plugin>
- + \ No newline at end of file diff --git a/docs/guide/page_elements.html b/docs/guide/page_elements.html index 8bef221..f79aa0f 100644 --- a/docs/guide/page_elements.html +++ b/docs/guide/page_elements.html @@ -7,7 +7,7 @@ Serenity Page Elements | Serenity BDD Users Manual - + @@ -16,7 +16,7 @@ Serenity BDD provides a simpler way of interacting with common UI components, which can avoid needing to use XPath or CSS expressions.

For example, the following HTML code illustrates a few different ways to represent a button:

<button type="button" class="btn btn-primary">Login</button><input type="submit" value="Login">

In Serenity, we could interact with these using XPath or CSS, e.g.

$("css:input[value='Login']").click()

or

$("xpath://button[.='Login']").click()

However, if the UI implementation switched from one to another, the test would break.

Serenity Page Elements provide a more intuitive way to identify many common UI elements. Using Serenity Page Elements, we can use a more expression like this:

import net.serenitybdd.screenplay.ui.Button;...$(Button.withText("Login")).click();

Or for a Screenplay test, you could do the following:

actor.attemptsTo(    Click.on(Button.withText("Login")));

Under the hood, Serenity will look for either <button> elements, or <input> elements of type submit, that display the "Login" text.

Another common location strategy is to use attributes like id or name, or test-specific attributes like data-test.

Suppose we have the following HTML code:

<button type="button" class="btn btn-primary" data-test="login-button">Login</button>

We could click on this button with the following code:

$(Button.withNameOrId("login-button")).click();

Or in Screenplay, we could do the following:

actor.attemptsTo(    Click.on(Button.withNameOrId("login-button")));

In this case, Serenity will look for <button> elements, or <input> elements of type submit, with a value, id, data-test or aria-label attribute of "login-button".

This means that, in many cases, you can use the Button class directly in your code, without having to inspect the page structure first.

Serenity Page Elements are found in the serenity-screenplay-webdriver module, but they can be used in both Screenplay and Action Class-based tests.

There are many different types of page elements available. All of them have the withNameOrId() method, but some have other methods for more specific locator strategies, such as withLabel() for checkboxes.

The following table gives an overview of the different types of PageElement available:

Element typeExample
ButtonsButton.withText("A Button")
CheckboxesCheckbox.withValue("Ferrari")
DropdownsDropdown.withLabel("---Pick Your Car---")
ImagesImage.withAltText("Girl in a jacket")
Input FieldsInputField.withPlaceholder("Enter the customer name")
LinkLink.withIcon("glyphicon-cloud")
PageElementPageElement.locatedBy(".item").containingText("Item 1")
RadioButtonRadioButton.withNameOrId("red-button")

Let's look at each type of page element in more detail.

Buttons#

The Button page element locates a <button> element with a specific tect, or an <input> element of type submit with a specific value.

Suppose we have the following HTML code:

<button type="button">A Button</button><input type="submit" value="Submit Me!" name="submit-button" data-test="submit-the-button"><input type="button" value="Press Here"><button type="button"><i class="glyphicon glyphicon-home"></i>Home</button>

We could use the following expressions to identify these elements:

StrategyExample
By textButton.withText("A Button")
By valueButton.withText("Press Here")
By nameButton.withNameOrId("submit-button")
By data-test attributeButton.withNameOrId("submit-the-button")
By iconButton.withIcon("glyphicon-home")
tip

The withNameOrId() method will match the id, name, data-test or aria-label attribute for any kind of Page Element, so we won't always repeat them everywhere in the following sections.

Checkbox#

This element will match an <input> element of type "checkbox", with a specified value, data-test, or class attribute value.

Suppose we have the following HTML:

<input type="checkbox" id="vehicle1" value="Bike" class="vehicule-option"><label for="vehicle1"> I have a bike</label><br><input type="checkbox" id="vehicle2" value="Car" class="vehicule-option"><label for="vehicle2"> I have a car</label><br><input type="checkbox" id="vehicle3" value="Boat" class="vehicule-option" checked><label for="vehicle3"> I have a boat</label><br>

We could use the following expressions to identify these elements:

StrategyExample
By idCheckbox.withNameOrId("vehicle1")
By valueCheckbox.withValue("Bike")
By labelCheckbox.withLabel("I have a bike")

Dropdown#

The Dropdown page element lets us work with a <select> dropdown list. Suppose we had the following HTML:

<label for="cars">Choose a car:</label><select name="cars" id="cars">    <option value="">---Pick Your Car---</option>    <option value="volvo">Volvo</option>    <option value="saab">Saab</option>    <option value="mercedes">Mercedes</option>    <option value="audi">Audi</option></select>

We could use the following expressions to identify these elements:

StrategyExample
By name or idDropdown.withNameOrId("cars")
By labelDropdown.withLabel("Choose a car:")
By default optionDropdown.withLabel("---Pick Your Car---")

Image#

The Image page element lets us interact with <img> elements. For example, suppose we had the following HTML code:

<img src="img_girl.jpg" alt="Girl in a jacket" width="500" height="600">

We could use the following expressions to identify these elements:

StrategyExample
By alt textImage.withAltText("Girl in a jacket")
By srcImage.withSrc("img_girl.jpg")
By src (starting with)Image.withSrcStartingWith("img_")
By src (ending with)Image.withSrcEndingWith("girl.jpg")

InputField#

The InputField page element represents an <input> element in a form, with or without a <label>. For example, suppose we had the following HTML code:

<label for="customer_name">Customer Name</label><input type="text" id="customer_name" name="customername" placeholder="Enter the customer name" />

We could use the following expressions to identify these elements:

StrategyExample
By nameInputField.withNameOrId("customername")
By idInputField.withNameOrId("customer_name")
By placeholderInputField.withPlaceholder("Enter the customer name")
By labelInputField.withLabel("Customer Name")

Link#

The Link page element interacts with HTML <a> elements. For example, suppose we have the following HTML code:

<!-- A simple link ---><a href="...">Link 1</a><br/><!-- A link with a title --><a href="..." title="Link Number 2">Link 2</a><br/><!-- A link with an icon and a text--><a href="#" onclick="update('Link 3')"><i class="glyphicon glyphicon-cloud"></i>Link 3</a><br/>

We could use the following expressions to identify these elements:

StrategyExample
By link textLink.withText("Link 1")
By link titleLink.withTitle("Link Number 2")
By partial link textLink.containing("ink")
By starting textLink.startingWith("Link")
By iconLink.withIcon("glyphicon-cloud")

PageElement#

The PageElement page element represents any element on a page. For example, suppose we have the following HTML code:

<div id="container" data-test="the-container" class="a-container">    <div class="item">        <h2>Item 1 heading</h2>        <div>            <span class="description">Item 1 description</span>        </div>    </div>    <div class="item">        <h2>Item 2 heading</h2>        <div>            <span class="description">Item 2 description</span>        </div>    </div></div>

We could use the following expressions to identify elements in this code:

StrategyExample
By idPageElement.withNameOrId("container")
By data-test valuePageElement.withNameOrId("the-container")
Containing a text valuePageElement.withNameOrId("item").containingText("Item 1")
Containing a text value (with a CSS locator)PageElement.locatedBy(".item").containingText("Item 1")

RadioButton#

The RadioButton page element represents a set of radio buttons. For example, suppose we have the following HTML code:

<input type="radio" id="html" name="fav_language" value="HTML" class="html-radio"><label for="html">Choose HTML</label><br><input type="radio" id="css" name="fav_language" value="CSS"><label for="css">Choose CSS</label><br><input type="radio" id="javascript" name="fav_language" value="JavaScript"><label for="javascript">Choose JavaScript</label><br><br>

We could use the following expressions to identify these elements:

StrategyExample
By idRadioButton.withNameOrId("html")
By labelRadioButton.withLabel("Choose CSS")
By valueRadioButton.withValue("JavaScript")

Using Page Elements in Action Classes

You can also use Page Elements in your normal (non-Screenplay) tests, simply by using the Page Element expression as a locator. For example:

public class LoginActions extends UIInteractionSteps {
     @Step("Login as a standard user")    public void asAStandardUser() {        $(InputField.withPlaceholder("Username")).type("standard_user");        $(InputField.withPlaceholder("Password")).type("secret_sauce");        $(Button.withText("Login")).click();    }}

Page Elements can be used with all of the usual methods for locating elements in a UI Interaction class, including:

MethodExample
$$(Button.withText("Login")).click();
findfind(Button.withText("Login")).click();
$$$$(Checkbox.withNameOrId("vehicle-option")).forEach(WebElementFacade::click);
findAllfindAll(Checkbox.withNameOrId("vehicle-option")).forEach(WebElementFacade::click);
- + \ No newline at end of file diff --git a/docs/guide/page_objects.html b/docs/guide/page_objects.html index 474a140..fef31dc 100644 --- a/docs/guide/page_objects.html +++ b/docs/guide/page_objects.html @@ -7,7 +7,7 @@ Interacting With Web Pages | Serenity BDD Users Manual - + @@ -80,7 +80,7 @@ Cookie cookie = new Cookie("testPassed", testOutcome.isFailure() || testOutcome.isError() || testOutcome.isCompromised() ? "false" : "true"); driver.manage().addCookie(cookie); }}

Driver Enhancers#

If you need to perform some action on the driver instance before each test, you can implement the CustomDriverEnhancer class. Note that this will be called immediately after the driver is created, and before any page is opened, so the number of actions is relatively limited.

Configuring the extension packages#

The last thing you need to do is to tell Serenity what package it needs to look for your extension classes. Add the package, or a parent package to your Serenity configuration using the serenity.extension.packages.

serenity.extension.packages=com.acme.myserenityextensions

You can find an example of how these classes are implemented in a real-world use case in the serenity-browserstack module on Github.

Custom WebDriver implementations#

You can add your own custom WebDriver provider by implementing the DriverSource interface. First, you need to set up the following system properties (e.g. in your serenity.properties file):

webdriver.driver = providedwebdriver.provided.type = mydriverwebdriver.provided.mydriver = com.acme.MyPhantomJSDriverthucydides.driver.capabilities = mydriver

Your custom driver must implement the DriverSource interface, as shown here:

public class MyPhantomJSDriver implements DriverSource {
     @Override    public WebDriver newDriver() {        try {            DesiredCapabilities capabilities = DesiredCapabilities.phantomjs();            // Add            return new PhantomJSDriver(ResolvingPhantomJSDriverService.createDefaultService(), capabilities);        }        catch (IOException e) {            throw new Error(e);        }    }
     @Override    public boolean takesScreenshots() {        return true;    }}

Note that if you use custom drivers you will be entirely responsible for configuring and instantiating the browser instance, and the driver-related Serenity configuration options will not apply. We generally recommend using custom drivers only for very exceptional circumstances, and using BeforeAWebdriverScenario classes for most custom configuration requirements.

Using the HasAuthentication interface#

Selenium 4 supports the HasAuthentication interface, which indicates that a driver supports authenticating to a website in some way. Serenity drivers integrate seemlessly with the HasAuthentication interface, so you can use it in the same way as you would in Selenium 4. For example, to register a username and password to use on all pages, you could add the following code before opening a site:

    getDriver().register(UsernameAndPassword.of("scott", "tiger")

If authentication is only required on certain pages, you can also use a predicate:

        Predicate<URI> onlyAuthenticateOnTheLoginPage = uri -> uri.getPath().endsWith("/login");        getDriver().register(onlyAuthenticateOnTheLoginPage, UsernameAndPassword.of("scott", "tiger"));
- + \ No newline at end of file diff --git a/docs/guide/step_libraries.html b/docs/guide/step_libraries.html index 3d6b4c5..c6eff6e 100644 --- a/docs/guide/step_libraries.html +++ b/docs/guide/step_libraries.html @@ -7,7 +7,7 @@ Step Libraries | Serenity BDD Users Manual - + @@ -47,7 +47,7 @@ @Step("#actor transfers {0} points to {1}") public void transfers_points(int points, TravellerEarningStatusPoints otherFrequentFlier) { // Left as an exercise } @Override public String toString() { return actor; } @Step("#actor should have {0} points") public void should_have_points(int expectedPoints) { // Left as an exercise }}

This approach uses the concept of persona step libraries, where a step library represents the actions of a specific user performing a specific task (Tracy the traveller who is earning points.) In this case, Serenity will automatically instantiate the actor field with the name of the step library variable (tracy), allowing it to appear in the test reports to make them more readable:

Shared Instances of Step Libraries#

There are some cases where we want to reuse the same step library instance in different places across a test. For example, suppose we have a step library that interacts with a backend API, and that maintains some internal state and caching to improve performance. We might want to reuse a single instance of this step library, rather than having a separate instance for each variable.

We can do this by declaring the step library to be shared, like this:

@Steps(shared = true)CustomerAPIStepLibrary customerAPI;

Now, any other step libraries of type CustomerAPIStepLibrary, that have the shared attribute set to true will refer to the same instance.

In older versions of Serenity, sharing instances was the default behaviour, and you used the uniqueInstance attribute to indicate that a step library should not be shared. If you need to force this behaviour for legacy test suites, set the step.creation.strategy property to legacy in your serenity.properties file:

step.creation.strategy = legacy
- + \ No newline at end of file diff --git a/docs/guide/user_guide_intro.html b/docs/guide/user_guide_intro.html index a1442cb..f0db5b8 100644 --- a/docs/guide/user_guide_intro.html +++ b/docs/guide/user_guide_intro.html @@ -7,13 +7,13 @@ Introduction | Serenity BDD Users Manual - +

Introduction

Serenity BDD is an open source library that aims to make the idea of living documentation a reality.

Serenity BDD helps you write cleaner and more maintainable automated acceptance and regression tests faster. Serenity also uses the test results to produce illustrated, narrative reports that document and describe what your application does and how it works. Serenity tells you not only what tests have been executed, but more importantly, what requirements have been tested.

One key advantage of using Serenity BDD is that you do not have to invest time in building and maintaining your own automation framework. Serenity BDD provides strong support for different types of automated acceptance testing, including:

  • Web testing with Selenium.
  • REST API testing with RestAssured.
  • Highly readable, maintainable and scalable automated testing with the Screenplay pattern.
  • BDD-style executable specifications with Cucumber

Serenity not only reports on what requirements were tested, it also reports on how they were tested. It includes step-by-step details of how a test played out, including optional screenshots, so your tests truly document what your application does.

But Serenity is not just about reporting. The underlying aim of Serenity is to make it easy to quickly write well-structured, maintainable automated acceptance criteria, using your favourite BDD or conventional testing library. You can work with Behaviour-Driven-Development tools like Cucumber, or simply use JUnit (4 or 5). You can integrate with requirements stored in an external source (such as JIRA or any other test cases management tool), or just use a simple directory-based approach to organise your requirements.

Serenity also provides a host of built-in features that make coding your test automation faster and more reliable. Testers working with Serenity typically report automating tests with less than half the code they would need for a conventional Selenium test.

info

Up until November 2014, Serenity went by the name of Thucydides. Thucydides was an Ancient Greek historian who wrote about the Peloponnesian War in the late 5th Century BCE. He was the first historian to write about events that he actually participated in, and in many cases, he wrote down the events that he directly witnessed.

In a similar way Serenity BDD not only reports on test outcomes, but also records and documents how each scenario plays out, giving a particularly rich form of test reporting and living documentation.

- + \ No newline at end of file diff --git a/docs/mobile/appium.html b/docs/mobile/appium.html index 1b57835..6518d88 100644 --- a/docs/mobile/appium.html +++ b/docs/mobile/appium.html @@ -7,13 +7,13 @@ Running Serenity Tests on Appium | Serenity BDD Users Manual - +

Running tests on Appium

Serenity supports running tests on mobile devices/emulators out of the box with Appium.

First, you will need to install Appium:

(sudo) npm install -g appium --chromedriver_version="102.0"

Afterwards Appium is available as command and can be started by invoking the following command:

appium

Then adapt serenity.properties to run on an Android device:

webdriver.driver= appiumwebdriver.base.url = http://www.google.com/appium.hub = http://127.0.0.1:4723/wd/hubappium.platformName = Androidappium.platformVersion = 5.1.1appium.deviceName = e2f5c460appium.browserName = Chrome

Here's an example for iOS:

webdriver.driver= appiumwebdriver.base.url = http://www.google.com/appium.hub = http://127.0.0.1:4723/wd/hubappium.platformName = iOSappium.platformVersion = 8.1appium.deviceName = iPhone 5appium.browserName = Safari

Note: All properties which are starting with appium in serenity.properties will be forwarded to appium driver.

For example, setting appium.automationName = XCUITest in serenity.properties will have as end effect setting the property automationName = XCUITest in appium driver capabilities.

Besides the properties file you can also use commandline switches:

mvn test -Dappium.hub=http://127.0.0.1:4723/wd/hub -Dwebdriver.driver=appium -Dappium.platformName=iOS -Dappium.browserName=Safari -Dappium.deviceName="iPhone 5"

All properties starting with appium.* will be forwarded to the appium driver as appium desired capabilities.

For example, setting the property appium.automationName=myAutomationName will have as effect setting the capability automationName in the appium driver to myAutomationName.

The following annotations are supported for a PageObject element:

@AndroidFindBy(id="")private WebElement loginButton;
@iOSFindBy(id="")private WebElement loginButton;
@FindBy(accessibilityId="")private WebElement loginButton;

Sometimes it may be necessary in a PageObject to use specific methods of the underlying driver:

AndroidDriver<AndroidElement> androidDriver() {    return (AndroidDriver<AndroidElement>)            ((WebDriverFacade) getDriver()).getProxiedDriver();}...androidDriver().hideKeyboard();

You can also add Appium to an existing grid. See the Appium documentation for more details about the node-config option.

- + \ No newline at end of file diff --git a/docs/reference/serenity-properties.html b/docs/reference/serenity-properties.html index f2d99f9..a9294fc 100644 --- a/docs/reference/serenity-properties.html +++ b/docs/reference/serenity-properties.html @@ -7,7 +7,7 @@ Serenity System Properties and Configuration | Serenity BDD Users Manual - + @@ -24,7 +24,7 @@ For alternative behaviour, you can set this value to DisplayedElementLocatorFactory, AjaxElementLocatorFactory or DefaultElementLocatorFactory.

chrome.switches#

Arguments to be passed to the Chrome driver, separated by semicolons. Example: chrome.switches = --incognito;--disable-download-notification

// FIXME link to Serenity.useFirefoxProfile()

webdriver.firefox.profile#

The path to the directory of the profile to use when starting firefox. This defaults to webdriver creating an anonymous profile. This is useful if you want to run the web tests using your own Firefox profile. If you are not sure about how to find the path to your profile, look here: http://support.mozilla.com/en-US/kb/Profiles. For example, to run the default profile on a Mac OS X system, you would do something like this:

$ mvn test -Dwebdriver.firefox.profile=/Users/johnsmart/Library/Application\ Support/Firefox/Profiles/2owb5g1d.default

On Windows, it would be something like:

C:\Projects\myproject>mvn test -Dwebdriver.firefox.profile=C:\Users\John Smart\AppData\Roaming\Mozilla\Firefox\Profiles\mvxjy48u.default

firefox.preferences#

A semicolon separated list of Firefox configuration settings. For ex.,

-Dfirefox.preferences="browser.download.folderList=2;browser.download.manager.showWhenStarting=false;browser.download.dir=c:\downloads"

Integer and boolean values will be converted to the corresponding types in the Firefox preferences; all other values will be treated as Strings. You can set a boolean value to true by simply specifying the property name, e.g. -Dfirefox.preferences=app.update.silent.

A complete reference to Firefox's configuration settings is given here.

serenity.csv.extra.columns#

Add extra columns to the CSV output, obtained from tag values.

serenity.console.headings#

Write the console headings using ascii-art ("ascii", default value) or in normal text ("normal")

tags#

"or" separated list of tags. If provided, only JUnit classes and/or methods with tags in this list will be executed. For example,

mvn verify -Dtags="iteration:I1"
 mvn verify -Dtags="color:red or flavor:strawberry"

output.formats#

What format should test results be generated in. By default, this is "json,xml".

narrative.format#

Set this property to 'asciidoc' to activate using http://www.methods.co.nz/asciidoc/[Asciidoc] format in narrative text.

jira.url#

If the base JIRA URL is defined, Serenity will build the issue tracker url using the standard JIRA form.

jira.project#

If defined, the JIRA project id will be prepended to issue numbers.

jira.username#

If defined, the JIRA username required to connect to JIRA.

jira.password#

If defined, the JIRA password required to connect to JIRA.

show.pie.charts#

Display the pie charts on the dashboard by default. If this is set to false, the pie charts will be initially hidden on the dashboard.

dashboard.tag.list#

If set, this will define the list of tag types to appear on the dashboard screens

dashboard.excluded.tag.list::If set, this will define the list of tag types to be excluded from the dashboard screens

json.pretty.printing#

Format the JSON test outcomes nicely. "true" or "false", turned off by default.

simplified.stack.traces#

Stack traces are by default decluttered for readability. For example, calls to instrumented code or internal test libraries is removed. This behaviour can be deactivated by setting this property to false.

serenity.dry.run#

Run through the steps without actually executing them.

feature.file,language#

What (human) language are the Cucumber feature files written in? Defaults to "en".

serenity.maintain.session#

Keep the Serenity BDD session data between tests. Normally, the session data is cleared between tests.

serenity.console.colors#

There is feature for colorful console output during executing serenity tests. To enable it you should provide variable serenity.console.colors = true, by default it is turned off. This feature can cause errors if it is enabled for builds under Jenkins.

Console color output is disabled

If this property equal to true you will find colorful output:

Console color output is enabled

serenity.include.actor.name.in.consequences#

Set to true to show actor names in the "then" steps. Especially useful when you have multiple actors in a test

Providing your own Firefox profile#

If you need to configure your own customized Firefox profile, you can do this by using the Serenity.useFirefoxProfile() method before you start your tests. For example:

@Beforepublic void setupProfile() {  FirefoxProfile myProfile = new FirefoxProfile();  myProfile.setPreference("network.proxy.socks_port",9999);  myProfile.setAlwaysLoadNoFocusLib(true);  myProfile.setEnableNativeEvents(true);  Serenity.useFirefoxProfile(myProfile);}
 @Testpublic void aTestUsingMyCustomProfile() {...}
- + \ No newline at end of file diff --git a/docs/reporting/additional_reports.html b/docs/reporting/additional_reports.html index 5c7bf27..391e92e 100644 --- a/docs/reporting/additional_reports.html +++ b/docs/reporting/additional_reports.html @@ -7,7 +7,7 @@ Additional Reports | Serenity BDD Users Manual - + @@ -21,7 +21,7 @@ In order to make my investments grow As a trader I want to be able to buy and sell shares to make a profit ...

You could tell Serenity to produce coverage for these tags by including the following line in your serenity.properties file:

report.tagtypes=department

When you generate the summary report, the results will be aggregated by each tag value (Marketing, Sales and Trading), as shown here:

Functional coverage can be configured by tags

Deep links#

You can include a link back to your Serenity report, and links to the individual scenario results, by setting the serenity.report.url property. You can do this in the serenity.properties file (if it is fixed), or pass it in from the command line (if you are pointing the the reports for a specific build, for example):

serenity.report.url=http://my.jenkins.server:8080/job/my-project/serenity-reports/
- + \ No newline at end of file diff --git a/docs/reporting/filtering_reports.html b/docs/reporting/filtering_reports.html index de0f1e3..d5c26cd 100644 --- a/docs/reporting/filtering_reports.html +++ b/docs/reporting/filtering_reports.html @@ -7,7 +7,7 @@ Filtering Execution and Reports with Tags | Serenity BDD Users Manual - + @@ -23,7 +23,7 @@ For example, you might want to flag all of the web services tests, or mark certain tests to run against Internet Explorer browser only. With JUnit tests, this can be achieved by providing a single tag or an "or" separated list of tags from command line. If provided, only classes and/or methods with tags in this list will be executed.

mvn clean verify -Dtags="feature:Reporting or release:sprint-2"mvn clean verify -Dtags="feature:Reporting or release:sprint-2"

When using Cucumber, we need to use the cucumber.options property to indicate which scenarios should be executed. For example, the following command runs all of the Cucumber scenarios with the @sprint-2 tag":

mvn clean verify -Dcucumber.options="--tags=@sprint-2"

Excluding Unrelated Requirements#

By default, when you use the tags option, Serenity will filter your requirements as best it can to report only the requirements that are relevant to the specified tag.

Requirements filtering only happens if you specify the tags option. So this will produce a full set of requirements in the Requirements page.

mvn clean verify -Dcucumber.options="--tags @sprint-2"

But this will report only the requirements that are related to the executed tests.

mvn clean verify -Dcucumber.options="--tags @sprint-2" -Dtags=sprint-2

If you have already run the full set of tests, you can also produce a filtered aggregate report, in which case you don't need to provide the cucumber.options property:

mvn serenity:aggregate -Dtags=sprint-2
- + \ No newline at end of file diff --git a/docs/reporting/integrating_with_jira.html b/docs/reporting/integrating_with_jira.html index e7ad8a7..cf26c8c 100644 --- a/docs/reporting/integrating_with_jira.html +++ b/docs/reporting/integrating_with_jira.html @@ -7,7 +7,7 @@ Integrating with JIRA | Serenity BDD Users Manual - + @@ -22,7 +22,7 @@ when 'Resolved', { 'failure' should: 'Reopen Issue'} when 'In Progress', { 'success' should: ['Stop Progress','Resolve Issue']} when 'Closed', { 'failure' should: 'Reopen Issue'}

You can write your own configuration file and place it on the classpath of your test project (e.g. in serenity's directory). Then you can override the default configuration by using serenity.jira.workflow property, e.g.

serenity.jira.workflow=my-workflow.groovy

Alternatively, you can simply create a file called jira-workflow.groovy and place it somewhere on your classpath (e.g. in the src/test/resources directory). Serenity will then use this workflow. In both these cases, you donโ€™t need to explicitly set the serenity.jira.workflow.active property.

Release management#

In JIRA, you can organize your project releases into versions, as illustrated here:

jira-versions

You can and assign cards to one or more versions using the Fix Version/s field:

jira-fix-versions

By default, Serenity will read version details from the Releases in JIRA. Test outcomes will be associated with a particular version using the โ€œFixed versionsโ€ field. The Releases tab gives you a run-down of the different planned versions, and how well they have been tested so far:

releases-tab

JIRA uses a flat version structure โ€“ you canโ€™t have for example releases that are made up of a number of sprints. Serenity lets you organize these in a hierarchical structure based on a simple naming convention. By default, Serenity uses โ€œreleaseโ€ as the highest level release, and either โ€œiterationโ€ or โ€œsprintโ€ as the second level. For example, suppose you have the following list of versions in JIRA โ€“ Release 1 โ€“ Iteration 1.1 โ€“ Iteration 1.2 โ€“ Release 2 โ€“ Release 3

This will produce Release reports for Release 1, Release 2, and Release 3, with Iteration 1.2 and Iteration 1.2 appearing underneath Release 1. The reports will contain the list of requirements and test outcomes associated with each release. You can drill down into any of the releases to see details about that particular release.

serenity-jira-releases

You can also customize the names of the types of releases using the serenity.release.types property, e.g.

serenity.release.types=milestone, release, version
- + \ No newline at end of file diff --git a/docs/reporting/living_documentation.html b/docs/reporting/living_documentation.html index 3e2cf78..9de49c1 100644 --- a/docs/reporting/living_documentation.html +++ b/docs/reporting/living_documentation.html @@ -7,7 +7,7 @@ Living Documentation | Serenity BDD Users Manual - + @@ -30,7 +30,7 @@ Icons indicate whether a scenario passed or failed, and if you click on the title bar of one of the scenarios, you will go to the test results page for that scenario.

The requirements page for a feature#

The requirements page for a feature

Enhanced Feature Documentation#

When you use Serenity with Cucumber, you can turn this feature overview into a rich living document that mixes business rules with examples and scenarios drawn from the acceptance tests. This lets you design a requirements overview that product owners and stakeholders can review quickly and easily, while still keeping the details on hand if they want to know more.

caution

Enhanced feature documentation is currently only supported for Cucumber.

For example, we could improve the Business Activities feature overview by embedding the tables (but not the "Given..When..Then" texts which essentially act as text fixtures in this case). To do this, we use the {Examples} tag along with the name of the scenario outline that we want to use:

Feature: Business Activities
   Some business activities are considered more risk-prone than others,  and certain customers and entities may pose specific risks.  The business activity risk factor for an industry is determined by the potential risk they present to the bank. For example:
   {Examples} The business activity risk factor for an industry

When the report is generated, Serenity will include the example table from the The business activity risk factor for an industry scenario in the feature description (see Feature Overview with Example Tables).

Feature Overview with Example Tables#

Example tables from the scenarios can be included in the feature overview

If the tests for this table have been executed, the result for each row will be indicated in the table.

The default form (using the {Examples} tag) will take only the examples table from the scenario outline; if you would like the title to be displayed as well, you can use the {Examples!WithTitle} tag instead.

Scenarios are generally to granular for the feature summary, and best left for the detailed section further down the page. However sometimes it makes sense to include a scenario or two in the summary. You can do this by using the {Scenario} tag. This works for both scenarios and scenario outlines.

Adding additional evidence#

Sometimes the automated test results are not alone enough to satisfy stakeholders or auditors. We need to be able to add some extra proof that our application works as described.

In Serenity, you can add evidence in the form of a String or the contents of a file. For example, you might record the results of a SQL query to demonstrate that a database contains the expected results, or record the full version of a generated XML report when you only make assertions on a few key fields.

You can do this using the Serenity.recordReportData() method:

    sqlQueryResult = ...    Serenity.recordReportData().withTitle("Database evidence").andContents(sqlQueryResult);

This method lets you record data from a String or from a file. To get data from a file, use the fromFile() method:

    Path report = ...    Serenity.recordReportData().withTitle("Generated Report").fromFile(report);

In both cases, this data is recorded with the test, and appears in the test results:

Adding evidence to a test result

Common Requirements Structures#

The exact organisation varies from project to project, but some common structures include:

  • Capabilities > Features
  • Capabilities > Features > Stories
  • Goals > Capabilities > Features
  • Epics > Stories
  • Themes > Epics > Stories

A two-level requirements hierarchy works well for most projects. A small project (for example, a micro-service) might need only a short list of features. Only very large or complex projects would typically need three or more levels.

Goals, Capabilities and Features#

The aim of any software project is to help our stakeholders achieve their goals by providing them with capabilities. In BDD, a Capability is something that allows users to do something that they couldn't do previously, or to do something that they could do previously, but do it more efficiently. A capability is technology-agnostic: it does not commit to a particular solution or implementation. An example of a capability might be the ability to pay online with a credit card.

A Feature is a concrete solution or implementation that delivers a capability. Some possible features that deliver the capability we mentioned earlier might be to pay via PayPal, via Stripe or to pay by integrating with a merchant banking platform.

Themes and Epics#

In Scrum, an Epic is simply a big user story, one that can't be delivered in a sprint. A Theme is just another way to group related User Stories, though many teams use Themes as groups of related epics. (Another way to implement the original idea of themes in Serenity BDD is to use tags).

User Stories#

User Stories are commonly used in Agile as a way to organise work, but they are not always very useful when it comes to Living Documentation. This is because they reflect how a feature was sliced up when it was built. But once a feature is delivered, no one cares how it was broken down during the development phase - all that matters is what was delivered. That's why Cucumber prefers to group scenarios in Feature Files (which describe a feature). For this reason, User Stories are generally considered to be not a great way to structure living documentation. (Note that JBehave still uses the older convention of "Story Files", which were meant to contain the acceptance criteria of a given story).

Configuring your requirements structure in Serenity BDD#

You can configure the way Serenity names the different levels in your own requirements structure using the serenity.requirements.types property. For example, if you want to describe your requirements in terms of themes, epics and stories, you would add the following to your Serenity configuration file:

serenity.requirements.types=theme,epic,story

If you don't configure this parameter, Serenity will decide on a sensible default hierarchy. This hierarchy depends on whether you are using JUnit, Cucumber or JBehave, and on the depth of your requirements hierarchy:

Test FrameworkDefault Hierarchy
JUnitcapability > feature > story
Cucumbertheme > capability > feature
JBehavecapability > feature > story
info

Requirements configuration applies to the container levels, not to the feature or story files themselves. If you are using Cucumber, feature files will always be represented as features. If you are using JBehave, story files will always be represented as stories.

Requirements Hierarchies for JUnit Tests#

Many teams write automated acceptance tests with Serenity BDD using JUnit. The Screenplay Pattern in particular makes it easy to write highly maintainable tests using a business-readable DSL that produces excellent living documentation.

JUnit acceptance tests should be organised in a package structure that reflects your requirements hierarchy. Note that this means that they may not reflect the package structure in your application, as is usually done for unit and integration tests.

A simple two-level hierarchy is illustrated here:

comโ””โ”€โ”€ acme    โ””โ”€โ”€ myapps        โ””โ”€โ”€ specs            โ”œโ”€โ”€ multiple_todo_lists            โ”œโ”€โ”€ sharing_lists            โ””โ”€โ”€ simple_todo_lists                โ”œโ”€โ”€ AddingNewItems.java                โ”œโ”€โ”€ DeletingItems.java                โ”œโ”€โ”€ FilteringItemsByStatus.java                โ””โ”€โ”€ MarkingItemsAsComplete.java

You need to tell Serenity where to find the requirements hierarchy in your package structure, using the serenity.test.root property. For the example shown above, the root package is com.acme.myapp.specs:

serenity.test.root=com.acme.myapp.specs

In this case, the Serenity living documentation will treat the JUnit test cases ("Adding New Items", "Deleting Items" etc.) as Stories, and the packages directly underneath the com.acme.myapp.specs package ("Multiple Todo Lists", "Sharing Lists" etc.) as Features.

Requirements Hierarchies for Cucumber#

When you use Cucumber, Serenity expects your feature files to be stored in the src/test/resources/features directory. Your requirements hierarchy goes directly underneath this directory:

srcโ””โ”€โ”€ test    โ””โ”€โ”€ resources        โ””โ”€โ”€ features            โ”œโ”€โ”€ multiple_todo_lists            โ”œโ”€โ”€ sharing_lists            โ””โ”€โ”€ simple_todo_lists                โ”œโ”€โ”€ adding_new_items.feature                โ”œโ”€โ”€ deleting_items.feature                โ”œโ”€โ”€ filtering_items_by_status.feature                โ””โ”€โ”€ marking_items_as_complete.feature

When Cucumber is used with the default configuration, the feature files always represent Features, and the directories containing the features represent Capabilities. A Feature is typically bigger than a user story, and can contain the acceptance criteria (scenarios) from several user stories.

Requirements Hierarchies for JBehave#

When you use JBehave, Serenity expects your Story files to be stored in the src/test/resources/stories directory. Your requirements hierarchy goes directly underneath this directory:

srcโ””โ”€โ”€ test    โ””โ”€โ”€ resources        โ””โ”€โ”€ stories            โ”œโ”€โ”€ multiple_todo_lists            โ”œโ”€โ”€ sharing_lists            โ””โ”€โ”€ simple_todo_lists                โ”œโ”€โ”€ adding_new_items.story                โ”œโ”€โ”€ deleting_items.feature                โ”œโ”€โ”€ filtering_items_by_status.story                โ””โ”€โ”€ marking_items_as_complete.story

By default the Story files represent stories, and the directories above them are rendered as Features.

- + \ No newline at end of file diff --git a/docs/reporting/reports_custom_info.html b/docs/reporting/reports_custom_info.html index a4ee100..273ce1a 100644 --- a/docs/reporting/reports_custom_info.html +++ b/docs/reporting/reports_custom_info.html @@ -7,7 +7,7 @@ Custom Fields in Reports | Serenity BDD Users Manual - + @@ -17,7 +17,7 @@ image::custom-reports-with-provided-property.png[]

You can of course pass in other properties, to override the ones in your serenity.properties file. Here we override the application version:

mvn serenity:aggregate -DHOST=$HOST -Dreport.customfields.ApplicationVersion=1.2.4

But a more elegant solution, if you know you will always be passing in a variable, is to use a shorter variable in your serenity.properties file and then pass this one in. For example, here we use the environment property to display the current environment in the custom properties:

report.customfields.environment = ${environment}

We can set this value from the command line as shown here:

mvn serenity:aggregate -DHOST=$HOST -Denvironment=INT5

Ordering the custom properties#

By default, the fields will appear in an arbitrary order. You can force the fields to appear in a pre-determined order using the report.customfields.order field:

report.customfields.order=ApplicationVersion,environment,user,host

A complete example#

A complete example of these properties and their various usages is shown here:

report.customfields.ApplicationVersion = 1.2.3report.customfields.environment = ${environment}report.customfields.user = ${USER}report.customfields.host = ${HOST}report.customfields.order=ApplicationVersion,environment,user,host

Custom Build Info#

You can also add your own fields the the Build Info screen, using the sysinfo.* properties. The sysinfo.* properties let you define fields and values that will appear in the Build Info page. For simple field-value combinations, the field appears alongside the other values on the Build Info screen:

sysinfo.lead = Daisy

You can use Groovy expressions to access system properties (that you can pass in from the command line). The env property gives you access to the current environment variables. For example, to display the current Jenkins build number, you could include the following line:

sysinfo.build = "${env.BUILD_NUMBER}"

You can also group custom properties into sections with sub-titles. An example of such a configuration in the serenity.conf file is shown below:

sysinfo {  lead = Daisy  build = "${env.BUILD_NUMBER}"  Test Run {    Run By = "${env.USER}"    Java Version = "${java.version}"  }}

The corresponding Build Info screen is shown below:

Customised Build Info details

Defining build info programmatically#

You can also use the BuildInfo class to add information to the Build Info page programmatically. Simply define the section, and add as many property name/value pairs as you want. You can see an example here:

BuildInfo.section("Toggles").setProperty("toggle-custom-ads-v2", "on");BuildInfo.section("Toggles").setProperty("toggle-user-feedback", "on");
 BuildInfo.section("Versions").setProperty("game-history-service", "1.2.3");BuildInfo.section("Versions").setProperty("player-service", "3.4.5");BuildInfo.section("Versions").setProperty("related-products-service", "2.3.4");

Customised Build Info details

- + \ No newline at end of file diff --git a/docs/reporting/the_serenity_reports.html b/docs/reporting/the_serenity_reports.html index cb564ab..ef35e92 100644 --- a/docs/reporting/the_serenity_reports.html +++ b/docs/reporting/the_serenity_reports.html @@ -7,14 +7,14 @@ The Serenity Reports | Serenity BDD Users Manual - +

The Serenity Reports

The Serenity reports are a particularly powerful feature of Serenity BDD. They aim not only to report test results, but also to document how features are tested, and what the application does.

An overview of the test results#

A typical Serenity test report is shown below:

Functional Coverage Overview

This shows a simple pie chart displaying the test result distribution, and bar charts indicating the test outcomes sorted by result and by test duration.

The squiggly lines in the orange bars (indicating broken tests) are for accessiblity. To activate these, you will need the following setting in your serenity.conf file:

serenity {    report {       accessibility = true    }}

Functional Test Coverage#

Further down the screen you will find the Functional Test Coverage section: A typical Serenity Report home page

This section gives a breakdown by capability (or by however you have decided to group your features). You can define the requirements types used in your project using the serenity.requirement.types property, e.g.

serenity {  requirement {    types = "epic, feature"  }}

Note that for Cucumber, the lowest level will always be defined as Feature.

The Key Statistics section shows execution times and the overall number of test scenarios and test cases. You can define the ranges of duration values that appear in the report using the serenity.report.durations property:

serenity{  report {    durations = "1,2,4,8,15,30,60"  }}

Serenity distinguishes between more general Test Scenarios, and more specific Test Cases.

A simple scenario or JUnit test counts as a scenario with a single test case. For example, consider the following scenario:

Scenario: Colin logs in with Colin's valid credentials    Given Colin is on the login page    When Colin logs in with valid credentials    Then he should be presented the product catalog

This counts as 1 scenario with 1 test case.

ScenariosTest Cases
11

A scenario outline, on the other hand, is a single scenario with many test cases. So if you had the following scenario outline:

    Scenario Outline: Login's with invalid credentials for <username>      Given Colin is on the login page      When Colin attempts to login with the following credentials:        | username   | password   |        | <username> | <password> |      Then he should be presented with the error message <message>      Examples:        | username        | password       | message                                                     |        | standard_user   | wrong_password | Username and password do not match any user in this service |        | unknown_user    | secret_sauce   | Username and password do not match any user in this service |        | unknown_user    | wrong_password | Username and password do not match any user in this service |        | locked_out_user | secret_sauce   | Sorry, this user has been locked out                        |

Then the test report would include 1 scenario but 4 test cases:

ScenariosTest Cases
14

So a test suite that contains both of these scenarios would include 2 scenarios made up of 5 test cases:

ScenariosTest Cases
25

Functional Coverage Details#

Further down the functional coverage results are displayed in more detail:

Functional Coverage Details

This lists the requirements by category. By default, Cucumber results organised in folders under src/test/resources/features will be organised by Capabilities and Features. As mentioned above, you can customise these categories using the serenity.requirement.types property.

Test Results#

The Test Results tab lists the actual test results:

Test Results

For data-driven tests and scenario outlines, each row of data is reported as a separate test result, and marked by a table icon to indicate that it is a data-driven test result.

Errors and Tags#

The last section of the report lists the most frequent causes of test failures:

Errors and tags

This section also mentions which the features containing the most failing tests. You can see which tests fail for a given reason by clicking on the corresponding error tag just below this section.

It also lists the tags appearing in the features. You can exclude tags you don't want to appear in this section (for example, technical tags) using the serenity.report.exclude.tags property, e.g.

serenity {    report {        exclude.tags = "resetappstate,singlebrowser,manual"    }}
- + \ No newline at end of file diff --git a/docs/screenplay/screenplay_ensure.html b/docs/screenplay/screenplay_ensure.html index 466838d..8f07f48 100644 --- a/docs/screenplay/screenplay_ensure.html +++ b/docs/screenplay/screenplay_ensure.html @@ -7,7 +7,7 @@ Making Screenplay Assertions with Serenity Ensure | Serenity BDD Users Manual - + @@ -116,7 +116,7 @@ Sometimes, however, we want to use the Ensure statement as a way to make sure the application is ready to continue the tests. In these cases, we may prefer to leave the Ensure statement out of the reports.

We can do this using the silently() method:

aster.attemptsTo(    Ensure.that(ElementLocated.by("#firstName"))          .silently()          .isDisplayed());
- + \ No newline at end of file diff --git a/docs/screenplay/screenplay_fundamentals.html b/docs/screenplay/screenplay_fundamentals.html index 06855d4..84dc649 100644 --- a/docs/screenplay/screenplay_fundamentals.html +++ b/docs/screenplay/screenplay_fundamentals.html @@ -7,7 +7,7 @@ Screenplay Fundamentals | Serenity BDD Users Manual - + @@ -43,7 +43,7 @@ public AddItem(String name) { this.name = name; } @Override @Step("{0} adds an item to the list") public <T extends Actor> void performAs(T actor) { actor.attemptsTo( Enter.theValue(name) .into(".new-todo") .thenHit(Keys.RETURN) ); } public static AddItem called(String name) { return new AddItem(name); }}
tip

Always remember to add a default constructor with no parameters to your Performable implementations, otherwise they will not appear correctly in the reports.

Questions - querying the state of the system#

Screenplay is an actor-centric pattern, and just as actors interact with the system by performing tasks and interactions, they can query the state of the system by asking questions.

Using bundled Question classes#

An actor can ask a question by using the askFor() method. You can see an example of how this works here:

   String pageTitle = toby.asksFor(Text.of(".title"));

Text is an example of a Question Factory. Question Factories provide a convenient way to query the state of the application, and there are many to choose from. For example, we could check whether a particular web element was visible using the Visibility class, like this:

   boolean isVisible = toby.asksFor(Visibility.of(".title"));

Serenity BDD comes with lot bundled Question Factories like these, and we will look at them in more detail in the next section. But you can also write your own custom questions, to query any aspect of your application that you like.

Creating custom Questions using Lambda expressions#

One way to implement a Question is to use a Java 8 Lambda expression that takes an Actor as an argument. For example, the following method returns an Integer Question (a Question that returns an integer).

    Question<Integer> numberOfTodoItems() {        return actor -> BrowseTheWeb.as(actor).findAll(".todo-list li").size();    }

We could find the answer to this question using the asksFor() method, as in the previous example:

   int numberOfTodos = toby.asksFor(numberOfTodoItems());

An alternative to the asksFor() method is the Question's own answeredBy() method:

   int numberOfTodos = numberOfTodoItems().answeredBy(toby);

This format can be more convenient for assertions, as illustrated in this example:

   assertThat(numberOfTodoItems().answeredBy(toby)).isEqualTo(1);

Making questions more readable with the Question.about() method#

We could make this method more readable by using the Question.about format - this will produce a more meaningful error message. In the following example, we use the BrowseTheWeb class to access the Serenity WebDriver API and find the number of todo list items currently on the page:

    Question<Integer> numberOfTodoItems() {        return Question.about("the number of todo items")                   .answeredBy(                       actor -> BrowseTheWeb.as(actor).findAll(".todo-list li").size());    }

Converting Questions#

Questions also provide a convenient way to convert responses into different types. This is particularly useful for the bundled WebDriver Question classes, that typically return values in text form.

For example, the TodoMVC application shows the number of items remaining to do at any time beneath the list:

We can locate the item count using the CSS expression ".todo-count strong". We could fetch this value as a String using the Text class we saw previously:

    String itemsLeftCount = toby.asksFor(Text.of(".todo-count strong");

However if we prefer to retrieve the value as an integer, we could use the asInteger() method like this:

   int itemsLeftCount = toby.asksFor(Text.of(".todo-count strong").asInteger());

Some of the conversion methods available include the following:

TypeMethodExample
IntegerasInteger()Text.of(".todo-count strong").asInteger()
LongasLong()Text.of(".todo-count strong").asLong()
FloatasFloat()Text.of(".currency-value").asFloat()
DoubleasDouble()Text.of(".currency-value").asDouble()
BigDecimalasBigDecimal()Text.of(".currency-value").asBigDecimal()

Converting date values#

Date values can also be converted to LocalDate objects. If the date uses the standard ISO date format (e.g. "2022-05-15"), it can be converted using the asDate() method, like this:

   LocalDate dateValue = toby.asksFor(       Text.of("#departure-date").asDate()    );

If the date uses a different format, the asDate() method takes a date-time pattern that can be used to parse the value, e.g.

    LocalDate dateValue = toby.asksFor(        Text.of("#departure-date").asDate("d MMM uuuu")    );

Converting to lists of values#

We can also use the asListOf() method to find all the answers to a specific question, and convert each of them to a specified type. For example, to convert a list of matching String values to integers, we could use the following code:

    List<Integer> itemQuantities = toby.asksFor(        Text.of(".item-quantity").asListOf(Integer.class)    );

Working with collections#

Another way to retrieve a list of values is to use the ofEach() method.

    Collection<String> itemQuantities = toby.asksFor(Text.of(".item-quantity"));

As with the Text.of() method, we can use the asListOf() method to convert this collection into another type

    List<String> itemQuantities = toby.asksFor(        Text.of(".item-quantity").asListOf(Integer.class)    );

If we need to perform a more complex operation, we can use the mapEach() method to apply an arbitrary Lambda expression to each matching element:

   Collection<Integer> nameLengths = toby.asksFor(Text.ofEach(".name").mapEach(s -> s.length()));

Actor-specific session data#

Sometimes we need to store information in a step or task and reuse it in a subsequent one. Each Screenplay actor can remember information, and retrieve it later on in the test. We do this using the remember() method:

    int actualCost = 100    actor.remember("Total Cost", total);

Later on, we can retrieve this information using the recall() method:

    int recalledCost = dana.recall("Total Cost");    assertThat(recalledCost).isEqualTo(100);

An actor can remember information of any type, even the answer to a question. For example,the Text.of() method returns a Question object of type Question<String>. An actor can remember the answer to this question by using it as a parameter to the remember() method:

    actor.remember("Total Cost", Text.of("#total-cost").asInteger());

We can then recall this value in the same way as any other:

    int totalCost = actor.recall("Total Cost");    assertThat(totalCost).isEqualTo(100);

We can even recall a map containing every value currently remembered by the actor. We do this using the recallAll() method:

    Map<String, Object> all = actor.recallAll();

We can also remove a remembered value using the forget() method:

    actor.forget("Total Cost");

Conclusion#

Now that we have seen how to set up a Screenplay test using different frameworks, how to organise interactions into tasks, and how to query the state of the system, we will look at how to use Screenplay to interact with a web application in more detail.

- + \ No newline at end of file diff --git a/docs/screenplay/screenplay_rest.html b/docs/screenplay/screenplay_rest.html index 4d2d717..24072e9 100644 --- a/docs/screenplay/screenplay_rest.html +++ b/docs/screenplay/screenplay_rest.html @@ -7,7 +7,7 @@ Working with REST APIs using Serenity Screenplay | Serenity BDD Users Manual - + @@ -70,7 +70,7 @@ public FindAUser(int id) { this.id = id; } public static FindAUser withId(int id) { return instrumented(FindAUser.class, id); } @Override @Step("{0} fetches the user with id #id") public <T extends Actor> void performAs(T actor) { actor.attemptsTo( Get.resource("/users/{id}") .with(request -> request.pathParam("id", id)) ); }}

Using this class, we could refactor our original class to read like this:

sam.attemptsTo(        FindAUser.withId(1));

Using tasks to encapsulate REST interactions results in a clear, layered reporting structure, that first describes what the user is doing, and they how they go about it. The test report for the previous scenario is shown here:

- + \ No newline at end of file diff --git a/docs/screenplay/screenplay_webdriver.html b/docs/screenplay/screenplay_webdriver.html index 8cbd0bc..49d1e2d 100644 --- a/docs/screenplay/screenplay_webdriver.html +++ b/docs/screenplay/screenplay_webdriver.html @@ -7,7 +7,7 @@ Web Testing with Serenity Screenplay | Serenity BDD Users Manual - + @@ -23,7 +23,7 @@ public static Question<String> value() { return actor -> USER_NAME.resolveFor(actor).getText(); }}

In this case, the @Subject annotation will have no effect, so we need to pass in the name of the object we are checking in the Screenplay assertion:

sam.should(seeThat("the displayed username", TheUserName.value(), equalTo("sam")));

So far you have seen how Screenplay questions work in detail. This will help you implement your own if you need to. However Serenity also provides a number of shortcuts related to querying web pages, which you will find in the net.serenitybdd.screenplay.questions package, which allow you to write much more concise automation code.

Bundled WebDriver Questions#

Serenity provides many bundled Question classes in the net.serenitybdd.screenplay.questions package that a short-hand way of querying a web page. For example, the Text class lets us retrieve the text content of an element, like this:

String name = sam.asksFor(Text.of("#name"));

If there are many matching entries, we can retrieve them all using the ofEach() method:

Collection<String> names = sam.asksFor(Text.ofEach(".name"));

The full list of Web Question classes is provided here.

Absence#

Determine whether an element is not present or visible on the page. A field that is present in the dom but is not rendered will be considered absent.

boolean isNotPresent = sam.asksFor(Absence.of("#no-such-field"));

Attribute#

Check the value of an HTML attribute of a specified element.

String placeholderText = sam.asksFor(Attribute.of(".new-todo").named("placeholder"));

CheckboxValue#

Determine whether a checkbox has been checked or not.

boolean termsAndConditionsApproved = sam.asksFor(CheckboxValue.of("#tnc"));

CSSValue#

Retrieve the value of a specific CSS attribute of an element.

String font = sam.asksFor(CSSValue.of(target).named("font"));

CurrentlyEnabled#

Check whether an element is currently enabled, without waiting.

boolean isCurrentlyEnabled = sam.asksFor(CurrentlyEnabled.of("#some-button"));

CurrentVisibility#

Check whether an element is currently visible, without waiting.

boolean isCurrentlyVisible = sam.asksFor(CurrentVisibility.of("#some-button"));

Disabled#

Check whether an element is disabled.

boolean isDisabled = sam.asksFor(Disabled.of("#a-disabled-button"));

Displayed#

Check whether an element is displayed. If the element is not currently displayed, the test will wait for a short delay to give it time to be displayed.

boolean isDisplayed = sam.asksFor(Displayed.of("#some-button"));

Enabled#

Check whether an element is enabled. If the element is not currently enabled, the test will wait for a short delay to give it time to be enabled.

boolean isEnabled = sam.asksFor(Enabled.of("#some-button"));

Presence#

Check whether an element is present in the DOM. An invisible or hidden element can still be present in the DOM.

SelectedStatus#

Alternative to CheckboxValue

boolean termsAndConditionsApproved = sam.asksFor(SelectedStatus.of("#tnc"));

Text

To fetch the text value of an element, we can use the Text class:

String introductionText = sam.asksFor(Text.of("#introduction"));

TextContent#

In some cases, we may need to read the textContent HTML property to get the text we need. To do this, we can use the TextContent class rather than Text. This returns the text content of the specified element, and all its descendants.

TheCoordinates#

Return the coordinates of a specified element.

TheLocation#

Return where on the page is the top left-hand corner of the rendered element.

TheSize#

What is the width and height of the rendered element?

Value#

Return the HTML value attribute of a specified element.

Visibility#

Determine whether this web element present and visible on the screen

Working with Dropdowns#

We can query the current selected value or values of an HTML <SELECT> element using the SelectedValue, SelectedValues, SelectedVisibleTextValue and SelectedVisibleTextValue Question classes.

For example, to find the current selected value of an HTML dropdown list, we could use the following code:

String selectedColorValue = dina.asksFor(SelectedValue.of("#color-dropdown"));

To get the visible text of the selected item, we would use SelectedVisibleTextValue:

String selectedColor = dina.asksFor(SelectedVisibleTextValue.of("#color-dropdown"));

For multi-selects, we can use SelectedValues and SelectedVisibleTextValues:

List<String> selectedColors = dina.asksFor(SelectedValues.of("#color-dropdown"));

We can retrieve the current list of options using SelectOptions, which returns the list of visible texts for each option:

List<String> selectedColors = dina.asksFor(SelectOptions.of("#color-dropdown"));

If we need the value attribute of each dropdown option, we can use SelectOptionValues, e.g.:

List<String> selectedColors = dina.asksFor(SelectOptionValues.of("#color-dropdown"));

Handling Waits#

Using the WaitUntil class#

If you need to wait for an element to appear with Serenity Screenplay, there are a few options available. By default, Serenity will wait for a short delay if you try to interact with an element that is not on the page. However, you can ensure that this wait is sufficient by using the WaitUntil class, as shown here:

private final static Target DELAYED_BUTTON = PageElement.locatedBy("#delayed-button");
 dina.attemptsTo(    WaitUntil.the(DELAYED_BUTTON, WebElementStateMatchers.isVisible()),    Click.on(DELAYED_BUTTON));

This code will wait until the element is visible before proceeding to the Click action. The timeout can be configured (in milliseconds) using the webdriver.timeouts.implicitlywait property, which is 5 seconds by default.

If you need to have a finer control over the timeout duration for specific situations, you can specify this by adding the forNoMoreThan() method, which lets you specify an explicit timeout:

dina.attemptsTo(    WaitUntil.the(DELAYED_BUTTON, isVisible()).forNoMoreThan(10).seconds());

You can also wait for other conditions. For example, to wait until an element dissapears, you can use the isNotVisible() matcher:

dina.attemptsTo(    WaitUntil.the(DISAPPEARING_BUTTON, isNotVisible()));

The following matchers are available in the WebElementStateMatchers class. Note that all of the following methods also have a negative equivalent (isNotVisible(), isNotEmpty() etc.).

MatcherPurpose
containsText(...)Check that an element contains a specific text value
containsOnlyText(...)Check that an element contains exactly a specific text value
containsSelectOption(...)Check that a dropdown element contains a specific text value as an option
isClickableCheck that an element is visible and enabled
isEmptyCheck that an element is not visible or contains an empty string
isEnabledCheck that an element is enabled
isPresentCheck that an element is present on the page
isSelectedCheck that an element is selected
isVisibleCheck that an element is visible

Waiting for a WebDriver condition#

Another option is to wait for a WebDriver condition (which can be found in the org.openqa.selenium.support.ui.ExpectedConditions class), e.g.

dina.attemptsTo(        WaitUntil.the(                invisibilityOfElementLocated(By.id("disappearing-button"))));

Waiting for Targets#

You can also place a specific wait condition on a Target object. You can do this either when you define the Target variable (if it should be applied any time you interact with this element), or only when you interact with the element, as shown below:

private final static Target INVISIBLE_BUTTON     = PageElement.locatedBy("#invisible-button");
 dina.attemptsTo(    Click.on(INVISIBLE_BUTTON.waitingForNoMoreThan(Duration.ofSeconds(3))));
- + \ No newline at end of file diff --git a/docs/spring/integration_testing_spring.html b/docs/spring/integration_testing_spring.html index f3f731d..522b5a3 100644 --- a/docs/spring/integration_testing_spring.html +++ b/docs/spring/integration_testing_spring.html @@ -7,7 +7,7 @@ Integration Testing in Spring | Serenity BDD Users Manual - + @@ -40,7 +40,7 @@ @When("I use the nested bean") public void whenIUseTheBean() { widgetName = nestedSteps.widgetService.getName(); } @Then("the nested bean should be instantiated") public void thenItShouldBeInstantiated() { assertThat(widgetName, is("Widgets")); } } - + \ No newline at end of file diff --git a/docs/tags.html b/docs/tags.html index 73213b4..090840e 100644 --- a/docs/tags.html +++ b/docs/tags.html @@ -7,13 +7,13 @@ Tags | Serenity BDD Users Manual - + - + \ No newline at end of file diff --git a/docs/tutorials/cucumber-screenplay.html b/docs/tutorials/cucumber-screenplay.html index 7b1fe1f..f8a3a6f 100644 --- a/docs/tutorials/cucumber-screenplay.html +++ b/docs/tutorials/cucumber-screenplay.html @@ -7,7 +7,7 @@ Getting Started With Cucumber using Serenity BDD and Screenplay | Serenity BDD Users Manual - + @@ -38,7 +38,7 @@ ......... [INFO] -----------------------------------------[INFO] SERENITY TESTS: SUCCESS[INFO] -----------------------------------------[INFO] | Test cases executed | 1[INFO] | Tests executed | 1[INFO] | Tests passed | 1[INFO] | Tests failed | 0[INFO] | Tests with errors | 0[INFO] | Tests compromised | 0[INFO] | Tests aborted | 0[INFO] | Tests pending | 0[INFO] | Tests ignored/skipped | 0[INFO] ------------------------ | --------------[INFO] | Total Duration | 20s 001ms[INFO] | Fastest test took | 20s 001ms[INFO] | Slowest test took | 20s 001ms[INFO] -----------------------------------------[INFO][INFO] SERENITY REPORTS[INFO] - Full Report: file:///C:/Users/calib/source-codes/temp/serenity-cucumber-starter/target/site/serenity/index.html[INFO][INFO] --- maven-failsafe-plugin:3.0.0-M5:verify (default) @ cucumber-starter ---[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 49.894 s[INFO] Finished at: 2022-08-12T15:28:52+05:30[INFO] ------------------------------------------------------------------------

Yes, the tests passed and the build is successful now. We have managed to test our feature successfully ๐ŸŽ‰

Reporting and Living Documentation#

If you notice carefully, the output of the mvn clean verify command informed us that a report is created in target/site/serenity/index.html

When you open this file in a web browser, you see a beautiful report like this.

Report Home Page

You can also find the feature-wise results detailing the scenarios in the Features tab.

Report of Features

Feel free to navigate the links in this report and look around.

This is also called a Living Documentation of the product because, this is generated by actually executing the specifications, rather than just writing it as a wiki or a document stored in cloud. As the product evolves, the scenarios will get added and this report is the single source of truth about what works and what is pending to be implemented in the product.

In some cases, teams use this document to onboard new joiners to the team. If you are feeling adventurous, this document can also be used as a user guide.

Next Steps#

In this tutorial, we just touched the surface of using Serenity BDD with Cucumber. There are multiple ways to customize the report, organize the feature files, implement the step definitions and so on. Refer to the links in the user manual to know more about further possibilities.

- + \ No newline at end of file diff --git a/docs/tutorials/first_test.html b/docs/tutorials/first_test.html index 61537de..9d3bbe2 100644 --- a/docs/tutorials/first_test.html +++ b/docs/tutorials/first_test.html @@ -7,7 +7,7 @@ Your First Web Test | Serenity BDD Users Manual - + @@ -34,7 +34,7 @@ public class SearchActions extends UIInteractions { @Step("Search for '{0}'") public void byKeyword(String keyword) { $("#searchbox_input").sendKeys(keyword, Keys.ENTER); }}

Reporting on assertions#

The last step of our test is an assertion. We can report on the assertion by wrapping it in the Serenity.reportThat() method, using a Lambda expression for the actual assertion:

@Testvoid theKeywordShouldAppearInTheResultsSidebar() {    navigate.toTheDuckDuckGoSearchPage();    search.byKeyword("Cucumber");
     Serenity.reportThat("The keyword should appear in the sidebar heading",            () -> assertThat(searchResultSidebar.heading()).isEqualTo("Cucumber")    );}

Generating the reports#

Let's run the tests and see what the reports look like. Delete the wikipedia package (we don't need the sample tests anymore), and run mvn verify from the command line. You should see an output along the following lines:

$ mvn verify...[INFO]  SERENITY TESTS: SUCCESS[INFO] -----------------------------------------[INFO] | Tests executed         | 1[INFO] | Tests passed           | 1[INFO] | Tests failed           | 0[INFO] | Tests with errors      | 0[INFO] | Tests compromised      | 0[INFO] | Tests aborted          | 0[INFO] | Tests pending          | 0[INFO] | Tests ignored/skipped  | 0[INFO] ------------------------ | --------------[INFO] | Total Duration         | 5s 626ms[INFO] | Fastest test took      | 5s 626ms[INFO] | Slowest test took      | 5s 626ms[INFO] -----------------------------------------[INFO][INFO] SERENITY REPORTS[INFO]   - Full Report: file:///Users/john/Projects/Serenity/serenity-new-documentation/serenity-users-guide/sample-code/docs-starter-tutorial/target/site/serenity/index.html[INFO][INFO] --- maven-failsafe-plugin:3.0.0-M5:verify (default) @ serenity-junit-starter ---[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time:  21.729 s[INFO] Finished at: 2021-11-30T11:27:29Z[INFO] ------------------------------------------------------------------------

Now open the index.html file in the target/site/serenity directory. You should see something like this:

Click on the "Test Results" tab and open the "When Searching By Keyword" scenario. This should show you the step-by-step details of your test:

Conclusion#

Congratulation! You've written your first Serenity BDD test, and seen a little of what Serenity BDD can do!

- + \ No newline at end of file diff --git a/docs/tutorials/migrating_to_serenity_4.html b/docs/tutorials/migrating_to_serenity_4.html index 0dab359..7d185d0 100644 --- a/docs/tutorials/migrating_to_serenity_4.html +++ b/docs/tutorials/migrating_to_serenity_4.html @@ -7,7 +7,7 @@ Migrating From Serenity BDD 3.x to Serenity BDD 4.x | Serenity BDD Users Manual - + @@ -15,7 +15,7 @@

Migrating From Serenity BDD 3.x to Serenity BDD 4.x

Introduction#

Serenity BDD 4.0.0 is a significant update that aligns with modern testing libraries by supporting Java 11. This major release includes changes to package structures, reflecting adjustments in the module structure for Java 11. If you are migrating from Serenity 3.x to Serenity 4.x, this tutorial will guide you through the necessary steps to make your project compatible with the latest version.

Step 1: Ensure Java 11 Compatibility#

Make sure your project is compatible with Java 11, as Serenity BDD 4.x requires it as a minimum version. If you are using Maven, update your project's pom.xml file to include the maven-compiler-plugin configured for Java 11. Here's an example:

<plugin>  <groupId>org.apache.maven.plugins</groupId>  <artifactId>maven-compiler-plugin</artifactId>  <version>3.8.1</version>  <configuration>    <source>11</source>    <target>11</target>  </configuration></plugin>

If your project uses Gradle, you'll need to specify the Java version in your build.gradle file to ensure compatibility with Java 11. Here's an example:

plugins {  id 'java'}
 sourceCompatibility = '11'targetCompatibility = '11'

Step 2: Update Serenity Dependencies#

Update the Serenity BDD dependencies in your project's build file to the latest 4.x version, e.g.

    <properties>        <serenity.version>4.0.0</serenity.version>    </properties>    <dependencies>        <dependency>            <groupId>net.serenity-bdd</groupId>            <artifactId>serenity-core</artifactId>            <version>${serenity.version}</version>        </dependency>        <dependency>            <groupId>net.serenity-bdd</groupId>            <artifactId>serenity-junit</artifactId>            <version>${serenity.version}</version>        </dependency>        <dependency>            <groupId>net.serenity-bdd</groupId>            <artifactId>serenity-screenplay</artifactId>            <version>${serenity.version}</version>        </dependency>        <dependency>            <groupId>net.serenity-bdd</groupId>            <artifactId>serenity-screenplay-webdriver</artifactId>            <version>${serenity.version}</version>        </dependency>        <dependency>            <groupId>net.serenity-bdd</groupId>            <artifactId>serenity-ensure</artifactId>            <version>${serenity.version}</version>        </dependency>        <dependency>            <groupId>net.serenity-bdd</groupId>            <artifactId>serenity-cucumber</artifactId>            <version>${serenity.version}</version>        </dependency>    </dependencies>
 

Step 3: Modify Annotations#

Because of Java 9 module constraints, some of the packages have changed places in the new version. Most importantly, all of the main Serenity annotations can now be found in the net.serenitybdd.annotations package.

In your project, replace the main Serenity annotations, such as @Step, to the new package net.serenitybdd.annotations from the old package net.thucydides.core.annotations. If your project is large, you can update all of your annotations in one go like this:

Step 4: Update Package References#

If you are using internal Serenity classes, you may need to modify the relevant package references in your code based on the following table:

ModuleOld packagesNew Packages
serenity-screenplay-webdrivernet.serenity.screenplay.*net.serenity.screenplay.webdriver.*
net.serenitybdd.screenplay.webtest.actions.*net.serenitybdd.screenplay.webdriver.actions.*
serenity-modelnet.serenitybdd.core.*net.serenitybdd.model.*
net.thucydides.core.annotations.*net.serenitybdd.annotations.*
Other net.thucydides.core.*net.thucydides.model.*

For example, you may need to replace net.thucydides.core.util.EnvironmentVariables with net.thucydides.core.util.EnvironmentVariables

Step 5: Test Your Changes#

After making these changes, run your test suite to verify that everything is working correctly with the new Serenity BDD version. Pay particular attention to the following:

  • Requirements Hierarchy: Ensure that the requirements hierarchy is displaying correctly in your reports.
  • Test Execution: Confirm that all your tests are being executed as expected, without any missing or failing tests that previously succeeded.

Conclusion#

Migrating to Serenity BDD 4.x involves updating package references to align with the new Java 11 module structure. Follow the steps above, and consult the official Serenity BDD documentation for additional information or support.

Remember to thoroughly test your updated project, particularly focusing on the requirements hierarchy and test execution, to ensure that the migration has been successful.

- + \ No newline at end of file diff --git a/docs/tutorials/rest.html b/docs/tutorials/rest.html index 21fa0fc..b73b534 100644 --- a/docs/tutorials/rest.html +++ b/docs/tutorials/rest.html @@ -7,7 +7,7 @@ Your First API Test | Serenity BDD Users Manual - + @@ -64,7 +64,7 @@ ......... [INFO] -----------------------------------------[INFO] SERENITY TESTS: SUCCESS[INFO] -----------------------------------------[INFO] | Test cases executed | 1[INFO] | Tests executed | 1[INFO] | Tests passed | 1[INFO] | Tests failed | 0[INFO] | Tests with errors | 0[INFO] | Tests compromised | 0[INFO] | Tests aborted | 0[INFO] | Tests pending | 0[INFO] | Tests ignored/skipped | 0[INFO] ------------------------ | --------------[INFO] | Total Duration | 9s 212ms[INFO] | Fastest test took | 9s 212ms[INFO] | Slowest test took | 9s 212ms[INFO] -----------------------------------------[INFO][INFO] SERENITY REPORTS[INFO] - Full Report: file:///C:/Users/calib/source-codes/temp/serenity-junit-starter/target/site/serenity/index.html[INFO][INFO] --- maven-failsafe-plugin:3.0.0-M5:verify (default) @ serenity-junit-starter ---[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 39.104 s[INFO] Finished at: 2022-09-02T17:33:14+05:30[INFO] ------------------------------------------------------------------------

Yes, the test passed and the build is successful now. We have managed to test our API successfully ๐ŸŽ‰

Reporting and Living Documentation#

If you notice carefully, the output of the mvn clean verify command informed us that a report is created in target/site/serenity/index.html

When you open this file in a web browser, you see a beautiful report like this.

Report Home Page

You can also find the test-wise results detailing the steps in the Stories tab, detailing the REST API calls.

Report

If you want to look at the exact details used in the HTTP requests, you can click on the link circled in the above screenshot. This will show you the details as shown below.

Report with HTTP requests

Feel free to navigate the links in this report and look around.

Conclusion#

In this tutorial, you created your own API test cases and ran them using Serenity BDD to generate a beautiful report.

- + \ No newline at end of file diff --git a/docs/tutorials/running_cucumber_scenarios_in_parallel.html b/docs/tutorials/running_cucumber_scenarios_in_parallel.html index 0b0a4b0..f15d21a 100644 --- a/docs/tutorials/running_cucumber_scenarios_in_parallel.html +++ b/docs/tutorials/running_cucumber_scenarios_in_parallel.html @@ -7,14 +7,14 @@ How to Do Parallel Test Execution in Cucumber with Serenity | Serenity BDD Users Manual - +

How to Do Parallel Test Execution in Cucumber with Serenity

Cucumber 7 has introduced native support for parallel execution at both the feature and scenario levels. This parallel execution can provide significant performance improvements in test runs. If you want to harness these performance improvements and run your Serenity BDD features and scenarios in parallel, you will need to upgrade to JUnit 5.

Pre-requisites#

  • Cucumber 7.x
  • Serenity BDD 3.9.8 or 4.0.x
  • Maven 3.x for building the project

Now, let's get started with the detailed step-by-step guide.

Step 1: Update Serenity BDD to a Recent Version#

Before proceeding, make sure that you have a recent version of Serenity BDD. Versions 3.9.8 or 4.0.x are recommended for best results.

You can check your current version in your pom.xml file or update it to the latest version.

Step 2: Update to JUnit 5 in Your Maven Project#

JUnit 5 provides the foundation for running tests in parallel with Cucumber and Serenity. Here's how you can update to JUnit 5 in your pom.xml file:

  1. Open the pom.xml file in your Maven project.

  2. Add the following dependencies for JUnit 5 and Cucumber 7.

    <dependencyManagement>    <dependencies>        <dependency>            <groupId>org.junit</groupId>            <artifactId>junit-bom</artifactId>            <version>5.10.0</version>            <type>pom</type>            <scope>import</scope>        </dependency>    </dependencies></dependencyManagement><dependencies>    ...    <!-- JUNIT 5 Dependencies -->    <dependency>        <groupId>org.junit.platform</groupId>        <artifactId>junit-platform-launcher</artifactId>        <scope>test</scope>    </dependency>    <dependency>        <groupId>org.junit.platform</groupId>        <artifactId>junit-platform-suite</artifactId>        <scope>test</scope>    </dependency>    <dependency>        <groupId>org.junit.jupiter</groupId>        <artifactId>junit-jupiter-engine</artifactId>        <scope>test</scope>    </dependency>    <dependency>        <groupId>io.cucumber</groupId>        <artifactId>cucumber-junit-platform-engine</artifactId>        <version>7.2.3</version>        <scope>test</scope>    </dependency></dependencies>

More details on JUnit 5 and Maven can be found in the JUnit 5 User Guide.

Step 3: Create a junit-platform.properties File#

Create a new file named junit-platform.properties in your src/test/resources folder. This file enables and configures parallel execution.

Add the following content to the file:

cucumber.execution.parallel.enabled=truecucumber.execution.parallel.config.strategy=dynamiccucumber.plugin=io.cucumber.core.plugin.SerenityReporterParallel

These properties enable parallel execution and configure it to use a dynamic strategy, along with the Serenity reporter for parallel execution.

Step 4: Create a cucumber.properties File#

Create a new file named cucumber.properties in your src/test/resources folder. This file will contain the Cucumber options for your Cucumber tests.

Add the following content to the file:

cucumber.execution.order = randomcucumber.plugin=pretty,json:target/cucumber.json,timeline:target/test-results/timelinecucumber.snippet-type=camelcase

You can find more details on Cucumber configuration options in the Cucumber documentation.

Step 5: Update Your Cucumber Runner Class#

You should have a single runner class for your whole test suite. Update it as follows:

import org.junit.platform.suite.api.IncludeEngines;import org.junit.platform.suite.api.SelectClasspathResource;import org.junit.platform.suite.api.Suite;
 @Suite@IncludeEngines("cucumber")@SelectClasspathResource("/features")public class AcceptanceTestSuite {}

This runner class will include all the features in the /features directory and run them using the Cucumber engine.

Conclusion#

That's it! By following these steps, you can leverage the power of parallel execution with Cucumber and Serenity BDD. This will significantly reduce the execution time of your test suite, leading to faster feedback and more efficient development cycles.

Happy testing! ๐Ÿš€

- + \ No newline at end of file diff --git a/docs/tutorials/screenplay.html b/docs/tutorials/screenplay.html index 83bd7b2..de3d034 100644 --- a/docs/tutorials/screenplay.html +++ b/docs/tutorials/screenplay.html @@ -7,7 +7,7 @@ Your First Screenplay Scenario | Serenity BDD Users Manual - + @@ -21,7 +21,7 @@ @CastMember(name = "Toby") Actor toby; @Test @DisplayName("Add a todo item to an empty list") void addToEmptyList() { toby.attemptsTo( Open.url("https://todomvc.com/examples/angularjs/#/"), Enter.theValue("Buy some milk").into(".new-todo").thenHit(Keys.RETURN) ); var todos = toby.asksFor(Text.ofEach(".todo-list li")); assertThat(todos).containsExactly("Buy some milk"); }}

Generating the reports#

Let's run the tests and see what the reports look like. Just run mvn clean verify from the command line. You should see an output along the following lines:

$ mvn verify...[INFO] -----------------------------------------[INFO]  SERENITY TESTS: SUCCESS[INFO] -----------------------------------------[INFO] | Test cases executed    | 1[INFO] | Tests executed         | 1[INFO] | Tests passed           | 1[INFO] | Tests failed           | 0[INFO] | Tests with errors      | 0[INFO] | Tests compromised      | 0[INFO] | Tests aborted          | 0[INFO] | Tests pending          | 0[INFO] | Tests ignored/skipped  | 0[INFO] ------------------------ | --------------[INFO] | Total Duration         | 7s 292ms[INFO] | Fastest test took      | 7s 292ms[INFO] | Slowest test took      | 7s 292ms[INFO] -----------------------------------------[INFO][INFO] SERENITY REPORTS[INFO]   - Full Report: file:///C:/Users/johns/projects/todomvc-screenplay-tutorial/target/site/serenity/index.html[INFO][INFO] --- maven-failsafe-plugin:3.0.0-M5:verify (default) @ serenity-junit-screenplay-starter ---[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time:  21.660 s[INFO] Finished at: 2022-04-04T13:34:26+01:00[INFO] ------------------------------------------------------------------------

Now open the index.html file in the target/site/serenity directory using a web browser, and navigate to the Test Results tab. Open up the "Add a todo item to an empty list" scenario. Notice how the report renders the actor's actions almost word-for-word:

Conclusion#

You have now seen just a little of the power of the Screenplay pattern. To learn more about what you can do with the Screenplay pattern, check out the full Screenplay Documentation.

- + \ No newline at end of file diff --git a/docs/tutorials/streamlining_your_serenity_reports.html b/docs/tutorials/streamlining_your_serenity_reports.html index e561087..4a47686 100644 --- a/docs/tutorials/streamlining_your_serenity_reports.html +++ b/docs/tutorials/streamlining_your_serenity_reports.html @@ -7,13 +7,13 @@ Three Strategies to Optimize Your Serenity BDD Reports | Serenity BDD Users Manual - +

Three Strategies to Optimize Your Serenity BDD Reports

Serenity BDD stands out for its ability to produce detailed and informative reports. These reports offer insights not just on executed tests, but also on the fulfillment of business requirements. But like all tools, getting the most out of Serenity BDD involves a few tweaks and optimizations.

Here are three strategies to make your Serenity BDD reports more efficient:

  1. Stay Updated!

    Ensure you're working with the latest version of Serenity BDD, ideally 4.0.12 or newer. With each update, you'll find several optimizations to enhance report performance and minimize generated files. For instance, standard report generation in version 4.0.11 is up to 10 times faster than in 3.9.8.

  2. Opt Out of Duration Reporting

    By default, Serenity BDD generates in-depth reports detailing the runtime for each test. While these reports are richer in information, they consume more disk space. For substantial projects where disk space becomes an issue, consider turning off duration reporting. This can be done by setting the serenity.report.test.durations flag to false. As a testament to its efficacy, one project with over 11,000 tests witnessed its report size shrink from 397M to 250M, and the generation time was halved.

  3. Limit Screenshots to Failed Tests

    When conducting web tests, a useful approach to conserve space is by capturing screenshots exclusively for failed tests. Achieve this by adjusting the serenity.take.screenshots property to FOR_FAILURES. This tweak not only accelerates the tests but also trims down the report size. Keep in mind, however, that this might slightly reduce the detail in your reporting.

Harness the power of Serenity BDD more effectively by applying these strategies and enjoy a streamlined testing report experience.

- + \ No newline at end of file diff --git a/index.html b/index.html index 08f1237..b09c4f8 100644 --- a/index.html +++ b/index.html @@ -7,13 +7,13 @@ Welcome | Serenity BDD Users Manual - +

Serenity BDD Users Manual

Automated Acceptance Testing With Style

Bring Your Team Together

Donโ€™t be a lonely tester writing scripts in a corner, create test automation frameworks that your whole team enjoys using.

Automate At Scale

Write clean, high quality, easily maintained automation code that scales with your test suite, so that you spend your time writing new scenarios, not fixing existing ones.

Report What Really Matters

Serenity BDD provides powerful living documentation and test reporting that gives meaningful feedback to testers, business folks, and the team as a whole. Serenity tells you not only what tests have been executed, but more importantly, what requirements have been tested.

Test UI, API and Mobile

Serenity supports both UI and API testing, and integrates seamlessly with standard industry tools such as Selenium 4 and RestAssured.

Integrate with your favorite test automation libraries

Automate executable specifications with BDD tools like Cucumber, or write clean and maintainable test code with business-readable reporting in JUnit 4 or 5.

Apply Best Practices

Use conventional Page Objects, and reduce the amount of code needed by 50% compared to traditional page object implementations, or try out more modern test automation design patterns such as Action Classes or the Screenplay Pattern, and write scalable, easy to maintain code tailor-fitted to your domain.

Platinum Sponsors

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators.

Perform Automated and Live Interactive Cross Browser Testing on 3000+ Real Browsers and Operating Systems Online.

Start Learning Real-World Test Automation Today with a proven programme that will set you apart from your peers.

- + \ No newline at end of file diff --git a/markdown-page.html b/markdown-page.html index ccffca6..2f99e25 100644 --- a/markdown-page.html +++ b/markdown-page.html @@ -7,13 +7,13 @@ Markdown page example | Serenity BDD Users Manual - + - + \ No newline at end of file diff --git a/screenplay/web/screenplay-web-elements.html b/screenplay/web/screenplay-web-elements.html index 39b268f..7264904 100644 --- a/screenplay/web/screenplay-web-elements.html +++ b/screenplay/web/screenplay-web-elements.html @@ -7,7 +7,7 @@ Serenity BDD Users Manual - + @@ -25,7 +25,7 @@ wendy.attemptsTo( Select.optionNumbers(0,1).from(Dropdown.called("planes")));

Elements#

In addition to HTML forms, there are many other elements we can interact with using the bundled Screenplay classes.

Elements on a page#

Sometimes we need to refer to specific elements on a page; this comes in handy when we want to locate an element in a particular context.

For example, in the following HTML code there are two submit buttons. each in different sections of the page. The only way to distinguish them is to refer to the <h2> header elements.

<div class="section">    <h2>Section 1</h2>    <button value="Submit">Submit</button></div><div class="section">    <h2>Section 2</h2>        <button value="Submit">Submit</button></div>

We can locate an element inside another element using the inside method, like this:

sarah.attemptsTo(        Click.on(Button.called("Submit")                .inside(PageElement.containingText(".section","Section 2"))));

The PageElement class gives us a convenient way to refer to an element on the page which specific characteristics. For example, the one shown here looks for an element matching the CSS selector ".section", that also contains the text "Section 2".

If we simply wanted to find an element with a specific name, inside some other element, we could also use a CSS or XPath locator directly for that:

sarah.attemptsTo(        Click.on(Button.called("Submit").inside("#section2")));

Images#

We can also refer to image elements. Suppose we had an HTML element like this one:

<img src="img_girl.jpg" alt="Girl in a jacket" width="500" height="600">

We could interact with this img element using its alt attribute like this:

wendy.attemptsTo(        Click.on(Image.withAltText("Girl in a jacket")));

Links#

Links are represented using anchor (<a>) tags in HTML. We can represent links in a number of ways using the Link class, including:

  • By the displayed text: Link.called() and Link.containing()
  • By the title attribute: Link.withTitle()

For example, consider the following HTML code:

  <a title="Purchase Widgets">Add To Cart</a>

We could locate this element with any of the following:

wendy.attemptsTo(Click.on(Link.called("Add To Cart"))
 wendy.attemptsTo(Click.on(Link.containing("Cart"))
 wendy.attemptsTo(Click.on(Link.withTitle("Purchase Widgets"))

All the comparisons are case-insensitive and exclude surrounding spaces.

Nested Elements#

Most elements can also be identified by their class, although this is generally only used in conjunction with filtering operations, as a class attribute is not a good guarantee of uniqueness. For example, suppose we had the following HTML:

  <div class="item">      <h2>Item 1</h2>      <button value="add">Add to cart</button>  </div>  <div class="item">      <h2>Item 2</h2>      <button value="add">Add to cart</button>  </div>

Suppose we want to click on the Add to cart button for Item 2. We could identify the <div> containing "Item 2" with the following PageElement:

PageElement.called("item").containingText("Item 2")

Then we could use the inside() method we saw earlier to find the "add to cart" button inside this section:

actor.attemptsTo(  Click.on(    Button.called("Add to cart")          .inside(PageElement.called("item").containingText("Item 2"))  ));
- + \ No newline at end of file diff --git a/search.html b/search.html index c982f5e..ea28ac7 100644 --- a/search.html +++ b/search.html @@ -7,13 +7,13 @@ Search the documentation | Serenity BDD Users Manual - + - + \ No newline at end of file diff --git a/theserenitybook/latest.html b/theserenitybook/latest.html index 9e59fce..dc2f126 100644 --- a/theserenitybook/latest.html +++ b/theserenitybook/latest.html @@ -7,13 +7,13 @@ 404 | Serenity BDD Users Manual - +

404 legacy url

Please use the header links and search to get to the latest content.

Or try searching in the old documenation

If there is anything missing in the new documentation, please let us know or add it yourself.

- + \ No newline at end of file