 Welcome everyone to today's session on functional programming by Narmada and Samina, without further delay over to you, Narmada and Samina. Thank you, Trisha. Hello all, hope you all are having a nice time at the conference. So today we're going to do a workshop on functional programming in test automation. So we'll give you a GitHub link, you can maybe clone the repo and you can look into the code and you can also practice it along with us before we get started a quick introduction about ourselves. So I'm Narmada I have around six years of experience and testing. I've worked on various domains I've done manual testing automation and I've also worked on various tools and technologies. I've worked in web web testing mobile testing API and currently we've been I've been working on functional programming for the past one year. And however we kind of used it in our project or in our work, we just wanted to share it with everybody how it's useful and things like that. So if you want to reach out to me after the session please feel free to contact me on my LinkedIn or my personal email. Hey everyone, myself Samina, I have an experience of nine years and I'm currently working as a senior consultant in ThoughtWorks. I have experience in front end the backend automation. So currently I'm working on one of the retail domain where I got exposure to the functional programming with the idea of doing the workshop came from. So if you want to get in touch with me, you can connect me on LinkedIn or my Jimmy. So let's get started to set the context. This functional programming workshop will be like you'll be learning the concepts which makes you to understand how the functional programming works. And then we will be looking into one of the code and where we have a kind of non functional way of writing it and then applying those concepts to the code existing code and making it to the functional bear. So you'll be learning concepts and applying to it to refactor. Okay, so let's get started to get started with what is a functional program. So if you look at any software which is developed in functional programming, how it looks like how different it is functional programming is not something like it's a programming language altogether. It is a style how a developer will develop. It's like like how you will use your code to have more functions. If you look at any code base, which is used as a functional programming style, you will see most of the functions as a smaller chunks of code, which will be more clear. And you will be seeing only two lines or three lines of code within each function. We will call it as pure functions. What is the meaning of pure functions? Pure functions are the small chunks of code where you'll not see any side effects with it. So it will take the input, it will give you the output. The main motto of crux of functional programming is to have these kind of functions where you will not have any side effects. Meaning you will not be changing anything, any state of any variable or any hard drives or emails, all the stuff you have to make sure like it is removed from those pure functions. So functional programming is basically coding in a such a way where you'll be using more pure functions extensively throughout your code. So in functional programming, we'll call functions as a first class citizens, but why? So if you look at a difference between imperative way and the functional way, in functional way, you will treat functions as if like a variables. Like how we'll call variables, how we'll return variables, how we'll take arguments as variables. The similar way, we will be using functions as variables. So that's why first class citizens in functional programming are the functions. So I'll show you how we can define functions as variables, functions as arguments and functions as written types. Before that, you people have done the setup like anybody wants some time to do it. So right now I'm going to switch to my note shell to execute few commands and just to brush you up how the functions look like in the JavaScript. In this full workshop, we're going to use JavaScript as a base language. So we need the NodeJS. So if you look at the repo we have given in the chat, you can look at NodeJS to be installed. Okay. So in functional programming, we are saying functions as first class citizens. Like we are saying functions more or less, we're going to use as the variables. So before going into looking into that, let's brush up some JavaScript functions, how we'll be using, throughout our workshop, we'll be using arrow functions and NMS functions. We'll be using normal functions all this stuff. So just to give you the brush up around basics of JavaScript. So a normal function, how it looks like is like a function keyword. And sample. Add. And let's say, let's take N1, N2. And I'll be having a return type for it N1, N2, let's say. So this is a normal function. If I want to call this function, I'm going to do, I'm going to pass my parameters. So these are all the normal functions will be in the JavaScript for basics and long. And then we have one more level of kind of functions where we'll say, we'll not give any function names for it will call it as anonymous functions. And it looks something of the sort which you have a function keyword for it. And you'll be having your parameters for it. It will be written for you. Let's say some again. So this is just to brush you up on JavaScript does in taxes what we will be using most frequently in our report base. So this is an again anonymous function in anonymous function and the normal functions. What is the difference? You are just not giving any function names. You just use the function keyword and then you pass your parameters. How can I get executed just pass your parameters, whatever you want. So there's one of the way of defining your functions. The other way is like add a functions. So arrow functions. You will not see any keywords like a function keyword. And you just have if it is single liner, no need of opening braces and closing braces. You just written also implicitly given for you if it is arrow function. And if you have multiple lines of code just start putting like having your code inside your braces. Okay. So this one I can say n1 plus n2. And this is an endless function. Arrow function where I don't have any function keyword. I'm just passing my parameters. It becomes a function for me. And then your body of your function. Okay. How can I call this? Just pass your parameters. Okay. So these are the three things which will be a most frequently using in our code base. One is the normal functions and the arrow functions and the anonymous functions. And now we are seeing the infunctional programming. We can call a function. We can assign a function to a variable. We can call. We can pass a function to your admin. We can return as a function as a written type. Right? How is it possible? Let's say I have one function. It says add. Let's say one comma none two is my normal function. I'm going to write return n1 plus n2. And here you're going to see the basic examples of it and how we can implement it in the code. We will see while the factoring the benefits of these things. Okay. So we have to define a function which is add function takes two parameters and returns to some of it. So if I call a method. Pass in it. This is my variable which is holding my function. Right? So if I want to execute that one, just pass. So this is my constant. Now I'm using my constant to call my function. This is how we'll define a variable to a function. Okay. So next we have what functions as an arguments. We need to see how we can pass functions as an argument to the other function. Let's say I have a function called function at multiply. So we are saying this one should take a function. So I'm going to say it will take two parameters and then function. And I want the definition for this one should be I want to apply my function on these parameters. Whatever I'm getting as input. And let me hold that into a variable. My constant. I'm just keeping it as output. And then I want to multiply by two. Hit on output. Okay. Now I'm in this function. I'm passing a function as an argument. Now how to call this function, right? Let's say I'm going to have a constant. I'm going to do multiply. I'm going to what parameters it is taking. Input one input two. I need to provide some function. So here I have defined my function, right? So I'm going to pass it as my function. See, it just passed my function, which I have created on top, which is nothing but my add function inside my function, which is taking that function as an argument. It is executing that function using your input parameters. And then we are returning some operation on it and then we are returning the output. That is what exactly I did. I just created my variable. I call my function with it. And then this function, what we created before, we are just passing it. And it is getting executed, which is passed as argument, getting executed inside your add multiply function. Okay. Is it clear? No. Yeah. So now we have seen two things, which is like how we can use a variable, how we assign a function to a variable. And we have seen how we can pass a function as an argument. Now we have to see how we can return a function from a function. Okay. So for that, I'm going to create one more function. Let's say add division. This one, I'm going to say one, two, add it and then divide. So the definition for this will be I wanted to return a function. So just a return function and it will take what it will do. It will return me the output constant output equal to my num1 plus num2 then divided by two. Return output divided by two. Okay. In this function, what we have done, we have created an add division function. It is taking two parameters. But if you look at the implementation of it, I'm returning a full function. So my definition of this function says take the parameters, sum it up and then divide. So I'm calling this function inside my function and then return it. I'm going to create one variable for my reference. I'm going to add division and then it makes two parameters. Let's say one comma five. It says it is returning me a function. It's returning me a function. So here I just defined a function which is taking the num1 comma num2 and it is returning a function which is performing an option. Okay. Let me redefine that function to pass the parameters. This is correct on your right. Yeah. I'm calling my function. It is returning a function. But that function in turn should return me the output for it. Okay. Did you see anything I'm missing over here? Sorry. Let me check. Okay. So you're doing add division of num1 comma 2 return function of add one comma two. And that is that is returning output by two. Correct. So your add division is going to give you a function. Okay. Yeah. With that function you need to pass two parameters. So can you store this to a constant and then yeah, can you pass it? Yeah. Yeah. Right. But we tried by passing without passing the parameters also. Let's try that also. Okay. So you're returning a function. Right. So you first store it in a variable. You take the return. Correct. Correct. Let me see without passing. I have a global variables declared over there. So now I have this one const add D equal to add division of 10 comma 10. Okay. Now this defining this now let's see add D. Yeah. Yeah. Previously it didn't work. Right. I mentioned. Okay. Fine. So to give you a summary recap. So what I have done here, I have a function which takes two parameters and this function returns a one more function inside that function. What we're going to just taking the sum of these things and returning as this one. So to call that function. I just created a constant where I pass my parameters to it. And then I'm to execute that function. I just call the inner function as well. So it is like that. One more way is to call is like, let's say D one. Yeah. So basically this is how we'll return a function to execute on top of your whatever function is getting called. So this ad division, which is taking two parameters in turn we are returning one more function which execute those two parameters and the written output divided by two. And how we called a constant call add division, then call your add constant and it will go and execute the inside function. Okay. Is it clear? Hello. Yeah. Okay. So can I clear it off or any doubts? Yeah. So we have seen how to pass the functions as a variable and functions as an argument and functions as a return time frame. So next what we can, if you want to familiarize with the function programming, we have to know the impure and pure functions. What does it mean? What does it mean if your function and if your function, right? Your function is such functions where you will see any where you don't see any side effects. If I give an input, it will generate your output. So anything else other than that, it doesn't depend on the time when you're calling it. What is happening with that? So if you call multiple times, it will yield you the same output that is called pure functions. Okay. What is impure functions? Impure functions are something like, let's say, getting a system time. Okay. If you want to get a system time, if you call this, now it will be different time. If you call after one hour, it will be a different time or sending an email. Again, it is a impure function, which will yield you different kinds of outputs with the respect to time. Okay. So we have to make sure like the pure functions will be more in the functional programming where you will not see any side effects and where it will yield you the same output for the given input that is called pure functions. Okay. Now let's move on. Let's say we have in the setup, if you see, we have given a juice shop. Again, we have taken juice shop as a sample app. So in that juice shop, if you see, you can see some products over there. We'll do the application tour as well. Business equipment is like in that juice shop, we have items added to it and now we wanted to start. Development is done. Now we wanted to start automating different rules for the same app. So to do that, and if you see your thinking, right? If you are coming from object oriented programming to the functional programming, it is very difficult to understand in the code, everything will be, you will be seeing it as a functions function. So it does like, if you want to get started from the scratch, you have to think like a functional programming and there are a few techniques which will help you to do that. Okay. So those techniques are like first identify your actions and then identify your calculations and data and the users for it. Okay. So these actions, which depends on time. If you call this time, it will lead to some other put. If you call other time, you will create other output. So we don't want to have that kind of actions to be merged with the calculations. Okay. So to do that, what we can think of like how we can segregate like actions will keep it as separate things and calculations will keep it as separate things so that it will be very minimal changes goes into the calculations. And always you will be concentrating on the actions. So in actions, I can give you an example of like, let's say you have a distributor system and where you have something you wanted to once system is done, some some operations are done, you want to send something like email. So if you're sending email at this time and if you send it again, we have to decide whether the previous email went off or this is if I trigger now it is for the second time generating or what happened to that one, where we have the ambiguity of with the past events, what happened in future, what is going to happen. Okay. For any requirement, if you're going to start with the functional programming, you categories your functionalities in these sections, actions which will have ambiguity or it's going to have side effects, you make those under actions. Okay. So in terms of calculations, calculations are the one where you have very minimal changes and for given input, it will be always the same output what we have seen as a pure functions, those things we have to segregate between the actions and the calculations. And then we have data for any application, we need to have the data right. So keep the data as separate don't include in your impure functions or pure functions and data should be immutable. Most of the functional programming, what it does is like it will copy your data, what do you want to perform actions on and start using it after copying. It's not like directly you start global variables, whatever you have start manipulating that and start doing operations on it. No, we should not do that. We always should do duplicate or copy of your object and then start using it. If it is not possible, if some cases, if it is too difficult to do that, then we can put it under impure functions, but maximum you categorize this way actions, calculations and the data. So if you put any software development or test code in this manner, it will be easier for you where to have the functions are the pure, where to have functions are the impure. So now in our full workshop, we're going to have a juice shop as a sample application and I'll just walk you through how it looks like and if you look at the read me, we have given how to get that in your locals. For that one, you need to have the dopper installed and you can follow that. Should I give some time to do a setup for the juice shop or you people already have your, shall we give some time for that? I think they would have done it. Parallel is Amina. You can go ahead. Okay. Fine. So this is my app where I have up and running in my local and if you look at this, what we have, we have a juice shop, like a user login. We can register a user and login with that user. And if you see here, we have different kinds of juices along with the users, we have your other items as well where user can let me log in with my registered user. I already have my registered user with me. Now in the test code as well, it is provided. You want to use it. You have to register your user and then start using it for your login. Then you can see add to basket. Options. Let's see how it looks like. So now you can see we have this is sampler where you have apple juices and along with the juices, you have multiple items in it. So you can go ahead and log in and add to the basket. And then you can see your basket and do a checkout. When you're doing checkout, you can select your address, whichever is already saved for us. We have done the setup for us. So for the first time login, if you're doing, you have to create your own deliveries, your address and all. Here I'm going to select the delivery speed. And then you have to select your delivery speed depending on your total card price will change whether you are one day delivery or fast delivery. And then we have our payment options. Payment options is again pre-saved card details. You can save it or at runtime. If you want to create your new card, you can create it right now. I have a pre-saved data. So I'm just selecting it. And then once you see your code is added and you can see depending on your delivery speed, your items are added. I can check out. This is the full flow. What we can see in this juice shop. Okay. This is how the juice shop is. Now let's look at a business case. Okay. We got our app developed fully. And now we wanted to test this flow, what we have seen like adding the card, adding the product and ordering it out. So what is my business use case? It says like your juice shop, when your user logs in, they have to see the card empty and then start using their own items, add to the card, then check out successfully. User should be able to check out. So the user journey for this business use case will be what the application told whatever scene it is. It could be typical of that. So it first user logs in with a registered user and get all the items of your juice shop portal. And we are saying like, we wanted a workflow where we're going to add only the juices to the card and then go to your card, check out the items. Then while checking it out, you have to select your delivery address and then delivery speed payment method. And then just validate your card price and check out. Validate for your successful message. Your order is placed successfully. That message we can validate. This is a user journey for our test case, what we're going to do code walkthrough and refactoring over it. Okay. Now if you look at code walkthrough, now the user journey, whatever we have seen, we're going to code it in the non FP way, like how we will use it normally using loops and all right. Let's look into that code, how it looks like. So we have a function. We have a test case where we have to add only favorite juices into it and check out for it. Right. So for that one, what is it? Can you use that the test, test underscore normal? Yeah. So if you check out your get report, right, we already checked in the code for you. And this is a non FP way of doing it. Okay. The first one will see how we're going to automate without, without, without applying the FP concepts for it. So for this, if you see, first we have our, we're going to use Selenium for it. So Selenium 4 we have used and JavaScript for it. Right. So again, we have created our driver and all. And here what we're going to do first launch your application and then log in. And then we have, get all items, meaning it is not differentiated between the use cases. We have to get our products, which are juices. Right. So this one is giving me all items on the list that I have. So in this case, what we have done here, we have taken a list, which is, which is a list for me, which is all products in my homepage. And then I'm iterating over it. I'm getting the text. So my text looks like how it looks like it is having Apple juice and the price of it. And then add to basket with my list. It is giving me juice also on the price also and the basket option also. Okay. So this text, whatever is holding for me is a list of things. So I'm iterating over my full list of items. I'm getting my price and the name of the product. Okay. So here I'm iterating throughout my list. And if the list is having the, if you look at the application, right, some items has a sold out option. Right. So in this case, you will be seeing four options like sold out as different option and the name and the price and the add to basket options. Once you get the text of your all products. So for this, that case, we have if else, if it is a product is three items only. If you are getting a text of three length of three, then you will be pushing it to the new map, which will be a new object for you where you are creating your name and price depending on that. And then we have other one where you have the sold out option. You just take your price and name according to your index and whatever you are getting from the text. We are iterating over full list. Right. We have for loops applied for loops. This is how we normally code in the non-fb then and we look after that how we gonna refactor this. The output of this method, what we have is get all items will be an object which will area of object, which will give me the price and the name of the juice. And next, we have launched our application and then we have get all items and then get juice items of a user Jenny says we wanted to shop for juice items. So this method is getting me among all the items get me juice items how we are getting in this. Here we got full list and then we got the string and depending on that string either it is juice only or the height. This is juice items. We are getting it. So we have applied right now in this case we are taking only juice only items. We applied one condition. If it is matching only juice only then you go get my juice among all products get me the juice item. So the criteria will be again you got your full products and then you gonna iterate throughout your list and if you get the text name of the product and if your product is having ML then you push it to your new new list which is having again juice only items in it. This is iteration again we are doing our all items list. Now next process what we have we got all juice type items and next we are going for add juices to the cart. So in add juices the cart we gonna have the favorite juices over here and we gonna iterate over all the juice items. Then we have normal find the element add to the basket just click on that and it will be added to your basket. Again we are iterating through our favorite juices. Whatever we shortlisted from the all items. Then we have navigate to the cart this is a direct operation which we will go to the to checkout we need to navigate to the cart and this is the navigate to the cart. Then we have checkout cart it is again a normal function we don't have any iterations over here. So just do a checkout with the added items and then once you do the checkout we need to select the address and we have seen in the address if you have already saved your address detail we are just selecting that address over here. Now we have select delivery again at the select delivery we have multiple options. So in this method if you see I'm getting the delivery type and then driver instance of it in the delivery type we have standard if you look at my delivery type I'm gonna select my address still here we have seen like how we gonna work on. So if you see here it is having a type right the one delivery pass delivery standard delivery so depending on that delivery type I'm gonna select one of the options and we are passing like the delivery type of one which is again an array for us we are hard coding it and if it is standard delivery go on to respond to it so this select delivery will give you that option then we have select card and continue we have already saved one of the card so we gonna select that card and continue for it once you into the card level you have to selected delivery speed will impact your total card price with all the favorite juices whatever you had it it will be some of all those things so just verify how your expected total price is coming actual total price and then we have assertions around total item charges displayed and then actual item item charges get bonus points there is one more option like where you can get a bonus point in the sense let's say let's say I have a rule where it says like see for this item I don't have any bonus point because my limit some limit is there which is not meeting so in this case it is not but it should be a zero that is a validation for us okay now place your order and pay once you click on place your order it is again just a click function once you click on your place your order and pay then you will get a confirmation message saying your order has been placed successfully then we have assertion saying that message we displayed once the user successfully do the checkout then we have normal close and driver to close and quit this is the normal flow how we will be seeing it in our non-fb way right this is a normal flow whether if you want to do it in java or any programming life this is how we will do it so how to if you do the method mapping whatever we have seen for our user journey it will give you this kind of launch application we have launch application and then we have login get all items we got the juice type items then add juices to the cart and navigate to the cart checkout to the cart select address select delivery pay and continue on the assertions and the confirmation this is all we have method mapping right now without with the non-fb way of coding so now looks like we have the normal flow functioning now with this test case whatever we have automated now we are getting more data and more business flows for it we wanted to make sure like our existing automated test cases are scalable for the what functional like new business cases whatever we are getting in so for that one we need to refactor like how we gonna do how we gonna handle for the more data right so to understand the refactoring of non-fb way to the fp way we need to understand few more concepts of fp which is higher order one of the major concepts is higher order functions what does it mean like what is a higher order functions higher order functions are like which takes as we have seen which takes the input as a function as an argument or a function which returns function as an argument for a written type is a function a function which takes a function as an argument or a function which is returning a function is called higher order functions so in javascript we have couple of inbuilt higher order functions for us which is nothing but we will call it as a map filter and reduce in map all these operations are on a list in the sense we gonna do it on the list of items so in map what it takes it takes input as your list and it will return you the same length of list so let's say take an example of for I have an input array let's say I have a function okay I have a function which says increment an input okay I am saying or return it as an input plus one okay so this is my function and let's say I have an input array where I will be having the 1 2 3 4 have my input array now what I am gonna do as I said we gonna see the map what map this it will iterate throughout your input array and apply the function whatever you are passing to it on each element so now I am gonna call my map and my input array what I am saying I want my input array each element to be incremented by one okay for this one I have to provide my function I am saying increment okay so what happens here if you look at this I just created my function increment and then I have applied my map higher order function meaning it is taking one more function as an input argument right so this is how we that is why we are calling map as a higher order functions so if you look at this what it has done it has taken each element and it has applied the function whatever we have taken over here so it has taken the first one and it incremented to 2 and it is done for all the elements for us so in normal way how we will do it will iterate with the fur loop and will take each element and increment it or put it in your new array wherever you wanna send it back so the similar way here we have inbuilt map functions which will take the other user defined functions if you wanna do it and whatever it is a implementation for it it will apply for each element of your array so let's say if I want to write it as arrow functions just similar way you can write it it does like take an element and that as I said map will iterate throughout your array each time it will take one element right so I wanna increment that element is how you will do as an arrow function this is like normal function and you can use it this way also this is other syntax for it just to be clear on the syntax is what we gonna use in the refactoring this will help you then we have filter function what does the filter function does filter also again a function which we gonna apply on a list so this filter is like by the terminology itself it says it gonna filter some few things in your input array whatever list you gonna give it will filter some items in it and it will return your back so how to do that okay so let's say I have a function I have my input array as 1,2,3,4,4 okay function which gives me in the array of elements which are even numbers okay even numbers and I need a input for it I'm just gonna write as a return if my input I'm saying even number right so equal to equal to 0 then you return me that input so this is my function which I'm gonna apply using the filter now what I'm gonna do I'm gonna call my filter function input array on top of my input array I'm gonna use filter function where I need to pass my function to it right so my function name is even see it has applied this logic of your function for each element and then it made you the other list out of it which is your input array is having all these elements and then it may cut out of three elements which the size of the list has been changed with the filter function as we are filtering on it so next we have one more function which is reduce function so by the internal it says if you wanna shrink your list of elements let's say you have right now we have seen 3, 4, 5, 6 right so you wanna do a sum of it okay so reduce function will take one callback function and you can it will take the initial value as 0 so let's say I'm gonna write my function which I'm gonna pass to my reduce function let's say summation in this it will take two parameters right input 1 comma input 2 in this I'm gonna say return sum of my input 1 and input 2 okay this is my summation one of the method but we have already now we wanna apply this on using reduce how we gonna do we have our input array dot reduce as I said it will take your it will take two elements in the sense accumulator and the current value in the sense if you're taking this array what it does initial value first value it will take it as 1 and the initial value take it as 0 this function I'm saying to sum it up all the values I wanted to be sum it up so it will pass to this function if you are applying input array and reduce on it first it will take the first element whatever you have in your input array and it will by default the accumulator will be sending it as 1 okay so accumulator will be 0 for it initially the element what you have is 1 and accumulator will be 0 it will be 1 plus 0 so it gonna put it in the normal empty array for you and then it will take the next value 2 and it will go and add to the 1 then it will become 3 and now it will take this 3 and it will go and add to the 3 this is how the reduce will work so it is like you are putting you are creating an object which will be taking the initial value and the element of it so now I'm gonna call my summation and by default it will take the like how we in the normal coding they will write right count equal to count plus 1 and count will initialize to 0 then start adding the other elements to it that's how we'll do it so the similar way here by default it is taking it as 0 let's say I have done summation on it so it has summed up everything whatever we have in our input array okay so it wanted to say like 0 initialize with 5 okay so what it has then it has taken 5 as the initialize value then it has taken the first element and it has added 5 plus 1 and 6 and then again 6 plus 2 it has added and then it continues the chain so this is how the reduce will work to give you one object out of your list of elements these things we are calling it as a higher order functions which will be using the regress linear functional programming refactoring of our code so now we have we have an idea about a few functional concepts like how we are calling the functions as syntax and how what we are going to use it and we learnt few concepts like in functional programming we more around using functions as variables as in arguments, written in types and assigning to the variable now we learnt about higher order functions as well now let's go look into the code which is existing first how we can refactor you applying these functions let me share so I hope everyone is able to see my screen and I hope the font is fine so we already went through this code we somehow gave everyone a walkthrough of how we normally write just a test case flow rate now we so what we learnt or what we understood is functions can be treated as variables they can be passed to other functions and they can be returned as well right so somebody was asking on the chat how does it know that this is going to return a function right so that's the that's the crux of it the return type the data type of this argument of this variable need not be defined there are only two types we'll use only const and where if it's a const it means I can't redefine this I can't assign this to anything else again I can't reassign this if it's a where I'll be able to change the value of that so only during runtime this variable will understand that this has returned a function so now let's start taking now let's start refactoring we'll start applying the concepts whatever we kind of brush through so first what we'll do is we understood about pure functions right so the whole concept of functional programming is to have is to use pure functions extensively so you want to code everything and based on pure functions but that's not really possible you need functions which are impure which need to change the state of something which needs to send an email right so we'll try to segregate out the pure functions as much as possible and we'll so that they can be reused everywhere okay so let's see so first thing let me start with first refactoring all the for loops so a loop is like an iterative way and it always has side effects okay so let's start taking a look so you guys already had a code walkthrough of how this get all items works so before that let me first execute if this is working right so this is my test case let me just run this I have the application running in the background so we'll see the normal flow is working fine all that we're doing is we're picking items which are of the type juice and we're checking it out and we're ensuring that the order is successful that's what we're doing so now we'll start refactoring this so first I'll start getting rid of all our for loops okay so our launch application and our login methods I think we don't need much refactoring here login is also fine okay let's start looking at get all items so we have a for loop which is like finding each item and performing some actions on every item but at the end of it what do we want we are returning a list of object okay and what is that object that's an object of name and price something like this so this is what this function returns so we want to achieve the same thing without using this for loop so let's say so let me take the whole thing I leave the find elements because this is anyways in the same configuration let me start with this loop right if you look at this these are all simple calculations they'll always give you the same result based on your input if you give the same input you'll get the same output for these so let's combine these so we are taking juices so let's do since we want since we want to return the same length as that as what we are giving as input we'll use map okay so to map we saw that we can pass one function so let's say the first function I want to pass first you want to get the text okay so let me do this so let me write an arrow function that says element and this is nothing but it's accessing each element of your map and I'll do element.getText but also there's a time check I think there's like 30 minutes left let me let me start using our already refactored code and maybe start explaining because it might take longer time to run it in debug mode and refactor on the fly so let's look at this get all items let's compare these two methods okay ideally I should be so the concept is ideally I should be doing first to the map I should be getting the text after I get the text what are we doing we are splitting the values okay so say I'll do another thing and I'll do again juices.map again the next function is split okay some type of split then we are again getting another list and we are saying this time you based on one kind of criteria you map it to an array of objects okay so let's say that function is something like map to array okay so if I write a function to split based on this and if I write a function to you know take out this map and then if I apply to the to the same I should apply okay first I will apply it on juices then values to I will apply to here and values to I will apply here okay so this way I'll be able to get the final result but if you see I'm like kind of using map three times right so one other thing which you can do in functional programming right like there are a lot of user defined libraries like there are a lot of libraries which JavaScript has to perform these higher order functions okay like for this workshop we use lambda so what I'll do is we'll have this we'll just import lambda and so that we can use the functions from them so if you look at get all items one second yeah if you look at get all items what I'll do is I'll first get all the text okay using I'm using a promise because I have to wait for each element to get the text okay and then what I'll do is I'll use a pipe function a pipe function is used to is used to combine two functions okay the output of this function will be given as the input to this function so let me repeat that what we saw was we have and might be going a little fast right so first we have getting all the text after that we are using almost three times map we are using map three times to perform two actions right split and map to array so instead I'll combine these two functions to one function because the output of this is the input to the next kind so for that reason I'll use a function called pipe okay so in pipe I can pass both the functions whatever I want and map relevant values I will I will write my custom defined logic right today it can be something tomorrow it can be something else so I'll write a logic for that okay map relevant values and I'll maybe shorten the long text like I'm reading through the array and everything because I'll just reverse it and get the values based on the index I think that this logic was working for this so we can use this so I'll combine these two functions using pipe and this one function okay I will execute it on this map of choices so if I write it without I'm going to write it will just be this dot map of one function so in other words say this is this is a list of all the text then we again got a list of text then we are getting the list of object okay now this and this we are combining we are combining these two functions okay using pipe and we are passing instead of these two lines we are just directly going to do values dot map of the one function and the list okay this way for the same length right I'm getting the output so let me let us see how much we are one second so let's look at this code again so what we have done we have instead of this loop we have converted it into map okay next we look at the next next map where next loop where it is used so I think get juice type items again what we are doing here is based on the type of type of the parameter right we want to return a certain function and we just saw that functions can return functions easily so how can we write this so we'll write it in this order so say I will have get juiced items I'm taking the list and I'm taking a function as an input and I'll return f of juices now what I'll do I will define this I will define where this has to be executed one second yeah so I'm saying sorry I'm just keeping two functions okay and I'm saying return that function right so I can pass this function as a parameter now what I've done in the test is get juice type items I'm taking a list and I'm passing another function okay and in this function what I've written it I've written is I've asked it to execute this function okay take juices and take f and return f of juices that is return the execution of this executed in this context itself okay so what will happen if we look at this again get juice type items juice prices comma return items which are okay this function itself I will pass in the argument this is one way of refactoring next add juices to cut okay so what were we doing earlier right add juices to cut let me use this yeah so here what we are doing is we have a sequence of operations right we have a sequence of steps based on the based on the juice name okay based on the name I'm first taking an element and then I'm finding a button which is below that element and then I'm navigating to that element and then I'm clicking on the element so I think during this you would have seen that all these basket items are not very close to each other right one second so if you see I want to click on this add to basket for multiple items and I definitely have to scroll because there are a lot of items below under like in the bottom also so what we have done here is based on this name right we are going to we have a sequence of operations but all of this is async operations right they're all we have to await for it to a if you want to like to a map right you cannot send an async operation like you you don't use it on async functions right on promises so how will refactor this add to add users to cart rate so I'll write a custom defined function I'll write an async for each okay your for each little your ideal implementation of for each right it will not have this await it'll just be index loop around under the length of index plus plus and it'll return the callback function but now what we're doing we're adding an await here so if you use an async if you write a custom defined function like this then you can then you can pass it to this for each so the juice names what I'll do I'll pass it I'll use an async for each I'll put the juice names and I'll put the entire function I mean I'll put the entire logic where based on the name it has to get text and then it has to click on add to basket it has to scroll to that basket and then it has to click so this is an impure function but still we will try to you know get rid of all the loops so for that purpose we'll refactor async operations also this way for each loops okay next let's look at what's next if we look at our test case we did this we did navigate add juices to cart navigate to cart I think there's not much refactoring here checkout cart also I think there's not much refactoring here as well select address and select delivery I think there are single actions we don't have to refactor then select and continue there's no loop here as well we have a set of calculations right we want to first calculate the expected prices so we calculate the total price right so all these things are impure functions right and impure functions all your calculations are always pure functions you give addition 1, 2 you will always get 3 no matter who calls this based on the type of the argument this will always return you the right values so let's see how we've written this here so what we okay first we'll look at how we are doing it here we have items and we are iterating through each item getting the price of it accumulated get getting the total and then we are returning the price right and similarly we are getting the delivery charges because I think the total price is item charges plus delivery charges plus the card price so even for delivery charges based on the type of delivery we are returning some value so how we can refactor this right we'll refactor this because we are using again loops to iterate through all of this so let's look at that here so get expected total price so first item total same thing whatever we learnt right reduce so you give it you give it an array you will get back an object right you'll get back a single value as the return item so you are ready to pass an accumulator and the initial value your list and your accumulator so I am just writing items.reduce of accumulator comma item where accumulator is equal to pass float of item plus price and this is my initial value so the same concept as what Savina explained to calculate the total price so we'll use the same thing and this reduce to something this simple right you don't have to iterate through the whole thing next the delivery charges you can use ramda functions you have like ramda.condition where it will give you the respective value based on based on the text based on what if you pass on standard delivery it will return you this value this is similar to a switch case but why we are using ramda functions is if you look at the documentation they would also mention the same thing the ramda functions and also they'll try to keep the data immutable they'll always so it's very safe to use ramda functions when you are using a functional program then I think bonus points is quite refactored it's a simple calculation so it is the same thing next let's look at what we have more in the text case I think we have only so much right so let's go back to our slide is this much amount of refactoring enough so all that we have done right now is get rid of for loops but all our other elements all our other methods and actions remain the same now why are we saying apply functional programming how to apply this to this test optimization we have not yet started that concept so if you look at our test case right it is completely following only the user journey that is a must you have to follow the user journey you have to first perform login then you have to perform cart operation right but how to reduce the amount of coding lines and also how to keep maximum pure functions and how do you design a framework for when you are using such concepts so let's look at that let's go back to our presentation so whatever I have right now I think everyone is familiar with them so now I will try to segregate them into three layers which makes sense to my test case so I will have a business layer and I will have current operations and then I will have item operations and I will have array builtins so what I am saying is I will try to keep all the business logic at the business layer I will try to keep all the current operations at this layer item operations at the item operations layer and array builtins here now what I want to achieve is I want to have a business layer functions as pure functions so that I can reuse them maximum also I can add them at any point and I want the business layer to be the top layer so what that means is this business layer should only be affected by the current operations right and my current operations should only call methods from item operations and all of them can call array builtins this is like required for everyone all the functions can call these any number of calls to these functions would not be harmful but too many but if you are passing the same data let me annotate sorry so if you are passing the same data throughout rate so add juices to cart so get all items will be sending to the cart and again the juices would be sent to calculate the total price again to calculate the delivery speed so the same kind of parameters will be sent again and again to different methods and also I have to have and also there is another advantage which we will cover so let's move forward yeah and I will also have some methods which don't fall into any layer that is also fine you may not be able to segregate them exactly as in cart operation or as a business then we look at what are the practices we need to follow to make it a very good functional programming style in your test automation framework also so first you always separate out the business rules as functions so it's easy to use in your test case so if your test case is saying test that item total has to be the sum of all the items added that thing has to be a separate function if your business rule says for so many for so much of your cart item you receive so much bonus points that is also a function always separate all such things out as functions so that when you have changes in the requirement you can easily update them okay next use the call graph so what happened is you use the call graph you will be able to identify if you are passing the same kind of data again and again to functions we often tend to do that in a lot of in selenium code especially like when we are automating web pages we want to carry the data from the first flow till the end and we end up passing that user journey completely from the beginning when he selects the juices I keep sending it until my last step which is to calculate the total so it's fine to send we of course needed to calculate the total but reduce the number of times you are sending it then always extract calculations from actions as much as possible we won't be able to do anything to click text all of this they are synchronous operations they have to happen one after the other but anything which you want to perform on that text after get text or anything which any type of calculation which you want to perform you separate it out you keep it on a different module or you keep it out of different functions so that you can pass that function in any of your test cases or wherever it's required then keep data immutable this is very important because say if I am using juices throughout I need to ensure that I am not changing it if one of the function in between changes my juices value rate then my test case actually fails you will never be able to your test case might be passing but it's actually not finding what it's supposed to do it's not testing what it's supposed to do so always try so what we recommend is what FP recommends is you copy the data when you get it inside the method and you make a copy and you send it back you always take a copy of when you get it and also when you send it out and avoid implicit input and output ok so avoid calling a function as add of 5 plus 4 or add of 6 plus 5 always try to I mean avoid always pass it as argument don't keep passing it as explicit arguments then refactor all your methods to generic names this is important when say your juice shop portal will now be used by someone else like your business says they want to sell some other items right for such cases always ensure that they are any ways modularizing with any ways separating out the calculations as much as possible keep generic names for them so that they can be reused ok we'll see how we are achieving all of this and duplicate code so in web automation I think we always do iteration right we always say get a list of elements do so and so and so again we do get a list of elements do so and so so such type of duplicate code always try to avoid this this is where we will have bugs in our automation framework so with this in mind let's try to refactor so let me just this changes so this is our first refactor method where we have removed all the loops next what do we what are we seeing which is you know the major issue here is we are passing driver to every single function ok we're passing driver to every single function so to avoid this what we can do is we can pass it to one function and that function first let's segregate out the functions so we've already identified water cart operations water item operations right so I'll put them in different modules ok I'll have a business layer then I'll have cart operations layer then I'll have item operations and user operations so in the business layer I'll keep only my business rules ok which is expected delivery charges and expected bonus points we went through the code for this all then in cart operations we'll have cart actions and cart calculations ok we'll separate out the cart operations also as two different layers which is cart actions and if you look at it actions right what are we calling actions something which is impure so in all these you know click get text we click navigate we can't help but it has to happen one after the other so if you see our calculation our actions will need the driver it'll always need the web driver because they're doing actions on the browser whereas our calculations will never require the driver we're not doing any impure activity here so these methods can be ok then you also separate out the item functions actions and calculations so item actions and item calculations now after I've put the method in their respective modules right now I would I would ideally just export this function ok and I would call this function in my test case I would just I would import the function so how ok for those who are not familiar with JavaScript right so let's look at the cart actions module so here what I'm doing is I'm returning I'm having one constant cart action of methods and I'm exporting that whatever you export ok you'll be able to import in your other module so all that I've done in the test case is I've imported that ok cart action methods I've imported I will tell you how I've written this right so my cart actions earlier what was happening I was sending driver to every single function whichever had a cart operation because they were all operations on the browser so what I'll do I've put all of them together in one file right I've put them I've put all these functions in this and I'll write a parent function ok my parent function is nothing but cart action methods you know that you can store the function in a variable so this variable what it holds is it's a function which returns a couple of functions ok this is your higher order concept we have a function let me you through that again we have a function ok and inside this we have multiple other functions but they will be executed only when they are called always keep that in mind you can keep writing function inside function inside function but they will be executed only when they are called so right now I'm not calling any of them I've just defined all these functions inside the parent function and I'm passing the driver to the parent function level so to each of my method I don't need to pass driver each of the method only needs that particular parameter and driver is globally available to all the functions within this function ok and in return statement I'm writing return all these ok just like you would return constants or you would return an internal string you just return all of this that means once so let's see how this works right so now I'll say can't actions equal to await can't action methods of driver so what I've done I've imported the can't action methods from can't actions and I'm saying can't actions equal to await can't action methods of driver is in a single operation so I'm passing driver and this thing will so now so now my can't actions will hold a function with the driver with the driver as the parameter ok and each function in the can't actions I can call it as can't actions selected items any function I will call it and when I call this is when it is getting executed only when I'm calling only when I'm saying can't actions select items and check out this function will get executed which is located one last time I have can't action method ok this is the parent function I am passing driver as a parameter so the driver parameter is available to all the functions which are written within this and this function returns the functions which I want to access from my test class or any other class ok sorry test module so from this module I will call function dot this function that time it will execute this until that it will not execute that function ok so when you combine functions like this so now what happened I don't have to pass driver to all of the methods which are performed from can't actions so I'll just say can't actions select items and check out I'll say user actions dot select address similar to can't actions I have written for user actions and item actions ok and if you because in user actions again my common is driver to all my action classes to all my action action methods the common element is driver ok and to all the calculations a data is similar right for all your can't calculations you need the list of can't items so ideally all of these calculate expected total of this calculate expected total of three was always taking my can't items again so here when I'm passing this can't items what I will do is I'll I will say can't items too and I'll say here I'll say const can't items equal to can't items do dot slice ok so what is the slice a slice returns a copy of this array ok so instead of performing all the actions on the same array you take a copy of it and then you work on way this is this way you'll achieve immutability this is very important so that there's nothing wrong with your program you'll find very less bugs if you follow data immutability and pure functions extensively now let me go back I may go back to the test case we did this for actions and we did this for calculations and if you look at rules rate I kept it as it is I don't have anything common to send to these functions and all so keep them as functions itself and export them so that and import it wherever it is necessary ok and rest of the things and also one more thing which you can do is you can rename your functions so if you look at some function which we have taken ok all these are constants ok fine then also so from this cart actions rate we are exporting cart action methods now say I want to use a different name for this rate here I am saying cart action methods because I have imported it now I will say import cart action methods as cart actions ok this means I now if you see this doesn't have a reference so I have renamed this method here so in your test case what this helps you is this helps you in writing your user defined names you can however it makes sense to you right this would be a juice cart for you for this test ok so this would be juice cart actions this way your test case will also be quite readable ok let's go back to the ppt now the client says they've decided they've changed the bonus point logic they've decided to give it only for the cart price which is above 1000 so for this what we'll do since we have the bonus points as a separate business rule for any business changes we'll be able to change only here and it will not affect our test case your test cases will have minimum changes ok then let's go to the concept of currying so currying is nothing but let's say you have a function which takes multiple parameters so we wanted to let's say that function can use all the parameters or other functions which will use only the few parameters from it so it will be like the currying concept is like to make sure the transformation of the multiple argumented function instead of using multiple things return a function which will make use of other arguments let's say your parent function is using three arguments the return function will make use of one argument among three but you can call the parent argument to the one and in turn the second function will call the third function which will make use of the third argument so the concept is called currying so how it is helpful like in the currying it is not a language it is giving you a support how you define your functions when you are calling from the other methods and all how you can eradicate the repeated arguments passing from one function to other functions to do that the currying is the one which will help you with that so in this case let's say you the rules to apply for the currying are more generic functions on the top and what data is specific let's say I want to say hi to the array of elements array of names so it should be like the first one should be generic message let's say I want to greet each person so here generic is a message let's say hi, hi is a generic and I am going to make this more specific to the name so the name should be at the end and the generic method should be on the top so this is how we achieve the removing of the repeated arguments to pass from one function to the other functions instead you break it down you have a function on top which is having a single parameter and they return a function which will take the other second parameter and in turn return the other functions whatever functions you have like that we can make use of removing the repeated arguments let's just look at the concept of currying with an example so that you are able to understand if it is used in the framework like overshooting the time for instance Samu do you want to do this or shall I sure I can do it I can share my screen yeah yeah you are able to see my screen so let's say if you want to have a function which takes the arguments usually we are having something of this let's say 2 of a, c so this is the function which is using making use of the arguments and instead of this it will be returning a plus b plus c so this is a non-curried function if you want to curry this function the definition by definition we wanted to have a function which makes use of a single argument I am sorry to interrupt you we are slightly over time so how much more time would you require yeah just this one concept and I think we will find it okay yeah so this is a function which is taking a single argument and in turn it will return one more function which takes the other argument which is nothing but the other argument and then you have one more function which will take the other argument so this is how you can achieve how you can remove the argument let's say this a nothing to do with the b so the dependency of the arguments we can remove using the currying function so this is how you can do it with your currying concept so I think we are just show up in the code okay so here we don't really have a use case where we can demonstrate currying with this current test case but what we kind of did is our maximum best possibility for the sake of this workshop to explain we try to write one function using the currying concept but here we are using so this is function a which returns function b which in turn returns function c so to call function a to call filtering I need only I pass the parameters like this just notice this I pass the parameters one after the other and all your user defined libraries they would use the currying concept this is a huge concept I think we are over shooting time let me just go back to our slide so after so I think now we completed the function programming like we have created it into different players now what is the major benefit right your everything is in terms of functions so you can easily change them like whenever your business expands all your operations can easily handle that and what is it more suitable for if your test automation framework needs to test a system which is like a very data heavy you have a lot of changing data like this juicer portal say it as mantra or something like that for such data heavy systems you can use this and also for concurrent systems so parallel execution for things which are the promises you have to wait explicitly but for all the calculations these can happen these are all if you see they are passing functions they can all happen in parallel so this way you speed up the process okay then there are a lot of other fp languages JavaScript is a language which allows even the non-functional way of programming even the object oriented way but there are pure functional languages like Haskell and closure which you can explore and it will be very interesting to work on that one of the some disadvantages right we don't use loop iteration so writing a recursion for small pieces might be like a little time consuming and complex and data immutability effects performance so what we did is we always copied made a copy of an array and then we performed actions on it so that would take a hit on the performance but if it's not taking a hit you can leave it if it takes a hit then you can think of refactoring that but it would give you a bug free code so then some of the references there's Eric Norman Norman's croaking simplicity and other YouTube videos and a lot of blogs on functional programming we find it majorly useful to automate a very dynamic dynamically changing website and things like that please do check it out thank you that's it for the workshop thanks for attending