 So, my name is Mayur Zalo, really excited to be here at Selenium Conf. So before I start, I want to know how many of you who haven't worked with Clojure or any Lyft languages? Okay. I got a lot of people who don't know about Clojure. So let's learn some new thing today. So I'm going to talk about how we write functional and integration tests for mobile and web apps using Clojure, right? But before that, first things first, what is Clojure? So Clojure is invented in 2007 by Rich Shaky. So it is a dynamic functional programming language. And its Clojure is a list for JVM, we can say that, right? So Clojure is actually two things, one, the language which has a list dialect with functional emphasis and the great support for concurrency and asynchronous programming. And second, so the compiler which takes code written in Clojure and compiles it to a Java virtual machine bytecode, right? So Clojure emphasizes simplicity where you can have obtained functionality, like using a libraries rather than having a forced instruction, like having a framework, right? So I'll spend most of my time demoing things using Clojure, but to understand that, you must know some basic syntax of Clojure, right? So every expression written in Clojure is in form of list. The first item of that list is a function. And everything else is passed as arguments to that function, right? Clear enough, right? Yeah. So Clojure is dynamic. It means that Clojure programs are not just something with which you compile and run, but something with which you can interact. So this is where Ripple comes into picture. So Ripple stands for read, evolve, print, loop. So basically what it does, it presents you with a prompt. You write code into it, it reads the input, evaluates it, prints the result, and loops presenting you with the prompt again, right? So Ripple is the best thing that I've seen while learning any programming language. I can show you how it developed some things in Ripple. So if I want to add arbitrary number of numbers. So what I'll just do, is it visible, everyone? So I'll just say 1, 2, 3, 4, 5. It gives me addition. And if I want to do something, if I want to add numbers, array of numbers. So I'll apply plus or add. So using Ripple, you can learn and build Clojure programs instantly, right? So Clojure is functional programming language. So Clojure provides functions as first class objects, right? So the philosophy behind Clojure is that most parts of the program should be functional. And that programs which are more functional are more robust, right? So in Clojure, FN creates a function object, it's like anonymous function, which yields any value like any other. So you can store it in a var, pass to other functions, right? And the defen, it is a macro which helps you writing a function a little simpler. And so let's see one example where I'll write one function, which shows the example of function as a first class object. So here is my basic use case. I want to do x mod y, right? Now I've modified my use case, now I want x plus z and then mod y, right? But I want to add a functionality to my function that I want to take any operator, x of z. So it will be like plus, minus, multiplication, divide. And the final use case is I want output in integer format. So you might want to convert that format or output to a string. So right now I just want it in integer, right? So let's see how can I do that in closure. So I have this fancy mod function. So what it does, it takes in three arguments. First, operative function, that is plus, minus, multiply, or divide. And second argument is numbered to mod y. And third argument is output function, that is for now it's integer. I want output in integer, right? So let's see code, yeah. So what it does, it returns another function. So which takes in two integer arguments, right? So before I'm returning that anonymous function, I'm just doing a pre-checking where operator function should be plus, minus, which belongs to that set. And number to mod y should be integer. And output function should be in an integer form, right? So let's look, how can I do that in closure? So I want to perform addition, and I want to do that mod by three. And the output should be an integer form, right? So let's try. So you may not understand this code, but you can imagine the same thing in your own preferable language. So you will see the difference, right? So this fancy mod function returns one anonymous function, which I'm holding in another depth. That is var. So mod by three, it's a var. So I'll just do mod, I'll call that, and I'll pass, suppose, 11 and 11. So it will add those two numbers, and then mod by three, the result is one, right? So now, suppose I want to add functionality where I just want to convert that mod output to string. So what I'll do is I'll add str in output function. And I'll just save it and compile it. Now if I say I want output as string, and do that thing again, so it will return main string. So you see, I just modified the, I just changed the sum, I modified code, and the changes get reflected in Ripple immediately, right? So feedback loop is fast in closure. So this is how we do iterative development in closure, right? So closure is designed to be a hosted language. So closure gives a clean, simple, direct access to Java APIs. You can call any Java API directly. So closure is actually a great Java library consumer with .target member notation, right? So this is a syntax of Java interrupt, where you can have a ., then class name or instance, then member of that class, and its arguments. Or in iterative closure, you can say ., immediate member of that class, then class name, and its arguments. So let's try this with example, yeah. So I'll say . space, then class name. So my class is string, and its member is suppose length. So it will give me a pipe, right? Now if I say ., and then immediate member of the string class, that is suppose two uppercase, and then class, which is against string, right? So let's try something. So let's call some Java API of cell name. So you can call any Java API. So you can call that using closure, right? So I'll, I have one function written, which is, we'll just do. So what you'll do, it will launch a Firefox driver, and it will go to our help ship support page. It will click on contact us button, and then it will click on submit, and quit the browser. The internet is slow here. So how I did it? I just created an instance of Firefox driver, that's, and how you do it in Java, I use that driver to find an element, and then perform an action on that element. And it's loading, yeah. It will click on contact us, and click on submit, done. So if I want to see the code, so I just called, yeah. So new instance, driver of Firefox, then I will, I, I, uh, navigate. So I'm exiting the body using that driver instance, right? So every time if, uh, you're not returning anything, uh, it's enclosure, it's just written in it. If you're returning any data structure, it will just return it here, otherwise it just return it. It's kind of, uh, what do you do in a C, like return, zero or at the end, right? Something like that. It will, it will give me an error, it will give me an exception, right? So let's move to macros. So, uh, closure is member of, uh, list family of language, right? So most of the features of lists have made it into other languages. But the list approach to macro system set it apart. So macros gives a closure a great power. So using macros, you can modify closure in ways that, that aren't possible using any other languages. So the key difference between the function and macros is that so function arguments are evaluated before they're passed to, uh, passed to the function. But in macros, they are, uh, the macros receive argument as un-evaluated data structures. So let's write some control for macro. So some languages provide a feature of unless, which is just opposite of if, right? So what it does, it performs a test, then executes a body if that test is logically false, right? But closure doesn't have this functionality. So yeah, I can write that. So let's try writing that, uh, unless feature using function. Because if you can do that using function, don't write macros. Yeah, because macros are complex and they require you to think carefully about the interplay of macro expansion time and compile time. So let's try this using a function. So this is a function, but, uh, here's a if syntax enclosure, which, uh, takes except, uh, expression. And if that expression is true, then it executes the first form, otherwise it executes the second form. So in, unless, uh, I just, the, I just did, uh, opposite of that if, so I added if expression, if expression is true, I'll return a nil. Otherwise I'll execute the form, right? So let's try the, unless function. So I'm passing an expression false. So it should print the statement, right? Yeah, it's printing it. But what if I now pass true, now this should not print, right? But it's still printing it because I already said that function arguments are evaluated before they have passed to the functions, right? So let's try this using macro. So I have written one macro. So what this micro does is it's, uh, list function returns a list given items. So here are my items in list. So I added a code before if, because code protects it from being evaluated, right? So if I use this as for my true expression case, so it should work. So this should not print now, or if I, if you want to, uh, see, or if you want to expand the macro, you can just say, so list returns this function, uh, the list, which has if then expression and return nil if that expression is true, otherwise return or execute the form, right? Finally, selenium. So CLJ WebDriver is library, closure library basically, which, uh, which is used for driving a web browser using selenium WebDriver as a back end, right? So, so it, it, uh, build on top of, uh, the version of selenium that is 2.31, but we modified this library for work with the latest version of selenium that is 2.42 maybe. So that can be found under the closures, right? So let's see how it works in closure. Now if I want to do, I have one, uh, so what we do, uh, normally when we write tests in selenium, you do, you launch a browser, you inspect an element where you want to perform an upper operation on that element, right? So what you do, you just find a CSS selector for that element, but still you don't, you are not confident enough to perform any action because you are not sure about that. So how can we check such things? So I have one function which, so it will launch a browser. What we'll do, it will just open a browser, it will go to a support page and I want to click on a contact us button, but I'm not sure it's at the same selector that I'm using. So I'll just do a flash. So it will flash that, uh, in the browser. So I'm, okay, that's my selector. So it's not loading, it's instead of that, I'll just show you one video. So it's performing a, or creating a web issue. It is flashing everything before performing any action enclosure. So it's navigating to a help shift support page. It will click on contact us, then fill the form, and then click on submit, right? So with user is back, actually a macro, which hold, which launches the browser and holds the instance of driver, right? So every time I don't need to play with that instance. So this is the beauty of Selja web driver because I don't need to play around driver instance every time when I want to perform any operation on elements. I don't need to tell that driver that find this element by class name or find this element by ID. I just need to remember a convention that is get, so if I want to get an element by ID, I'll just say element. Then I'll add a hash before that ID name. Or if I want to just get element by class name, I'll just put dot before that class name, right? So this is how we do it in Selja web driver. So when you write Selenium test or any test, so basically we write independent functions, right? And all these independent functions, we call them in a single test. And all these functions are single test cases we can consider, right? And if one function breaks, it breaks whole test. But we don't want that because if I suppose consider an example where I'm creating an issue, and then it checks whether I got the email of that issue. And then I'm rejecting that issue. So if I don't get email, so check email function fails. But I don't want to fail the next function, that is reject issue. Because it should not affect. So to handle this case, what we do, we add tri-catch exceptions in each function. Because each function has a different exception, right? So it's like I'm collecting the things. I mean, I'm repeating stuff. I'm adding tri-catch in every time. Because my definite function doesn't provide this facility. So how can I do that? Because every language provides some way to encapsulate pattern, right? But without macros, I mean, the mechanism is incomplete. And most of the time you sense this incompleteness when you say, my life would be easier if only my language had feature x. But in Clojure, you just implement feature x using macros. So we have written one macro which takes a function. And if that function has an exception, it logs that exception. And takes screenshot of current browser. So you'll get to know, okay, this fails my case. And you'll get to know, you just don't have to look for that exception, the whole exception thing. You can just look at screenshot and get it done, right? So we have written a macro in Defend with log, which takes a function dog, it's dog string, it's argument and it's body. So what it'll do, it will execute the function. It will log everything. And then if that gives an error, it waits for two seconds. And then it takes a screenshot. And it stores in a directory, wherever you want, right? So I know this contact of function will work every time. But I don't know when design team changes the CSS selector. And it will fail. So at that time I just run this and it gives an exception. It should not break whole thing. It will just say, yeah, okay, I got it. I logged it and I taken a screenshot of it, right? So that's the easy thing to do in it. Yeah, so Calabash CLJ, it's an Android automation library in Clojure using Calabash JVM. So couple ready from Hellshift who wrote this library. And we've been using this library since last week or eight to 10 months. And we've had a lot of features to make it work very efficiently. So I'll show you one demo, so working. So I've written one function, Android demo. So I have one device connected with me. So it's a real device connected. I'm running on, and it's a mirror image of that device, okay? So when I run it will just launch an app. It will click on support page. It will click on a section and it will open an FAQ. Yeah, done. Now I want to do some interactive development for this Android automation. So what I want to do is, I don't want to launch it again. I just want to perform some operation from here. I want to go get back to a previous activity. So how can I do that? So with Android continue. So this is again another macro which executes a body against the current state of the Android app, right? So I'll just say Android, sorry, Android command and go back. Now I want to inspect elements of this activity because I want to perform some operation. I want to click on this, yeah? It's a macro. Yeah, it's a macro. So I want to inspect elements and I want to click on that contact us button. So I'll just say, but before that I will, I want to know description of each element. So what I can do, I'll say query. Query the elements of the current activity. So it will give me a description of each and every element. Now I want to click on that contact us button. So I'll say click. I want to click on this ID. I'll select, sorry, okay. Now I'll just click on this. So it's look easy while doing an iterative development. So I'm happy to tell you that I wrote this library so it is used for iOS automations and it's just a wrapper around Appium Java Client. So it is capable of doing everything that Appium Java Client can do, right? So I have demo to show for this. So what we'll do, it will click on contact us button and fill the form and then report an issue. And this is also a real device. It's not a simulator. So I forgot to mention the features of Calabash CLJ for Android. So in Calabash, we have added one feature. When you run an automation against Android App, so sometimes it gets, it crashes your app and you have to get error logs for getting those exceptions because you don't, you have, you have to know the cause of that cash log, right? So we added one feature where you say, this is my app name, these are my tags and this is type of my log, like error log or debug log. It will just give you in a log. It will capture a log, everything. It will just save in a file and you can, after that, after finishing your automation, you can just take a look at your logs if it crashes, right? So right now, it's built on top of Robotium and it's not that fast enough. And we know there is one library is pressed by Google, which is quite fast enough. So we are, the next step will be like integrating that server into Calabash. And also we are going to support Gradle for this because right now it's, it builds the app using and. So I showed you each individual library, that is for Selenium, then Calabash, and then Appium. Now I have to do some integrated development, like I want to perform some operation on Android app, then the changes will get reflected to a web app, then I will perform some operation on web app and it will get reflected to an and device. So you need to understand the use case. So for this, I'll explain you how to implement a Helpshift product. So Helpshift is a in-app customer support platform which enables mobile apps to improve their customer experience. So as Helpshift is built into your app, it is easy to communicate with your customer. And we have this real-time dashboard where you can manage a large volumes of conversations efficiently. So for this demo, what I'll do, I'll just say report an issue from Android device and it will increment the dashboard count of issue submission. So for this, first I'll launch browser, I'll go to dashboard and I'll take initial count of issue submission, then I'll file the issue from Android, and I'll check whether it count get incremented or not. So initial count is 96, right? Now it will launch browser, sorry, Android app. It will fill a form. At the end, it will reject the issue because every test should be idempotent, right? So it will go to issues list, it will match conversation title in issues list. It will flick on that issue and it will get an issue details page and there it will click reject on for that issue. Yes, so it's rejected issue. So as you can see it ran one test, yeah, it ran one test and passed four assertions. So that's it for the day. I hope all questions, I then think we are running out of them, right? So I'll take questions offline if you have any. Yeah.