 Hey good evening everyone. Okay myself Shyam, Shyam Shashi. I currently work with Carousel. So I will be completing two years with Carousel next month. So I'm also a core team member at Takila. So if you don't know what Takila is, it stands for Test Automation and Quality Engineering Lab. So we got this new name last month, not last month, last year from Singapore Appian Meetup. From India, from the state Kerala. So if you're planning to go for your next trip, I suggest you just go to Kerala. It has got everything for you. It's a seaside state and green carpet, hilly areas, waterfalls, culture, heritage, monuments, everything you got there. So I strongly suggest you go there. Okay, so personally I want to dedicate this talk to Mr. John Adelips. I had a chance to meet him during the LASOS conference. I asked a lot of stupid questions with him and he was very kind and answered all the questions that I asked him. And he even gave us a video testimony in our last first year celebration. So almost all the tips that I took it from his weekly APM newsletter called APM Pro. So if you haven't subscribed to that, I highly recommend that one. You go and subscribe that you get a lot of tips from that newsletter. So let me ask one thing. How many of you are using APM in your project or office? Okay, cool. Most of you haven't. Nice. So APM, basically it's using for the mobile test automation mobile apps, automating the mobile applications. So it supports a number of programming languages and it's the most perfect automation testing to do across the world for the mobile application testing. So I won't be focusing much on the beginning levels. So basically I want to give you some tips on that one. Some small tips on how you can effectively use APM. The first one, how to inspect the elements. So the most preferred tool for inspecting is the APM desktop. This is the official app that APM suggests. So there are around 30 contributors that are already there. So if you look at Makka.js, it's a web-based tool where you can use that one and you can hit an URL. So the mobile server will be displayed on a web page. There are APM iOS inspectors also. So personally, I prefer to use APM desktop over the other tools, which is highly stable now. Second one, how can you check some network conditions? So there are situations where you need to test your app on multiple network conditions. Like what happens if you turn on the flight mode and obviously the internet will be cut off and what will happen to the application that you are testing on. So if you want to test something like this, methods are useful. Like toggle airplane mode. If you want to toggle data, there are toggle data commands. If you want to toggle Wi-Fi, there are toggle Wi-Fi commands. The first three are specifically for Android emulators. Basically, if you want to send an SMS on Android, you can call these commands like send SMS. So it will do a fake SMS, like make a GSM call or how much signal strength you want to emulate on an emulator. Like thing we can do. If you have test cases related to the location, you can use the final one like set location. So basically, it's a longitude, altitude, all this information you need to give when you start the new location class. Desktop app. So APM can be used for desktop application as well. So I have a small demo for it. It's quite interesting. So you can use APM for both Mac machines as well as Windows machine. I won't be able to do a demo using the app driver. I can do a demo on Mac. So how does it work? Like there is a tool called APM for Mac. So you need to install this app first. Then if you want to, like, how you get the accessibility ID or any other locator strategy, you want to get the element location of location strategy for a particular element, what you can do. You just point to it, whatever the element you want to inspect, and click the function key. So you can see that the APM desktop actually jumping. Then you just go to any notepad and just paste it. So that particular location in a zoom-in. I cannot zoom in, sorry. So that particular expression is called AX path. So that particular AX path expression being captured, and you can just use this as a Web Bellyman's locator strategy and you can instantiate a web driver and you can do whatever be the things with it. So we can see a demo. Okay, so I have this test case. So the first thing is you need to start the APM server. Close this. So when you run this command, the APM server will be starting on the default port 4723. And what are you going to do? Let's say when I set the capabilities, I'm giving platform name as Mac and device name as Mac. What I'm going to do, there is an application in Mac called Activity Monitor. So this is the app Activity Monitor. So I'm going to open this process and I'm going to click on all these tabs and I'm going to do a search and I'm validating the search result. So I have already captured the locator strategies. So what I'm going to do, I set the app as Activity Monitor. Then once I open that one, then I'm going to click on these memory, energy, CPU, network tabs. I'm going to search node and I'm verifying that particular node is being displayed over there. So let me run this one. Searching node and then it's verified the node result over here. So if you have a scenario where you need to automate the Mac apps, it's very highly helpful. So like this, there is something called WinAppDriver for Windows where you can use it. So in order to inspect elements, it's from Microsoft. So they're providing something called inspector.exe. So using inspector.exe, just like the AX path, you can identify the elements in the Windows machine and you can just instantiate the WinAppDriver and start using it. Next one. Which locator strategy should I select when I start automating? So if you compare it with Selenium, Appium is an extension of Selenium. So you can see that class name, ID, name, X path, which supports in Appium as well. So Appium specific locator strategy, there are accessibility IDs. For iOS, there are predicative string and class chains. Android, there are UA Automator. The UA Automation is deprecated from Xcode 8 onwards. So the other stuff like link test, those are not available with Appium. It's available only with Selenium. So I should be my priority when I select the locator strategy for the particular element. The first preference goes for the accessibility ID. So if an element has accessibility ID, you should always use that one. You shouldn't select any of the other one. This is for iOS. If there is no accessibility IDs there, there could be cases where elements don't have accessibility ID. Like especially some QA teams are not lucky enough to sit along with the dev team. But the dev team may be in another location or the team QA team is simply handling the testing. The development has been done by some other companies. There are so many scenarios out there. So in that case, if there is no accessibility ID, the first preference should be go for NSPredicates. So NSPredicates is something like, it's like XPath, but in a better transform which the XCUA test understands. For example, if we want to check the label as Olivia in a table, this is the corresponding expression for that one. So Clustain also there. Clustain is also something similar like XPath, but much faster than XPath. Android, if, okay, the first preference goes for the accessibility ID again. It's called resource ID or content description in Android. If there is no content description in Android, you should go for, you can use the latest one, UASector. So UASector is very helpful to identify the elements based on what, TextView or any other properties that Android provides. So my point is that try to not use XPath. Avoid XPath if you can. But it's not really possible to avoid XPath 100%. There are cases, but if you have a chance to use other locator strategies, just go for it. Because XPath, it will work. Your test will work, of course, but it's term consuming. And it's very expensive for a PM to deal with it. Especially, I have seen people write long XPath chains and in another update, everything's going to fail. So try to avoid this one. Always use the first preference goes for accessibility ID. And for iOS, the second preference is predicate strings. And you are a meter for Android. This might be familiar for everyone. So I think everyone is using in all the project data respective of Selenium or Api. Waits. So how do you wait for an element to appear on the screen? When I started my career, I was heavily using the static ways, like hundreds of thread dot sleep in my projects. And it was working fine on my machine. And the moment when you run on any other machine, it's begun to fail. Especially when there is no internet speed, so many other reasons. So try to avoid the static weights like thread dot sleep, 30 seconds, three seconds. So what will happen? The login screen appear after the third second, in the fourth second. Obviously, it's going to fail, right? The second one, implicit weight. So I have seen that people are just using the implicit weight when you instantiate the driver. And just expecting that it will be working fine. It's not the case. So if you instantiate the implicit weight like this, it means that for all the elements, by default, it will wait for 10 seconds from this example. But it should be more dynamic. There are cases like maybe a new page takes more than 10 seconds to log. So you need to write the custom or not custom explicit weight for that one. So explicit weight is more dynamic to use. So basically, you can tell that there is a web driver weight and you can wait until an expected condition made. Like there are a lot of conditions like presence of element located, is element visible, is element clickable or something like that. So there are custom weights you can write. There is an apply method over there. If you override that apply method with explicit weight, you can have your own custom conditions. Like you can wait till it's visible and it clickable. So both conditions you can club together. So such things are possible. Okay. I didn't add one more weight. Anyone familiar of any other kind of weight in Selenium? Any idea what's that? Exactly. So basically the explicit weight means that by default, it will query for the element within 500 milliseconds or something like that. Okay. So with the fluent weight, you can control within whatever be the time interval you are polling that element. So which will be more dynamic. So there is a fluent weight also. So similar like the explicit weight. Dealing with an element when visibility is false. Yes. Yes. I recommend strongly recommend to use the explicit weight. Yes. Okay. What happens when visibility of an element is false? So I have seen this issue mostly in iOS. Element is visible on the page for humanize, but if you check the property, it's false. Anyone made this issue before? When the visibility property is false for an element, but it's still showing on the UI. So there is a workaround for it. So what do you need to do? The element still won't be null. So what we can do, you can click using the coordinates. So if you call the click command using a PM, it means that by default it check for the visibility. But if you click using the coordinates, it's never checked for the visibility. So you can find out the middle X, Y coordinates of that particular element and you can click on it. So basically it's quite simple. So let's say I find my element REF, then I get the middle X and middle Y points of that element. Then I find out X at point where I need to click, maybe the middle portion. Then I do the actions to click on it. No, it's not sensitive because this is the X, Y coordinates we are not hard coding. So if you look at the code, we are finding out the X at middle point based on the total width and height of that particular element. So if you are testing this on different screen size devices, the X, Y coordinates also vary accordingly. So it's more dynamic. But if you are hard coding this, then there is a high chance that the test can be breaking in other devices. So by going this method, that can be omitted. Speeding up your tests. This is my favorite portion. Deep links. Inventory deep links in your automation framework. Okay, so let me tell an example. Okay, just forget about the user sign-up flow. If you have an application, obviously you will have a login flow write. So in order to test any other functionalities, the first steps you need to do, login. Imagine the login takes 20 seconds to complete, including typing the username, typing the password, click on the login button and go to homepage. Maybe you have automated 50 test cases. So this login functionality takes every time 20 seconds. So 50 into 20. That much seconds, almost 15 to 20 minutes for an entire regression test that you are wasting. The question is, can we bypass the login so that I can, if I specify the username and password in a PM, the moment when I start the app, can I directly go to the homepage so that you can save this 20 seconds for each test case? Yes. It's possible. So basically what you need to do, you need to create a deep link in your application. So deep links are nothing but it's a special URI schemes and providing that when the app gets a request for this URI, it means that it understands that app need to navigate to the homepage. So for example, the app login of the user or the password I am passing the credentials over there. So when you call driver.get method, instead of going to the login screen, the app will directly go to the homepage. So we completely bypass it. We can see a demo. So we have this demo from Appian Pro. Cool. So first, I will show you the normal flow like the user login using clicking or entering the username and password and clicking on the login and go to homepage. Okay. So I am running on one of the iOS simulator. Yeah. So enter username, password, click on login. Yeah. Basically it wait for the presence of element. So it passed. Next, what if we can skip the login? So what I am going to do here, I'm calling the deep link here and passing the username and password. So let's do it. Basically I need to wait here a bit to see that happened, but basically it passed. Yeah. Better. So I have a check here like get logged by you logged in. Basically check accessibility ID phone. Basically it means that it passed. So there won't be any username input actions that are happening over there. Another method is the process arguments capability in Appian. So what you can do, you can call something called optional intent, intent argument. I think the spelling is wrong here. Yeah. Optional intent arguments and likewise you do with the deep links. You can pass the username and password. So for this I have a carousel example over here. It's quite similar. So what are you going to do like? I have a capability setting process arguments and I am passing the argument over here as a username and password. So let me run the first one. This is without process argument the normal flow. So it's clicking on the... So I'm stopping till when I see the notify me button form. So we do the same for intent arguments. So it's understanding the app and testing again. Yeah. So basically it's keeping that part, directly going to the homepage. So if you're really considering about saving some time in your automation flow, consider implementing deep links and optional intent arguments. Yeah. So next one, some useful capabilities that Appian provides. These are 3R cross-platforms. Like no reset, full reset, everyone might have family raise. So if you're giving no reset, it means that App will not be uninstalled. Request means that App will be uninstalled and reinstalled every time when you run the test. So if you're not... If you're going to disable the full reset, it means that you can save the time by not installing it over and over again. So you can save some time. He's headless is a new capability, so which means that you can run the simulators on emulators in headless mode. So there won't be anything showing on the UI, but you can still hear the sounds. It won't be like the HTML unit drive or something like that. It's like the UI won't be rendered on the screen. So in terms of performance perspective, that saves some time. So if you have simulators running in your automation framework, consider using the ease headless to capability. Yes. Not exactly, but it's very few. I did a small test. One or two seconds for a single test, yes. Android one, these are some useful ones for Android. So disable Android watches. So what it will do, there is some process running on, whether there is a crash or some other stuff going on. So you can disable it using that capability, so which will boost some performance. Another one, autogram permissions, which means that App will automatically accept all the allow pop-up by the Android. So everything will be certified to true. You don't need to handle these pop-ups. Skip unlock. So if you have an unlock on the not the... I'm talking about the Appian unlock thing, not the your screen-specific log. So if you want to skip Appian specific log, you can just pass that. Skip unlock. Ignore unimportant views also. It won't select some of the views, which is not really used for the test. So by default, it will fetch all the hierarchy. So if you're enabling this ignore unimportant views, not all the screens will be loaded. Only that specific testable areas will be loaded. For iOS, use pre-built WA and derived data path together. So what happens in iOS is that when you start a run, so web-driver agent will installing on the phone or simulator and it will kick-start the testing. So every time it will build the web-driver agent from the Xcode when you start it. So if you have a pre-built WA agent, you can use this one. You can give the path to that particular file. So every time Xcode come and will not be running. So it will reuse the existing WA and you can get all the tests passed. Use JSON source. So it's like retaining the JSON instead of XML, especially for some large applications. It will take too much time to retain the XML corresponding XML structure of the screen. So if you're using this one instead of XML, Appian will consider using JSON, which will be much more faster than XML. iOS install pose. So once the web-driver agent has started, Appian again checks whether the... what's the right time to start, the kick-start, the launch, the application. So if you think in some of the phones or simulators sometimes the installation fails, it because Appian thinks that the process got over and it will try to launch the application even before the installation completes. So you can specify how many seconds you want to wait after the web-driver agent instantiation. So if you're giving that one, so after that fetch seconds only, the next process will start, which will be much more stable. Max typing frequency. Basically it's the speed which Appian types on the keyboard. So you can control it by default. I think it's 60, so you can increase it or decrease it based on your requirement, which means that the typing speed will be slower or faster. Real device screenshot. So if you're taking a screenshot on a real device, it's always buggy sometimes. I mean it's always buggy, not sometimes. So instead of real device screenshot, I mean if you're enabling this one, Appian will use ID-based screenshot library, which will be much more stable. It will ignore the default screenshot library from Appian. Symbol is visible check-through. Yeah, so checking element is whether true or not. The default library is sometimes it may fail. So if you're enabling this one, so which will be much more better logic in this particular section. So try to make it enable as true and you will get much more ease visible check happening over IPM in iOS. Okay. Next one, testing app upgrades. How many of you test app upgrades in automation testing? Let's say you have a release today. So you need to make sure that when users get the current release from the previous one, what they're going to do like most of the time you get a new update when you connect the charger, your phone, and from play store it will be automatically upgraded. They're not doing a fresh install. They're updating it, which means that if you're already logged in, when you update the app, all your data should be there. Nothing should be lost. So how can you do this scenario with IPM? Because the current one we have seen that it will always uninstall and reinstall the app, right? So how can you really update an app? I mean upgrade testing. Yeah, it's quite easy in Android. So there is something called start activity. So if you call that start activity, then the corresponding app will be launched. So in terms of iOS, what you need to do, you need to do a couple of extra steps. Like there is a mobile terminate app, then install app, sorry app, this one, the version of the app to be updated, you need to give that one. Basically another IPFL or an APP file. Then you need to call the install up and launch up, which means that if you're calling this, then none of your data will be lost. You will be still logged into the application and you can see all the existing data. So to test, basically you need two different files to be installed. One with the older version, one with the latest version. And first you need to install the older version and start using this command for the latest one to be installed. Switching between the apps. So earlier it was not possible to get a different screen other than what you have tested in iOS, but it's now possible. You can switch to different screens now. Android, again, it's easy. You just start the activity of the application that will be instantiated. It will be started even though you are testing the current app. On iOS, for example, let's say I am on the gallery page. So mobile launch, that particular one. If you want to activate another app, you can call mobile activate app, which means that whatever will be installed up on your phone, and you call that particular app, it will be open on the top of the gallery page. So it's quite straightforward. Earlier this feature was not available in iOS, but it was there in Android. Testing the push notifications. I really wanted to do a demo, but I don't have a backend service to enable the push notification. But the logic is very simple. For Android, it's again straightforward. You just call open notifications. You get it as a list, or the available notification on the screen. For iOS, what you need to do, you need to scroll down from the top to the mid of the screen. Then it will open the open notification session. You need to click on the open notification. So all the push notifications that you have received will be available on that site, and you can verify that. So basically, you need to call the Terminator app and activate the app again. So basically, it's same as just killing the current process, go to the push notification, and getting it in the app back. Custom alerts. So the earlier alerts were like accept, alert, and decline. A dismiss alert. That was the only few methods were available in the app. But what happens? There are multiple buttons on the alert. Like OK, an order. Yeah, I want to do something else. So more than decline and accept. So in that case, what we can do, you can get all the button labels from an accessing alert, and you can click on that particular alert. So it means that, let's say, I have an action called, sorry, get buttons. So if you pass that one, I will be getting all the alert as a list on buttons. Then you need to iterate this list, and you can have a custom code like whether it has OK or cancel button or whatever be the label that on that particular button. And you can click on that one. So again, on clicking. So you can do something like accept on, as the action, you can put accept, and you can click on it. So logic is simple like get all the buttons, and what would be the button that you want to click, click on it using the accept argument. Find element using image. So basically, internally, this is an openCV library. So what you can do, it's quite straightforward. The only precondition is that you need, the image should be in the base64 format. So you can call this base64 code. Then you can set up the threshold level like how many percentage of matching you want to meet with the given image. And you can click on it. There is an presence of element located by image or driver.find using image command is there. So it will return the corresponding image. So what it will do, it will take the current screen screenshot, screenshot of the current device, and whatever be the element that you are passing, it will try to find a match on the current screen, and it will return it. Picker wheel. I think someone asked. Is it you too, sir? Oh, yeah. You pinged me earlier, right? So she asked me a couple of months back like how to automate a picker wheel. I didn't know that at that time, but now I know. So it's easy. Just use senkeys. Yes. So that particular, basically are you swiping now? Are you swiping on? OK. So it's more easy. Basically it will work like a text field. So you can, if you know which value to be selected, you can pass senkeys. So that particular value will be selected. But there are cases where you are not aware of the value to be selected. In that case, you can use the other one like select picker wheel value argument. So it needs three arguments like on which direction you want to scroll, like next or previous, what's the offset that you want to swipe, then ID of the picker element. So if you pass this one and you pass the parameters, it will be picked up. We can show a demo. Let me run this one. So I am selecting March 6th as a senkeys. Then using the other options, what I'm going to do, I'm going to select the pass the next and get the first element that has been displayed over there. And again I am doing the, selecting the picker wheel in the opposite direction using the previous. So let me run it. So if you are stopped automating any functionality just because of picker wheel, just use this one. You are able to automate that. Starting. Yep, March. Okay, 6th is not selected. I think there are some issues with selecting that one. You're supposed to select the 5 instead of 6. I need to find out why. Sorry. But basically that's how it works. Label. This one. Oh, senkeys. It could be basically this picker element. Basically I'm getting it by the picker. So there's a class name for that one picker wheel or something. In this example we are using, but if you have an accessibility ID for that particular picker wheel, the better you just do it. Using that one accessibility ID. Next one. Screen Recording. This is a much needed functionality, especially if you have an in-house device one or something. So again, it's quite handy. For example, in this example we use the iOS again. So the first thing you need to do, you need to give the iOS start screen recording options. And you can specify the quality of the video you want. And in how many seconds of duration maximum you need for that particular recording. Then you can start recording by calling start recording method. Then you pass the options, all the recording options over there. Then same for the stop recording. You can just call the stop recording. So once you call the stop recording, it will returns you a string. So you need to convert this. You need to decode this string to byte and just write the file used from this byte. So if you look at this record string, it's going to be like it just look like an encrypted format. So you need to decode that using base64. And using the files, Java files, you can just write it. Again, we can just use that picker will demo. So I have already run this. Let me delete this and I'm running it again. Yeah, now it's selected six. It passed. And if you look at the, yeah, it came back again. Here and open this one. All the screen action has been recorded and we successfully write into a file. You are planning to do it in your automation framework along with your HTML report. This is highly recommended. Especially if you want to check why the test case has been finished or failed. Okay, parallel and distributed testing. This is a very vast big topic, but we will give an overview on how it's possible to do parallel and distributed testing with Appium. So there are four ways. The first one, you can run multiple Appium servers and sending one session to each server. Which means that I can run multiple PM on different ports like 4723, 4724 and just give that particular path to the driver and it will be instantiated. Second one, run only single Appium server and sending multiple sessions to it. That also possible. So you don't need to run multiple Appium servers. Always point towards the single Appium server that has been running and still it works. Appium handles it. Then third one, one or more Appium servers behind a grid and sending all session to the grid hub. So you can reuse the Selenium grid and register the Appium as a node over there and you can start using it. The fourth one is using a cloud solution. So there are so many cloud providing companies are there for automation. You can reuse that one. So let me do a quick demo on the grid. So here what we're going to do, I have these three commands. The first one is I need to start a grid hub. So let me open three tabs and go into this folder where my Java is. Then I'm starting the grid on the port for 443. So what will happen now? So hub has been started successfully and if you go to this URL, you can see that it's running. So if you go to the console, no node has been registered yet. So it's empty there. So how you can register an Appium node over here? So Appium provides something called node config capability. So let me open it. So I have two JSON files. The first one, let me open it in another. Okay, cool. So there are some capabilities that I have provided here and the configuration also. So in the configuration, I have given that in which URL the hub is running. I'm specifically here and this is the IP address and this is a port where the Appium node should be running. This is a hub port and this is a hub host. So as the capabilities, I have provided, like, the name, browser name, basically, the same as the simulator name and the device name is almost the same as UDID. Then UDID also is given. This one is node-needed. Then WDA local port, if you want to specify, then platform name also. So if you run this, the corresponding node will be registered to the grid. So let me run the first one. So the command is appium-nodeconfig. Just give the JSON file and the appium will be trying to register that particular node on the grid. So interface has been started. Yeah, appium successfully registered with on the grid, the URL of the grid. So if you go here, if you refresh, you can see that it has been came here. So with all the configuration that we have provided. So likewise, what we're going to do, we're going to register one more simulator. Yeah, so the second node also been registered. So if you refresh this page, you can see that there are two nodes are running. So it could be another machine. So it need not be the same machine. If you run this command from another machine, which is the same intranet, which is accessible to the hub, it will be registered out there. So the first one is, sorry, this is iPhone 5S and this is iPhone 6. So how can we start using it? So what I'm going to do, I'm going to pass this URIID as a capability. Then I'm not specifying any other thing other than the URL of the hub. So let me run this one. So we are again running the same picker wheel. So you can see that this one came up and one simulator has started and we will be running the test on that particular one. So basically if you look at iPhone 5S, it picked up a match on the registered node and if it is available, it will be running out there. Likewise, you can register Android 1, even Chrome, Firefox, Internet Explorer, anything. And based on the request that we have given from the web driver, it will be picked up over here. If it is already being used, then it will be going to the queue and once the execution has been done on that particular node, it will be picked up from the queue. Yeah, it passed. Basically same for the other simulator. Yeah. Selenium Grid will already handling that one. But you need to specify, okay, so what I have seen like, let's say if you are not passing the UDID and if it's not found a match on that particular session, sometimes it will throw a node found. I mean the requested capability is not found. But again, if it matches the same device name, Appium will try to create a new simulator. So that quite messy. So you need to always control the simulator with the UDID. Yeah. So in web testing, it's possible. But in Appium, when you start the driver, right, especially on iOS, the device name capability is a mandatory one. So without device name, you cannot instantiate. So if you are providing that one, so Appium, if it's not found on that particular machine, Appium will try to create a new simulator based on whatever. If you go to the Xcode and check the simulator, you can see that a new simulator has been added by the Appium. So that part quite messy. And we need to solve it by using the UDIDs. But there are ways to use that one. Like you can check the selenium grid and check whether a particular node is in use or you can wait for that time or you can even check what are the available nodes which are not being in use and you can dynamically assign to that one. It's possible. Yes. There are multiple ways. Multiple work accounts. Yeah. I think I'm done. There are some references. So almost 90% of what I have said is there in the Appium Pro editions. And there are another great reference is that from Srinivas, there is an awesome Appium GitHub. So almost everything related to Appium is over there on that page. You can check that one. There are some advanced concepts in the GitHub Appium reports also there. You can check the advanced concepts. It's a documentation that is maintained by the Appium team. It's also there. So if you have any questions, you can ask. Hello. Yeah. I think it's still the same. Yeah. Anyway. So what I'm asking is which method you will either buy selenium grid. So, I mean, which one we should use? If you have enough budget, I would suggest use a cloud provider. But because even though you are setting up all these things, you need to maintain that one. Right? Yeah. So, and there are conditions like you cannot run your test on a cloud provider. In that case, obviously, you need to build a device from in your office. Or ideally, you should, you need not run all the devices for, I mean, depends on how you test the application. Like how frequently you are testing. Are you testing on all the protocols? Or are you testing only on the nightly build or something like that? Depends on various parameters. Conveined Carousel, we are using both cloud provider as well as the in-house device from based on the requirement that we got. But obviously, I won't be using the first one and two points. Different Appian servers and running on a single Appian server. Popular one. The cloud provider AWS or any example. Okay. So, again, that really depends on your application, your kind of application and what kind of testing you can do. So, all these cloud providers offer a different set of goals and different set of packages. So, you need to evaluate based on your requirement and you need to conclude. So, if one company selects one cloud provider, it doesn't mean that another one really, it's a match for, it's an exact match. So, it really depends on what you really need. Hi, Shyam. Hi. This is just in general question. Like how Carousel is like integrating the automation with Jenkins and CDCI? Oh, okay. I mean, your question specific to Appian, how we are using Appian? Not just Appian, but, okay. You can talk about Appian, but in general, automation can be a way. So, currently, we have two types of automation testing running in our project. The first one is nightly build. So, where we are testing the nightly build and we will be running it on every night and we get a result on the next day, maybe even before when we come to office. Another one kind of things like the pull request. So, basically, it's like whenever developers are opening a PR, so we are testing a sort of subset of the sanity tester out there for every pull request. So, we will be getting the corresponding build points to that particular branch and we are downloading that one and we are testing that one. Yeah. So, basically, for every PR, so we are uploading the APK or IP or APP files to the common location and our automation script will be picking up that particular file and will be reused in our automation framework. Okay. So, your question is like, what happens when two peers comes at the same time? Obviously, we will run both at the same time. That's why the Selenium grid is going to be handy out there. Yes. For Selenium, we have like the record and playback, right? So, in APUM, does it have that capability? Yes. With the latest version of APUM desktop, there is a record and playback. So, you can, if you use that one, the corresponding location, I mean, locators will be copied over there and you can convert it to any programming language that you need. So, there is a template over there. You can select Ruby, Java, Python. So, corresponding code will be generated. Yes. That's it. Okay. When I run my automation, it's actually not the test itself fail but actually it's like wait for certain element and it doesn't appear, let's say a soft keyboard, it doesn't appear. That's why it was like stayed out there but actually the APUM, or rather my test script is running bypassed at that stage already. Let's say you are in the locking screen. So, you are supposed to have a soft keyboard appear but it doesn't appear due to some simulators. This is especially happening on the simulators, right? Yes. Okay. So, in that case, it's not because of my test case failing but it's because of this. So, how do you... It's still because of the test case. I mean, it's part of the test case, how you handle the, how you maintain the simulators, maintaining the test devices, everything part of the responsibility of the QA. Because just now the question was asking about nightly. Yes. I was like, imagine if next time I'm going to use that as a nightly thing, then if this thing is going to occur, then the next morning I come here, I will discover actually never you run all my test cases but actually it's a failure due to this issue. Let's say, if that issue happens, okay, it would not going to be an intermittent issue. So, basically why that keyboard is not appearing on simulator? It is because keyboard never appeared on that, that particular simulator or you are just used in new simulators, right? Yeah. So, basically, which means that the next day when you fix it, the on-going test will be... So, that's why I realized my test case is not even running. Yeah. Then I got to kind of... You can just retry it, right? Once fixing it, you can retry the run, that's it, right? So, this issue won't be happening next if you are fixing that keyboard. You can configure the simulators like that. Always there will be soft keyboard present over there. You can specify, go to the hardware and you can just connect to that corresponding keyboard. So, every time when you run the simulator, the keyboard will be appearing on that simulator. I have faced this issue. So, just fix with that one. But it may happen if you are using a new simulator, if you're going to use a new simulator, then you need to fix this. It's just like you just started a new test device to your inventory. You need to make sure that everything works fine on that particular device before we enable the test. Yes, obviously, yes, because the concept is same for APM. So, how it's going to check whether... So, let's say you have given a device name as iPhone 8 and a version as 12.0 or something like that. And there is only one simulator available in your machine. So, maybe not a simulator, it's a real device. And maybe someone accidentally upgraded it to another version. So, what happens is that APM may not be finding out that particular device and it will throw the exception. So, all these things, you need to make sure that whatever you are requesting should be available in our infrastructure. You need to make sure that it won't create a new iPhone for you, right? It will be amazing if you're working something like that. That's it. Okay? Thank you. Thank you.