 Good evening, everyone. Welcome to Introducing Test Flow Charts, a free no-code test automation platform by Narayan Raman. Narayan is the CEO of Sahipro, TITO Software Private Limited. He's the author of Sahi, which is an open-source test automation tool equivalent to Selenium. He has commercialized it as Sahipro. He has been working in test automation solution for the last 15 years. Recently, he has launched the product test flow chart. Without any further delay, over to you, Narayan. Thank you, Pankaj, for the introduction. Thank you very much. Hello, everyone. My name is Narayan. Today, I'm going to be presenting about Test Flow Charts. It's a flow chart-driven, intelligent, test automation platform. Before this, I'm the author of Sahi, the open-source tool. We built a Sahipro as the commercial version of it. We've been working in the automation space for a long, long time now. Recently, we have started looking at, based on how we have been progressing in our own improvements in the Sahipro tool, we found ourselves inching closer and closer towards the no-code test automation tool. Test Flow Charts is an attempt at that. Today, I'm going to talk about and introduce Test Flow Charts to everyone. So what are the problems with the existing solutions out there? What is the problem that we are trying to solve here? Initially, test automation tools started off with pure recorded playback tools. These eventually reached their limitation because it was too simplistic for real-world usage. Then, Sillilim, like test automation engines, even Sahi like test automation engines, they came in. Especially with Selenium and these tools, they were very code-centric. They were too low-level and code-intensive. Because they professed a way of doing automation where you don't use recorders, etc., there was a lot of drudgery. You would do the same thing again and again. Being caught in that world where you're working with locators, you're trying to add weights, you're trying to do interactions with the user interface, it is very easy to lose the focus of your business. Then, of course, there were these other layers that came on top of that, DSLs, domain-specific languages, then BDD, behavior-driven development, and then tools like Cucumber. These actually were nice because they gave a better business abstraction. It was easy to relate to what is happening in the business, but they also had limitations. First thing, even though it was looking like English, it had some structure around it. That was not always very natural for the business user. The end implementer was not really the business user, even though it was purposeful to be. Tools like these also needed a good amount of plumbing code. We needed to implement all the keywords or whatever they are called. This needed programming knowledge and the ability to actually pass in parameters. They were also implemented using tools like Selenium underneath, which combined with the structured approach of BDD and these other tools, it could become more complex to work on these than simpler. Of course, different people have different experiences with these, but broadly, these are some things that people face. Even with Sahipro itself, our journey has been such that this started us as Sahi, the open source tool in 2005. We had record and playback right from the start along with the most things that we needed to actually run it with continuous integration, etc. But it did start off as a record and playback tool, but the scripted recording was exposed as scripts because we understood that people would need to refactor it and structure it in such a way that it is understandable. It fixed the drudgery of manually hand-crafting those interactions and it also, with the recorder, it speeded up the element identification, etc. But at that point of time, it was still not very close to the business. So then we introduced scenario files, which actually where Excel user interface from which you could write your business scenarios and then you would basically record your interactions, then extract our functions or keywords and then you would call them from these scenario files. That is the next step that we took. So that brought in an ability to actually express the business, but then be able to use the keywords that were there already. This is similar to BDD and other like robot framework and other things that are there in the system. Then we came out with a business driven test automation framework wherein we actually said, okay, you know what, don't drive it by recording and then extracting out the functions, rather proceed the other way around because we needed to be able to express the business before the application was built because we wanted to try to see if the in-sprint automation could be done. And there what we did was we actually allowed the scenarios to be written first in the Excel interface along with data and what that data represented, etc. And then from there, drive the... So when it would see that a particular keyword is not implemented, it would prompt you to actually either implement it or record your interactions with the system. And that brought you to actually a fairly business driven test automation process where the keywords were not written a prior. You would actually write your business scenario and then from there go to the actual implementation. So this has been a part of our product for the past three years or more and it has been very well received by our customers. But we still found a few problems and a few areas of improvement in this. One of them was that if let's say there was a scenario wherein we were applying a coupon to a product or a shopping cart, now there were scenarios where the coupon would have expired or not expired. For these two things, we would actually have to duplicate all those steps that were for expired and then put it for another and then tweak a few pre-conditions, post-conditions, etc. And then run it. So basically for each condition that would creep in about whether a coupon is valid or not, it could be that it can be applied only once or it could be only applied if the overall cart amount was greater than this specific amount. So for all these scenarios, we would copy paste the whole thing again, again, again, and then tweak those places where the actual changes needed to be made and then execute them. So it quickly became a lot of copy paste and this was actually happening in the Excel interface. Now of course, another way of doing this would have been to actually put this all into a data-driven framework and put all these conditions, etc. inside the data-driven framework and just pass the data from outside. But then we lose visibility of what is going on inside that framework or who are we taking the correct decisions, is it actually doing the right path given the right conditions, etc. So all that is lost. So it has now become a black box to which you supply data and then everything is taken care of internally. So that actually, so you either had a chance of like, you know, too much duplication or you had another implementation where like too much was being hidden. So we wanted to strike a balance in this so that the actual, so there was a lot of business value and figuring out like which condition caused it to apply the coupon or not apply the coupon. So we wanted to bring that out. So that was one of the things we wanted. Then another thing we saw was we would write a scenario which says, okay, add this product to the shopping cart and then like, you know, apply this coupon. But who will set up that product that needs to be added to the shopping cart? Who will set up the coupon that needs to be added? So like there were pre-appearance steps before that, which we needed to actually do. So say that, you know, hey, create a login as an admin, create a product and then create a coupon for that particular product. And then you apply that thing. So these pre-conditions were also like, you know, we needed to actually do that for every, every one of them. And a lot of times the actual test case would be very small. The pre-conditions would be pretty big. So and that's a lot of implementation that we need to do to do all that. Now, then another thing that we noticed was like data needed to be passed around and data was kind of loosely coupled or like, you know, we should say it wasn't tightly integrated with the overall solution. Data was something separate and then we applied it on top of the rest of these test cases. So we wanted to bridge all this and see if we could come up with something. And what we actually like, we had been trying this for a while now and like what we came out with turned out to be fairly no code. So what I'm going to present here is like, is that the test flow charts thing. So what are these test flow charts? They're a clear visual way of depicting intention of the application. It's easily understandable by everyone and it is built for automation. So why test flow charts? It gives you high visibility and of course like all the reasons that I told you, it is easy to maintain. The actual implementation of automation is fairly uncomplicated and effortless. So there's no coding required. And because of all this, it's quite scalable. So in your team, it is very easy to actually implement automation and, you know, derive value out of it. And so what are the different automation aspects that we cover in test flow charts? We cover the UI interactions, of course, like, you know, clicking set value and all those things. So we have extensive experience in the UI automation space because we built Sahipro and like, you know, Sahipro interacts with desktop mobile browsers. So we have been cross browsers since 2005. So that's one of the earliest products out there, along with Selenium, which could actually do that. So we do those interactions very, very well. So that is available. Then in test flow charts, we have data generation, which is inbuilt. It has automatic form field validation, which is inbuilt. It has automatic precondition matching, which means that you need to specify only the path you need to traverse along with and along with specifying your precondition preconditions in a specific way. And if you do that correctly, then it'll automatically try to figure out all the pre parts and then execute all of that. Overall, in the user interface, we give designated places for all the UI elements, the data, the data generators, et cetera. So it is all well structured. So anybody who's new to the system can easily learn that and do a consistent job of it. It has inbuilt reporting, which is in progress right now. So testflowcharts.com is available publicly. Anybody can sign up. It's a freemium model. So the free version is available. So in that, the reporting is not yet there. And apart from that, one of the things about test automation is not just about executing. What we want to derive out of it is an understanding of how ready our product is to be shipped. And for that, we need to actually bring out, we need to be able to observe how, what is working and what is not working, whether, like, are all our high priority workflows working correctly? What is the significance of the places of those parts which are not working correctly? So this actually helps us take business decisions, go, no, go, et cetera, off the build that you want to ship. So these things can be easily pulled back and showed on the user interface itself, which is the flowchart like thing. And because it is built on the Sahi platform, it can actually work with the browser's desktop and mobile. The current version, which is right now available online, is, it supports only web browsers. So given that as an introduction of what testflowcharts is and what it does and why, what was the motivation behind it, let me get into a demo of this. So this is what the testflowcharts user interface looks like once you log in. So I'm going to create a new project. And so this creates a project and I'm going to create a new flowchart. So let's see what a flowchart looks like. So this is where we start from. What we do is right click and say, okay, so what are we trying to do here? Let's actually try to register a user into a system. It's a fairly simplistic case that most people understand. So we'll do that. So I'm going to say, I'm going to give this a label of a register, register user. I'll also save this and this flowchart. And now we start writing some preconditions, some actions and some post conditions are like, you know, state changes. So for this, we do an add node and say, I want to specify a condition, which is actually user.exist is equal to false. So we want to start off with a user does not exist. So let's do that. Then the next thing we want to do is, let's say that we want to arrive at a particular point here. So we will do, we'll add an action node. We'll add a node and say action. And we'll say, okay, we want to land up at the registration screen. So whatever path you come from, go and navigate to the registration screen. So these orange ones are actually actions. These double lined ones are our conditions. Okay. So now what we do is we add a, I mean, now we add another action, which says, it's the user. So now here you see that, you know, the user has been specified as hash user. And even in the condition, we, we put it as hash user. So that's an entity in the system. We add that, we say register user, and then we'll add another node. So we'll say, you know, action, confirm registration. And these things lead us to post condition or an outcome, which is, which we'll say at this point, user.exist is equal to true. And the outcome is also that like another outcome that we could do is verify user registered. Okay. Okay. So this seems to be a flow that we have created. Okay. So let's save this. Now, okay, I would believe that this makes sense for, for any person who looks at this. It's, it's fairly English-like. Okay. But of course, there are these, this, these syntaxes we believe like it can be easily learned. Okay. Now, what I did was I right clicked and said show paths. Okay. So this shows us the, the different keywords that need to be implemented here. So it says, you know, navigate from the base to registration, register the user, confirm the registration and verify that the user registered. Okay. Now let's go ahead and implement this. Okay. So I'm going to click on this. It shows up the keyword dialogue. And we're going to launch a browser here. So I'll say open browser and you will see that a browser will open up now. Okay. There is the browser. So we are going to do this test on an open cart application. This is an open source application, which, you know, it's an open, it's a shopping cart application. Now, how did that browser come up? So what happened was like, you know, we, we have this TFC engine running on this machine. Okay. And how do you do that? You actually go to the under the open browser run settings. It allows you to download the TFC engine from here and start it. And once you start it, it will show you all the browsers that are there in the system. And you can specify the start URL here. And once you apply that from that point on, whenever you do open browser, it opens that browser in that particular URL. Of course, you can change the URL to whatever you want. And so that did you interact with your application. So here we are. We have the application here. Now let's look at the first keyword, which is to say, which says that, you know, navigate from base screen to the registration screen. So this ad registration and ad base, etc. are screens. Okay. We'll, we'll start. So when we did hash user, that was an entity. When we do at registration, that's a screen. We'll talk about like why they are different or what they are. So let's start recording now. And we want to navigate from base to registration. So we'll just do that. We'll click here. It shows this register thing and we click on register. So we see that those two steps have been recorded. Okay. So we'll save this keyword. So we are at the registration thing. We'll go to the next step, which says register hash user. So it asked us to prompted us to save that. You know, create that entity. So we created that. And here we are the register user thing. And in this, we're going to fill in values. Okay. So let me again, like, you know, let's say it's still in recording. So we'll, we'll do fill in some, some values here. So it says that your user account has been created and all the interactions that we did here have been recorded here. Okay. So we will again, like go to the next step and we'll save this keyword and then go to the next, next confirmed registration screen, which is just this much. So it may have been like, you know, you may have wondered why I actually did a use register user and then a confirm user. That's because that had a form. And like, when we come to validations, we need to be kind of like, you know, utility, you know, bank on the fact that just the form related fields can be kept separate from the rest of it. So I'm not sure if I made sense, but we'll come back to that. So this is the confirmed registration here. And this is the logger. And at this point, like it just shows, you know, a logout screen and that kind of means that you have registered. So what I would do is like, you know, I'll just verify in for the next one, which says verify your user registered, I'll do a lame thing of just like verifying that the logout link exists. Okay. So for that, I could do something like this. This is not an action that you're performing on the browser, but rather like something that you derive from it. So I'll click on add step and say assert and I exists. And here it says element, I'll inspect it. Okay, I'll inspect, bring the inspector and then control whore on the logout. It shows me what it is. And I'll put it into this. And add this. So that's, that's my asset exists of that link logout. Of course, like it could have been better and nicer, but like we'll stop for now. So we'll save this also. Okay. And let's close this. And we will. So you see that all of them look black now. So which means that they are, they are implemented. We can now run this. But if you, if you have ever done this kind of automation, you would realize that we just, you know, registered donate example.com. And if you try to do it again, it's gonna fail. Okay. So for the interest of time, I can say I can tell you that it will fail. So what instead of that, like what we're going to do is do something else slightly different. So we'll go back to this keyword. Okay. Here we see that a lot of interactions have happened. So here I want to, you know, separate out this, this first name, last name, email, et cetera, and store it into the entity of user and also store all these elements, text box, first name, text box, last name, et cetera, along with those, those entity attributes. So, so let me do quick extract. Okay. So here it shows me that, okay, these are all the things that I could extract. I'm going to do user dot first name for that and user dot last name. This would be email, I believe, and then like phone. Right. So we did all that. And these separate things like we can actually put it. So those elements have been associated with that particular entity itself because if you, if you have noticed, like, you know, all user interface elements fall into two broad categories, either elements that are pertinent, like, you know, are bound to a data or they are unbound to the data. So for example, the, the text box where you fill in the user's first name is bound to the first name. Like, so nothing else can be put there. So you always put the first name of the user and it gets bound to the, you know, in the database to the first name or wherever you're storing it. So these elements, we keep it with the first name itself because if you wouldn't use a password, you wouldn't enter a username in the password field. So it's all kept separately. Okay. And these, the, the agree button, et cetera, that we will keep it as, you know, part of the registration screen. Okay. So we put that like that. And then we do extract. Okay. So when we do extract, you see that this particular, all the, all these steps look a little different now. And they say, you know, hey, set value, but the param actually looks like this. It shows that, you know, okay, it is the first name input inside the user attribute and it is taking the value of a user dot first name. Now, what does all this mean? So let's actually look at this. What did we extract? What is it that we did right now? Okay. So this is the, we edit the user. Okay. This is the entity user. And in that entity, we have, we have created all these attributes, first name, last name, email, phone, password, et cetera. Okay. And along with this, we have actually stored the UA element into which it was populated. So for example, first name. Okay. So it says first name input, you can give more meaningful names to these, but it's just like, you know, it just auto generates these things because it thinks that, you know, that's all it can do. Now, the next thing it also does is it actually associates valid data generators with it. Okay. So what that means is during automation, you want to like actually run the same script again and again, the repeatability is a very, you know, very major thing in, in test automation. And for that, what we try to do is like, you know, associate some, you know, some data generator for each, each of these fields. Now you could actually say, you know, give me this text along with some random characters or like, give me this number, like of this size with random numbers, or you could say like pick from this list, et cetera. So there are these various data generators that are available that you can associate with it. And for by default, like we have just put it as, you know, use whatever text you filled in and then add some like min length max length of text here. So that like whatever is filled in the, in the form eventually will look like this. And for email, like this is one of the techniques that you could use. So email, like what we are doing is by default, like we add up, you know, add a timestamp to it with a plus before the ad. So most email clients actually ignore that part. So you can actually just, you know, create newer, newer emails using that, but it'll all land up in the same email address. So for now, like we have done it like this, of course, you could do other generators, et cetera. Okay. So that's what it does. Apart from this, you can also say, okay, what are the invalid, you know, invalid data for a first name. So for example, like I could say that, you know, hey, there is a, for a blank value, there is a problem. Okay. Or there was, there was a limit in this thing greater than 32 characters. So, you know, I could put in, I could put in a long value, you know, this is like, you know, text fit more than 32 characters. So we could add these validation related stuff also along with the first name. So in the first name, we're storing elements that are, you know, pertinent to first name, we are storing a data generator valid data generator along with it. And we're also saying what are the invalid data that, that, that, you know, that field validation should, you know, fail. So those things we are putting here, of course, for example, for an email, you could also do much more, which is to say, you know, hey, emails is a standard format. So it's like, it's part of the RFC. So you can actually say, okay, give me all the suggestions for invalid data suggestions for email. Okay. So this, so it tells you, you know, okay, I have, we have all these like, you know, problems that you could have at is missing incomplete email ID, the domain is missing etc. So you could take these suggestions, you could pick what you want, and then you say, you know, add it as, as validations for that, you could, you could do it like that. So I'm not going to do that because it'll take a long, you know, it'll be a lot of validations here. Okay. So, so we, so that is what we did. We'll, we'll save this entity. Okay. So, and what are these screens? So I click on add registration. So this, you know, registration is just screens. And they actually have elements which are not bound to any data, but they sit in a particular screen or a user interface. Now a screen is a loose name, of course, it could be just a nav bar or the left side bar or anything you want. But it is, it is a holder for keeping all these things. Okay. Okay. So now, so you'll see this keyword and we'll close this. Now let's run this. So you see that it is entering all those values and then like continuing and, you know, doing all that. And as it does it, it'll keep like populating whether it is like working or not working, et cetera. So it finished. And then you can see that you can also like, you know, view the reports, et cetera. Like, you know, there are these reports that are created. So it shows you all the steps that you performed. And you can see like what you did there, you know, so enter value, et cetera. So it shows you everything that you did. So we will be refining this further. Okay. Now we saw that, okay, okay. Specifying a simple path and then automating it is fairly easy. Okay. Of course, we didn't do like too much of object identification, et cetera. So the next thing we'll do in this is we'll see how automatic validations work. Okay. So let's do that. So for that, we'll use open this particular entity. Okay. And we had just added a couple of, what do you call it, error values. Okay. Actually, this shouldn't be here. This should actually be here. Okay. Let me actually take you first to that particular screen and show you what it looks like. Okay. So I can, so we want to actually go to the screen. So I'll say like, you know, run till here. So it'll bring me to that particular point. Okay. So this is also an easy way of interacting with the system. You say run till here and then it'll bring you to that point and then you can proceed further with whatever you want to do there. So, so here we are in the screen. Okay. Now I'm going to just like press continue with, without filling any values. And we see all these error messages and other things that are there. Right. So these are the field validations that are there. If I put a big value, also it will come something similar. So let's actually go back to that entity. And this is the invalid data that we were adding. And this was the error message. So what is the error message I can control over on this. And that thing appears here, whatever that error messages. And I'll put it here. And I know that it's the same one for the blank also. I'm just going to put it there. Okay. So and update this. Now, they put in the invalid data, but where will they appear? So for every UA element, which is a free form element, which is a text box like thing, it is possible to actually make mistakes in that. So there would be some validations around it. And like, there would be an error element also, which is associated with that. So, so what we will do is for this text box input text box first thing that we need to associate a error element. So what is the error element? This, it is the holder of this particular thing. Okay. Now, how do we find that? So what we can do is we'll control over this. Okay. And it shows us this particular do first name, et cetera, and says text danger. So we pick one of the alternatives. If we do it for the last name, let's say, okay, so you see that, you know, it says it as text danger one. Okay. So this is not great because like, you know, we don't want to associate with that index. So what we'll do is we'll control over on the first name. Okay. And that thing comes here. So I'm going to open this up and these three dots and then click on the anchor button. Okay. And then I hover on this particular element again. So it is going to like, you know, give me a relation between these things. So it says it's a dip takes danger near this label first name. So this is an identifier that I can use, which kind of makes sense in the business, in the business way, as I like, you know, from the user interface, you can relate to this. So this is my error element. Of course, I can actually say, you know, hey, highlight it and show me whether it is the correct one. So it'll actually like, you know, that it highlighted there. Right. So you can play around with that like that. So I'll update this. Okay. So okay, let's do one thing. I'll put the UI error element for this similar way, except that this is the last name. I can play around with that here. So and you know, say whether it see whether it is correct or not. So I'm highlighting the second one. So that's, that's fine too. So that is working. So I'll update this and I'll put in some similar invalid data here also. So again, like this is blank. And then, okay, the error message seems to be this. So this is the error message and I'll add another row. And here, like again, I'll give a big value and update this. So I could of course, like, you know, give a comment saying that, you know, hey, this is again greater than 32. So we've just like added a couple of validations here. Okay. And we'll save the keyword and close it. And now we are saying, okay, run validations on this. Okay. So when I say run validations on this, so watch what happens. So the browser comes up, it does registration and then it fills in some value. So it left the first one blank. Okay. And then it said continue. So it found it's seeing an error message. Now it is putting in a bigger value. Okay. It says continue. So again, it found the error message. So the first one, it became fine. The second one is blank now. So it does that. It found the error. Now it went on to actually do that with a bigger value. Again, it found a problem. Now it will go on and try to see whether, you know, whether a valid value, everything is working fine after these errors. Right. So basically it did all the validations for you. You could have put in a bunch of them. You need to, you can add more validations to it and it'll automatically go through all that. And, you know, it'll give you like, we haven't pulled it back into the report here to say, okay, what are all the field validations and like, which ones are, you know, done and not done, but we'll do that. Like you'll pull that back all into this and user interface and show that. So that, that actually like, we just saw that the validations can also be done automatically. Okay. But this is all very simplistic, right? We need like something bigger, something like, you know, more meaty. So let's actually look at another case. So here is something that, sorry, I'm just moving that my camera screen. Yeah, here we are. Okay. So in this, I was talking about a small example of, you know, a shopping cart where you actually, you know, check out a product and then you apply a coupon to it. Okay. So here is, let's, let's pay attention to this particular path. Okay. So in this particular path, this is the checkout path. The first action says that, you know, this is a specific syntax for just login. The reason being that in browsers, because of how sessions are handled, you can have only one person logged in at any point of time. So you either log in as a user, not login as an admin, not login as an admin, login as a user, or be not logged in at all. So in this particular case, we don't want the admin to be logged in. Okay. We are not considering a user rate. In fact, like that condition would also come like when it is ready. Okay. So we are saying the admin should not be logged in. A product should exist. Then search the product, add the product to the cart, view the cart, and then what path do we want to take? Do we want to take the path where we add a coupon? No, we are just trying to first say, okay, just nothing, no coupon. What happens? You go ahead and verify the total. Okay. Now, next, we want to take a path of, okay, I want to add a coupon. Okay. Then what do we do? Then does the coupon exist or doesn't exist? So are you just bluffing and putting in a coupon or like the does it does a coupon actually exist? So let us take the bluffing part. Okay. So we're like a coupon does not exist. The person applies that coupon to the product. Okay. Verify that the product is, the coupon is not applied. Okay. So in this particular case, the coupon should not be applied and then verify the total. So what does the verify total do? So verify total basically like says that, you know, okay, if the coupon had a discount, whether the discount is applied in the total or not. Okay. So let's look at this. Okay. Just just stepping back. Okay. So, okay. So it will verify the total. Now, let's look at another case where the coupon does exist. Okay. And we are applying that coupon to the product. Okay. Now, there is a case where this particular coupon was created for this product. Okay. So is the coupon dot product equal to product? Yeah. Sure. Then like apply the, apply the coupon and then like the corresponding discount should have been reflecting here. Okay. But what if this coupon was not for this product, but some other product? Okay. So then we say that, okay, don't apply that coupon. Okay. So these kind of like, you know, take you through a brief, you know, way of explaining how the system should behave. Okay. And you can easily see like what it is doing here, like by following these parts. Okay. Now, so how do you know like whether the, how do you verify what the car total is? So you can actually do the show parts and then, you know, you can see the data. Okay. So where we say that the product dot price was 100 and because the coupon is not being applied, the subtotal and the total are also 100. Okay. While actually in this particular case, okay, this data we specify. Okay. So we specify this data. We say that, okay, for this particular path, okay, we say, okay, the product price enter it as 100. Okay. The coupon type, we put it as percentage and the discount is 10 and the subtotal will be 100 but the car total will be 90. This is the behavior that you will see, actually, that you know, okay, when you actually applied that coupon, you got a 10% discount. Okay. Now you would start correlating this hash product and hash coupon, etc. to entities, like we created a user in the previous example in the flow chart I showed you, this actually shows, you know, these coupons and products, etc. Okay. So these are also entities. Okay. Now this is the, these are the parts. Now, let's look at this path. It shows that in order to actually do the checkout, it needed a product. So it went down the path of creating a product. Okay. And then for the product, it needed an admin. So it created the admin. So it actually like, you know, match the pre parts and went up to say, okay, this is the path I need to take. This is automatically done by Tesla charts. Okay. So how does it match? So it says products that exist should be true. So it looks for a path where it says product dot exists equal to true. This matches. So it goes up and here it sees that, you know, hey, the admin should exist. So then it like looks for an admin and then like does this. Okay. Now for a, for a coupon, what does it do? So let's pick the case of this coupon. So create an admin, create a product, create a coupon. Okay. So you can click on this. So this is the admin object that will be created. Here is a product of ID zero that will be created. And then I create a coupon, which is for this product zero. Why is this for the product zero? Because we have specified here in the coupon that the coupon path looks like this. The admin should exist. We should be logged in as the admin approach that exists. A coupon should not exist at this point. We should, we should go to the coupon form and there create the coupon for the product and the end, you know, the, the state change after that is that the coupon exists and the coupons product is equal to this product that we have created. Okay. So we have associated this as a coupon dot product equal to product. So when we actually do this, so it knows that, okay, I need this product and like the coupon dot product is, is this product. Okay. So it creates that, you know, a relation and then it'll, it'll go ahead and do all the steps that are needed. Now, of course, all these are like, you know, implemented similar to what I showed you with the, with account, you know, a user account registration. Now, let's look at this, this interesting thing where the coupon dot product is not equal to product. Okay. So let's like actually pick this path. Okay. So here we want this path. Okay. So we want to come here. So look at what this is doing. So it says create the admin, okay, create a product, which is product zero, then create a coupon, which is, which is for this product, it's coupon zero and product zero, then create another product. So it goes on to actually figure out, Hey, you know what, I want a product which is, which has, which doesn't, which is not associated with coupon, this coupon. So it actually creates another product. Okay. Product one. Okay. Then it does a checkout and in this checkout, it is applying for product one, coupon zero. And because of this, it will not apply because this coupon zero belongs to product zero. So it knows how to do that. Okay. And then actually it, it satisfy all these conditions and then it'll execute it. Yeah. Not in time to five minutes. Yeah. Thank you very much. So that, that is what it does. And of course, like once you have these things in place, you can actually do run all. Okay. And it'll execute all these scripts together, like in parallel. So like if you will, so if I were to like, you know, and do this, so you can see that, you know, multiple browsers will open up, they'll all execute in parallel. And then, you know, and give you the reports at the end. Okay. Now going back to the presentation. So what are the problems and solutions that we actually like, you know, saw and fixed in this, right? So the main problem was visibility and repetition. The visibility, basically, we are bringing out the actual, you know, we're keeping it, there's no code in this, of course, the end user doesn't do that. They specified things like, you know, in designated places, the flow chart actually lets you navigate in, you know, understand what, what the flow is and navigate still that by, you know, matching all the three parts, et cetera. Right. So it is the overall user interface is like, you know, you can see the business, business test case in that. Okay. Then we solve the problem of repetition because we added, you know, these data generators, et cetera, it can automatically, you know, run. Of course, like, you know, in some cases, this may not always work. We may need to actually pick from specific values, et cetera. But that is, it is, it is possible to do that. Test creation is auto generated. So there is no effort in that data generation, you know, we give inbuilt data generators. And we also like, we saw that, you know, discount and total sub total, right? So we overwrote that data at the path level. So it'll, when we give an override like that, it'll use that data instead of the data generators thing. Then object maintenance, there was an inbuilt object repository. And we also had the recorder and like objects by, et cetera, with which we could do that. Keyword implementation was with the recorder. So there was no effort involved in that. Parameter passing is automatic. Script generation is automatic. Reporting is automatic. So you basically like do very less in this and you get a lot of effort, right? So this is more on the flow charts, basically like what I said, like, you know, it depicts application functionality, pre-cutting, like express preconditions, et cetera, et cetera, right? So what we saw in that, I'll leave this. So beyond the demo, right? Like there are, what if like you want to use, there are multiple users in this. So you want to add a user one as a beneficiary to user two. So the concept of like hash user one, hash user two also exists, where it is, it'll take the entity and like create multiple instances of it. There is a concept of, you know, numerical conditions where you say, like, if login attempts is less than three, okay, if it is more than three, like lock the same, lock the screen, et cetera. There are complex path matching. It'll actually like, you know, traverse across paths and the paths themselves need not be in a single flow chart. They can be across multiple flow charts. In a project, it will automatically look for all of them. And of course, like reporting, we haven't built that all fully yet. So it is coming. So thank you very much. That was, that was our presentation. I hope you liked it. This is more information about it. Testflowchart.com has a free, free, you know, version also. So you can just like log in and start using it. Thank you very much for the opportunity. Thank you, Narayan, for sharing our experience with us. Thank you very much.