 Welcome everyone to this session with Atmaram. He's also known as ATM tells me from way back. He's been in the testing space for about 15 years. And today he's going to be talking to us about APM Flutter Driver, a use case demonstration for us. So looking forward to that. Hello everyone. So today I'm going to talk about Flutter APM Driver. Now, I believe many of you might have done automation previously, right? Any sort of automation, let's say Selenium, APM or Flutter or any other sort of automation. Some might have used Cypress or any other automation. And what do you think automation is easy? You can quickly raise your hand if you think automation is easy. Okay. So many, many times we hear from the people who code like UI automation is easy. And in case of mobile applications, because it's just another mobile application, right? Mobile application in the sense the application is made of screens. And the screens are made of elements or the screens are made of some sort of objects that you drive and you drive those objects through drivers or any other technologies that underneath framework provide. There are so many frameworks available, right in the market, and that makes your job of automation easy, right? But in case of mobile application, application can run across many platforms. Many platforms in the sense when you talk about mobile application, many people might be using Android, other people might be using iOS. Now it depends on case to case basis like what is your target users. But most of the times you might need to cater to both Android and iOS applications, right? And your application might be running on both Android as well as iOS. And what if I say this application is built with some third party components. Third party components in the sense these components could be some sort of third party libraries, libraries that are made with some third party screens as well or third party UI components as well. We often come across these cases, right, like these applications. So if it is a simple application, it could be just created with some simple, simple libraries, but there could be libraries included into the application which are having these third party screens. You might have, you can relate it with the react native applications that if you might have used. In case of react native applications, a react native application could be embedded like a web view into the native applications or there could be a web view embedded into other applications. How many of you know Flutter? Just raise the hand. So Flutter is similarly the programming paradigm or it's a framework where you can create application for cross platforms. And similarly, the similar case arise with the Flutter applications as well that these applications are having Flutter screens as well as native screens. Now, how many of you still think like UI automation is easy? After hearing this complexity is about mobile applications. Okay, so the talk which I'm going to talk about is about one such use case, which is APM Flutter driver. APM Flutter driver is a APM based driver created by community for such kind of use cases only where application is made with third party libraries and application could be run across many platforms. And application has a native screens as well native screens in the sense application has Flutter screen as well as application has native screen. So before jumping into the talk, I'll talk quickly about myself. My name is Atmaram Naik. I am working at Kodo Technologies right now. I've been maintaining an open source tool called as a core. This tool is used for data generation as well as stubbing data or stubbing APIs mocking APIs. It's used for multiple purposes. We have been using this tool. I'm passionate about writing good code. And here are my Twitter handles, ATMNK9, my LinkedIn profile also has ATMNK9 and I go on GitHub by ATMNK9. So I have been maintaining open source contributions with GitHub at ATMNK9. Do tweet about the talk, do tag me if you find this talk helpful. So let's jump to the use case. Application use case. So for simplicity, what I have done is I have reduced this use case into the smaller application. So let's talk about this use case first. Use case is like your application is made with Flutter technology. And now this application has some native screens as well. This native screens could be because of third party libraries or because of native application features. Or there could be native interactions with the applications. So that is the use case. And to cater this use case, I have created a modified counter app. So counter app we mostly use for our demos and all of those purposes. But I needed to modify this counter app just to cater the use case. Now how this modification is a modified counter in this modified counter app. Unlike the typical counter app where you click on add button plus button and counter increments. Here you need to purchase the counter purchase in the sense like when you click on plus button, you need to pay 1 rupees to get that counter incremented. Now what does that mean? It means it integrates with either native payments or it either integrates with payment gateway. So for this demonstration purpose, I have integrated this counter app with razor pay payment gateway. So we will be using razor payment gateway. Now this application screen, which is the counter screen, which is made in Flutter. And this application, because it is made in Flutter, it can run on iOS as well as it can run on Android. So that's the use case of the application. On the PrimaFace here, it sounds simpler. Any other application or any other application. So let's have a quick application demo. So what I'm going to do is I'm going to demo the application. I have iOS simulator. Now this is the purchase counter application that I'm launching. So it has launched the application. Initially you see counter is zero. Now when I click on plus button, it launches the razor payment gateway screens. Now first screen in this razor payment gateway asked me to enter my phone number. I'm just putting some dummy number. And of course an email ID. Just putting some dummy email ID. Once I proceed, I need to select payment mechanism. How I'm going to pay for this counter. So there are two payment options right now. Pay using card or pay using net banking. So for this use case, we will be paying using card. Now it is asking me card details. These are not my card details. This card details are generally provided by these are fake card details. These are provided by payment gateway generally. Now once I click on pay. There is a screen either I can make this transaction successful. This is a test purpose screen that razor pay test sandbox or razor pay test environment provides like I can make this transaction successful or failure. I'll make this transaction successful. And I can see a payment successful message and the counter is incremented to one. So this is the whole demo of the application. So, again, looking at the application, it looks simple like it looks like any other mobile application. That's that's the beauty of the beauty of mobile applications or flutter applications as well like you create cross platform applications and this flat. These applications can run on both iOS and Android. But let's see what it means by this application. So now jumping back to the presentation. This application demo we saw. What do you think what would be the test scenario in this application what what we will be testing in this application will be checking if purchasing a counter increments a counter or not. So that's what we are going to check here. And what does it involve like what does it involve while we are doing this or what what will be the steps for doing this. So the steps for doing this would be like click on plus button that we did when the counter value is zero. Enter your details like email phone number select payment method the one which we selected either pay by card or pay by need banking. Then we entered the card detail and we decided whether to make transactions successful or failure and expected behavior out of the application is like counter value should be now one. So that's that's a simple test case that we see out of this application as well like I have an application and this is a simple test case I need to automate for. Now, when I'm going to automate this particular test case, it seems simple like looking it as a black box application it seems simple, but to understand what complexity it brings. Let's see the internals of the applications. So this applications counter screen the first screen that we saw where we saw zero as a counter value and one when it incremented and payment successful that screen is made in Flutter actually. So that screen can run across many platforms. Now, when it came to other screen which were provided by razor pay payment gateway library. So we have added a razor pay Flutter SDK library for integrating this application with razor pay. Now, what what as this library brings as a challenge to the to the floor is like when people started developing in Flutter. The screens that were created natively in Flutter were very well good for all of these automations but Flutter was new into the market and there were already native libraries created for many platforms the same was the case with razor pay. So what this third party library started doing is they have started wrapping their libraries into the Flutter library. So the Flutter uses a programming long language called as a dark and that in that dark language you need to write that library. So they what they did is like they actually wrote a dark base connector for this native libraries and they bundled the native libraries into the package of package of Flutter based library. What does that mean is this library is nothing but using the native features only but it's just a bundle library. And the screens obviously used on a razor play flow are now a native native screens and not the flutter screens. So many of you might have used already used. Flutter driver which comes if you have done flutter based automation you might have used flutter driver to do this automation for flutter screens only right. So when you have only flutter screen you can use flutter driver very well to automate this flow but when there comes this native screens what you can do. So that question bothered me when I was doing my pet project and that time I was integrating with such third party libraries which we are having this native screen that question bothered me how do I test this thing. How do I test non flutter things in Flutter application. So that's that's what the challenge we want to understand. So home screen is made in Flutter and the locators for this home screen are flutter specific locator. So those who have used Flutter automation might understand there is something called as a accessing by value or finding by value key or finding by text or all those mechanisms in Flutter screens is slightly different. And the result based screen since these are made in native screens for Android you use different driver for locating the element for iOS use different driver for locating the elements. So locating the elements on native screen need to be done differently and locating the element on Flutter screen need to be done differently. So that's the challenge that we have right now over here. And when we talked about Flutter driver Flutter driver has a really good abilities when app is purely made with Flutter screens. Because Flutter driver is Dart based driver and what it does is Flutter driver is suited for applications which are made in Flutter only and hybrid apps are difficult. So that's that's the problem with Flutter driver like you you cannot use hybrid applications for automatic Flutter driver and running this simultaneously on device farms or multiple devices simultaneously is also not possible with Flutter driver. So that's that's the that's the problem with Flutter driver. But underneath Flutter driver uses a very good technology called as a Dart VM or Flutter VM that VM can control the application on on some on some protocol. So that VM protocol it is called as that protocol can control the application. So that is very good part of this Flutter driver. Now, let's talk about APM Flutter driver. So APM Flutter driver is APM based driver it is different from the Flutter driver we just talked about. APM Flutter driver is APM based driver and underneath APM Flutter driver also uses Dart VM service protocol. So it has all those abilities that Flutter driver provides some of them are yet to be developed but it has most of the abilities that Flutter driver provides. And since it is coming from APM community, it supports native screen that APM provide so it supports native screens as well. So that's the power of APM Flutter driver it supports dot based dot based applications dot based applications screens as well as native screens and supports many thing that APM supports there. There is some question from Pooja Shah to everyone. Let me have a quick look at this question. We have been tried switching between native web drivers while using testing offers. So widgets Flutter and we were talking about Flutter screens right Flutter screens are made with widgets and these widgets can be located using value key and those keys. So that's about Flutter APM Flutter driver. Now to get more about how this APM Flutter driver internally works. Let's have a look at a diagram. So what APM Flutter driver provides you is it's provides you the context of the application. So whatever Flutter screen you have, you can have a context, which is called as a Flutter context, which you can see on the left side of this diagram, which is there in blue. So Flutter screens you can you can automate in Flutter context and native screens that you can see on the right hand side of the diagram. Those can be automated into the native context of APM Flutter driver provides you the ability to switch those contexts. So in this case, here, when we are on the counter screen, we switch to the native screen when we click on plus plus button and that's why we switch to the native context as well. And when we are done with this entire journey of razor page screens, like when we do the success, which is the bottom left bottom left screen in the green zone when we click on success, we switch back to the Flutter context. So that's the crux of the Flutter APM driver in Flutter in Flutter APM driver. You can, you can switch the context from right side native screens to the left side Flutter screens. Now how does that happen and how we can code for that. That's what we are going to see in this course demo. So now I'll be jumping on to the demo of the code. Many of you might have used mostly people use Java right for automating things Java or any JVM based languages right. Maybe Java or Kotlin, some people use some people use some people use other languages as the JVM based language like groovy, right. But here I have used TypeScript since this APM Flutter driver is readily available in as a as a Node.js package. So underneath, we are using Node.js. So Node.js is similar to any other platform like JVM is a platform for writing Java based or bytecode based code. Node.js is a platform for writing, writing sport, which can be transferred into the JavaScript and TypeScript is a superset of JavaScript, which gives you type safety. So you can relate TypeScript may very well with the, with the Java as well. So here we have used TypeScript. So in any Node.js project, you will find package.json file. So this package.json file. So the way you have the way you have this Maven POM file or gradle in case of gradle build.gradle file, you have package.json file where you define your dependencies. So here we have added these dependencies, WDIO CLI. So we are using WebDriverIO, which is again driver automation tool, which gives you simpler interfaces for automating for drivers. We are using APM 2.0 beta and we are using APM Flutter driver. So this is the library that we are using APM Flutter driver. And there is one more helper library created by the community, which is APM Flutter Finder. Yeah, so this APM Flutter Finder and APM Flutter driver. These are the crux of this libraries that we are using. These are added as a dependencies and there are added other dependencies as well. So dependencies are like runtime dependencies that you add in Maven or your build.build gradles. So we have added WebDriverIO. Chai we are using for assertions. So in case of Java-based projects, you might be using Hamcrest assertions or you might be using AssertJet assertions. So here we are using Chai library for doing those assertions. WebDriverIO provides APM service as well. So we don't need to start APM server and do anything. We can use directly APM service. WebDriverIO takes care of starting the APM server. Local runner we are using for locally running this particular test. We are using Mocha framework. Mocha framework. So you might have used JUnit or TestNG as a test management framework in case of automation. So here we are using Mocha as a test management framework. These were the types for the Chai. So in case of TypeScript, you generally need to add types as well so that they provide you the type definitions or the class definitions. In simple words, you can say class definitions for this library Chai. So Chai as a JavaScript library, it is not a type base, but when you add types with Chai, then it becomes a type and use it with TypeScript. Then you can use types or the classes or objects in the Chai as well. TS node is used as a compiler for this particular TypeScript is used as a compiler. TS node is used for transpiling the applications and we are using WebDriverIO Mocha or some reporters. So this reporter is used for reporting the applications. Now this is about the package.json file. We also have TS config file. This TS config file is used for defining from where the types are going to come. So our types are going to come from node platform, then Mocha framework, then WebDriverIO, then Chai and APM service. That's why we have defined these types are going to come from. So this TS config is like a configuration for TypeScript. Going back to the package.json, we have defined two scripts over here. Test Android and test iOS. So these two scripts are actually, if you see, there is a run button over here. These two scripts can be used for running the actual automation test. And underneath they are using NPM, WDIO run command with two different configurations. For iOS, we have different configurations. For Android, we have different configurations and we are going to talk about these configurations now. So these are the commands. These are nothing but like we are creating commands for running the test. Now if you saw this, these two configurations were coming from config folder. So let's go into the config folder. So WDIO.android.con. This is the folder. This is the file where we are going to keep Android related configuration. So Android related configuration. The WebDriver.io configuration. This is a WebDriver.io configuration. So when we are running test using WebDriver.io, WebDriver.io is going to pick the configuration from here. And this is going to run on the port 4723. The specs or the test will be residing in test slash spec slash star star slash star dot ps. So this is the directory we are telling WebDriver.io that my test is going to be residing into this particular folder. And WebDriver.io provides this capability of adding capabilities to the APM driver. So it initializes driver for you. You don't need to initialize the driver. And when you, in typical APM scenario, when you initialize driver, what you need to do, you need to provide the capabilities. So that's why we have these two files. So because these capabilities are differing in case of iOS and Android, we have two files. So for Android, we have platform as Android and we will be using emulator. Our automation name. So this is the crux of this particular driver. Our automation name is going to be Flutter in case of both the capabilities. For iOS also, we are not going to say the automation name as Android or iOS. Rather, we are going to say automation name as Flutter. And similarly, we have iOS configuration. I won't go into the details of iOS configuration. Most of you might have already done iOS. The configuration is similar and all. The only thing that differs over here is capabilities. And we are telling from where to launch the folder and all. So these are related to the configurations. Now we saw our specs or our tests are residing into the specs folders. Now let's go into the specs folder. So the specs are in test specs folder. Now, what do you think how should how how this test should look? We are interacting with elements and all that. But we are using page object pattern. We are using with screen objects like we have screens and we have objects. So we call it screen objects. But our test should not look as polluted as like that. It should just interact with pages. So that's why over here, what we are doing is we are just creating new home screen. On home screen, we are clicking add button. So we have a command on this on this home screen page. We have add command. Once we have we are done with add, it will return a page which has add details as a feature. So the next page on next page, we are doing add details. There we are providing random email, random mobile and random email. This will bring me a next page on that next page. I can do select card as a payment method. So where I selected the card. This will bring me a next page, which where I am going to put the credit card details. So I have created a method pay where I'm providing credit card details, expiry name and CVV. Once I am done with paying, I click on pay button. I see a test screen where I can either make that transaction successful or failure. So I can, on the next screen, what I'm going to do is I'm going to make it successful. So Nikhil has a question, can we use cucumber or behave also with WebDriver? Yes. So the way I talk to Moka as a test runner, you have a cucumber test runner as well available with WebDriver. So that is very well possible. So, but here I, for the simplicity purpose, I have only used page object pattern and I have not added a Durkin based or BDD based scenario. Once this payment is made successful. Yeah, I'm going to go into the details of the screen. We have sufficient time. We are going to see entire code. First, I'm going to walk you through the, how the test looks, wait for payment successful. I'm going to wait for payment is successful. Then I'm going to get the counter, the value of the counter, and I'm going to assert the value. So this expect is used from the chai. I told you the assertion library. So expect value to be equal to one. So since you are very much interested to the code, the actual magic, which is happening behind the screen. Like how this entire, entire one single script can cater to both iOS, Android, Flutter screens, native script, how does just one single script can do that. And that's the, that's the beauty of this code. That's what my passion is about like writing good code, right? So we are going into the screens now. So, so the way we saw that diagram, we had two zones, right? Native zone and Flutter zone. We have two zones in our code as well, Flutter zone and native zone. In Flutter zone, we have Flutter screen. In native zone, we have native screens. So in native zone, we have Android iOS and something common about those. So I will keep Flutter screen for the later part. First, what you have done typically with the Android screen and iOS screen. Let's see that. You might have typically automated APM with Android or iOS. So this automation is nothing but similar. We have something as a base screen object. So this is a razor-paste screen base, base class. And each screen or first screen that we talked about customer detail screens, right? First screen is extending the razor-paste screen. But what is this? Implements I customer screen. So that's, that's the beauty about the abstractions in any programming languages. You can generalize your screen. So we saw like both iOS screen and Android screen. Android screen have very similar behavior. Like, like they, they, they have both, both the screens are same, but implementation is slightly different, right? That's why we have used interfaces. And that's nothing but in our common folder. So for example, in customer screen, what we are doing is we are just defining the contract for the screen, like this I customer screen is defining the contract. This is called as a programming by contract where we are just defining contract for the screen. Like whichever screen implements add details can be called as a customer screen. Now, in case of Android, this customer screen implements this customer screen. In case of Android implements this I customer screen. So if I don't implement this particular method, it will give me an error. You can see this. It is giving me an error. So I need to implement this contract. I need to provide this method. And because I am providing this method, I can use that method, you know, in my test. So this add details screen is made like that. Now implementation of this add detail function is local local in the sense local for the Android. So we have used local locators for Android the way you use you I select a resource ID, you I select a resource ID email. You I select a resource ID button overlay. So that's that's the that's the local implementation or space Android specific implementation for this add detail. So I won't go into the details of type after clicking these are just reusable method we have created. So, but crux of the screen is it is using local locators for example customer screen that mobile locator this local locator it is using local to this class. And, and this method will just execute for Android. Similarly, for iOS, if you go into the customer screen. This locators are totally different. These are iOS locators. You can see similar is the case with all four screens or whatever native screen we saw on flutter context in flood, sorry, in native context, all those native four native screen card detail screen. For example, card detail screen has element locators for card details decision screen where we are making successful as locators for natives native screen. So these are native native implementations. Now, what do you think then we should we should create similar thing for flutter screen as well. How many of you think like that. So, for flutter, since code flutter code is made with flutter database code and locators on iOS and Android are going to be same. There is no different locator and this flutter APM flutter driver that we are talking about is providing us that ability to locate by flutters native flutters native location strategy. So find by value key find by value key this locator is going to work on iOS as well as Android. That's why we don't need separate screens for Android and so whatever screen you create in flutter, we will just need only one particular class for each screen. And that's why we have home screen, which is just a one class note to different different implementation for native screen. And there are locators are fine by value key. So this find is nothing but APM flutter find our library, which we are using so find by value key we are using value key is defined as add so you can think of this value key as ID. In case of, in case of, in case of, let's say we are using Selenium based browser or browser based automation that we use at ID in case of Android application we use accessibility ID. So value key is used for testing purpose only you can add this value key into the application port. So I have already added that and that's why I use find by value key counter I am accessing find by value key counter. Now, when we click on add button, we are doing driver element screen element click add add button. So that's what we are using. So this driver element click home screen add button is provided by APM flutter driver. Now, once we click on add button we want to switch to the native context, right. And that's why over here we are doing switch context native app. And now, when we switch to the native context, if the platform is iOS, we want to get iOS screen. And if the platform is Android, we want to get Android screen that's why we have the over here if condition, if platform is iOS return custom customer screen iOS. So we have imported customer customer screen from iOS as a customer screen iOS and as a for Android we are imported customer screen Android. And this is how we are targeting the platforms like we are we are using platform as a environment variable when the platform environment variable is iOS we are we are we are loading the iOS screen. And when the platform environment variable is not iOS we are loading the Android screen and switching to the native context was the crux of it. When we are on the success screen over here in any Android or Android or iOS screen, decide screen, where we are deciding, we want to switch back to the flutter context right. So, once we click on that make successful button, we want to switch back to the flutter context so here we are doing that. So switch context flutter so we are switching the context so whenever we switch from native screens to flutter screens, we switch context from native to flutter and when we are switching context from flutter to native we are switching native to flutter. So that's that's all about this code. Now I'm going to run this test. This will run the test. Since it is taking time I will just show the recorded videos of the test I have. So same code I have run it clicked on plus button. Then it entered the values. And that's how it executed. Similarly, it can run for Android as well with the command that I just showed. So that was about the demo. Now going back to the slides. If you have flutter driver has this many features like finders and some some commands that you can that you can access and that you can that you can understand on the APM flutter driver page as well. It is a GitHub based repository. So I'm going to talk the quick summary of the use case. So this use case was some screen where made in flutter code and application can run on different platform application is integrated with third party flutter library, which wraps native feature screens on the flutter package right and test scenario need to cover all these screens. And that was the summary of this use case. And then you can encounter many such use case in other serious scenarios like there could be more payment gateway. So stripe also uses similar thing like stripe has arrived at the library and native libraries for this automation for for this particular particular flutter related library. There could be maps there could be native feature there could be flutter embedded and native apps, there could be web view so there could be many similar scenarios where you need to interact natively or you need to switch the context, then you can use switching context as as the core concept for flutter flutter, but you need to have some caution with this library. This library is very early in the stage of experiment and breaking changes and breaking code are expected. And some of the mobile commands are not yet implemented for this library. And some of the APM commands are also not yet supported by this library like long cut so you need to use it with caution, only if you have a use case you use this library. That's what I'm going to suggest. So on closing start APM started supporting APM flutter driver since APM version 1.21. And because of which it has unlocked automation of many apps may automation of many apps like flutter and APM flutter driver was the first steps towards making APM support other drivers like APM flutter driver is a community driven it's it's not a native to APM it's a community driven driver. So since APM 1.21 APM started supporting APM flutter driver. And now with APM 2.0 it's not just one driver that we are going to have in future it's going to be a whole set of new drivers that we will be having and we are at the age of that fantastic change that you will be creating your own drivers you will be having your own drivers and you can unlock many automations that were not possible previously. So that was all about it hope you liked it hope you like the demo hope you like the port. If you have any questions, I'm going to take those right now. Do we have some time for questions. Yes, we do have some type of questions in your screens here and we'll get a good look at you we've still got. Well, we got one or two minutes of some questions if there's some questions there we've got something in the Q&A. Can we use Flutter driver concept using Java and Python language. Yeah, so this APM flutter driver although it is implemented in in node but you can use APM flutter driver in Java as well and flutter finder library that we use this library is available as a as a package in my own base package. It is hosted with the author's own credentials but you can safely use that so you can use it. Cool. We've got one more question here. Let's bring it back up again. Can we automate native apps as well with APM flutter driver. Obviously, that's what we saw right like we saw we automated the entire native screens, native screens which were made in razor pay right so you can definitely automate native apps. In fact, you can automate a native app in which you have flutter view that also you can automate you can add automatic native app in which you have web view, you can automate a native app which has both web view and Flutter you can automate all of those things. There are certain there are certain things which are not yet not yet implemented in this APM flutter driver you can go through that library and you can you can find the things. At the end of this presentation I have shared the references as well so whenever you get the link for this presentation you will get the references for all the libraries. Thank you for your talk today. It's been great. Lots of interesting things there that you've been been working on.