 Mari kita mulakan pejabat kerja sehingga kedua-dua orang duduk di sini, tolonglah. Okey, selamat datang ke testing 0-100. Kerja saya di sini hari ini adalah untuk memberitahu semua orang mengenai testing dari unit testing ke testing API untuk ke belakang anda dan mengenai testing di depan dengan komponent yang akan dihubungi oleh salah satu orang mengenai dan sehingga mengenai testing unit dan unit, dan pengenai pengenai dengan pengenai yang lain juga. Jadi, kita akan mendapatkan anda dari testing 0 ke testing hero. Ya, sekejap introduksi tentang siapa saya, nama saya Shilin dan saya seorang co-founder dari UI Leisure. Kita beri peluang untuk anda untuk mengenai testing unit. Sebelum saya mengenai company ini, saya mengenai developer full stack pada peluang lain. Saya mengenai semuanya dari analitik dan semuanya. Sebenarnya, cerita saya adalah saya mengenai... Saya mengenai pengenai yang sangat teruk. Saya adalah pengenai pengenai junior sebelumnya dan saya mengenai test 0 sehingga saya menghubungi tangan saya terlalu banyak kali dan saya memutuskan untuk mengenai test dari sekarang. Jadi, sebabnya saya mengenai workshop ini adalah sebab saya datang untuk belajar bahawa ia bukan hanya saya yang tidak mempunyai test berharga. Sebenarnya, perniagaan yang saya mengenai sebelumnya, ia adalah perniagaan 6 tahun yang lalu. Sebenarnya, startup. Dan ada beberapa peluang dari peluang senior. Tetapi, perniagaan tidak dihubungi. Jadi, saya mengenai projek dan tidak ada projek yang mempunyai test. Jadi, saya mempunyai atau tidak mempunyai projek ini yang dibuat di jay curry dan angular pada masa yang sama. Jadi, beberapa peluang dari jay curry dan beberapa peluang dari jay curry dan beberapa peluang dari jay curry adalah peluang angular. Jadi, ia adalah yang saya membuat. Dan hanya itu, ia adalah juga jay curry UI plus bootstrap 2 plus bootstrap 3. Jadi, anda dapat mengingatkan jika saya ingin menambah satu feature baru, saya akan mengambil masa yang sangat lama. Jadi, saya mengingatkan jika saya perlu menambah kode untuk bersih untuk saya dapat bekerja. Tetapi, jika anda mengingatkan, saya tidak tahu kenapa saya mengubah satu komponen dan sebuah komponen yang tidak berlainan. Jadi, saya sangat penat. Kerana saya mengubah banyak bukti untuk produksi. Saya mempunyai banyak kali. Saya mempunyai tidak hanya peluang, saya juga mempunyai oleh pelanggan. Dia kata, Hey, kenapa anda seperti itu? Okey. Jadi, saya tidak dapat belajar peluang saya dan memulahkan perniagaan dan perniagaan sendiri. Jadi, saya biasanya mempunyai perniagaan yang tidak berlainan. Tetapi, jika ada satu perkara yang saya sangat berlainan tentang, ia adalah bahawa anda tidak seorang peluang yang benar-benar, jika anda tidak memulahkan perniagaan anda. Okey. Jadi, memulahkan perniagaan adalah sangat penting. Dan saya belajar untuk memulahkan perniagaan juga kerana saya ingin memulahkan perniagaan dengan peluang. Okey. Jadi, saya memulahkan perniagaan ketika saya memulahkan perniagaan. Saya akan memulahkan ketika saya datang kembali. Jadi, anda tidak mahu itu dalam hidup anda. Anda hanya mahu pergi. Anda tidak mahu tidur di bilik hotel anda dan memulahkan perniagaan. Saya tidak tahu jika perniagaan itu okey atau tidak. Bolehkah saya periksa e-mail saya atau tidak? Okey. Jadi, anda tidak mahu itu. Anda hanya mahu tidur di dalam bilik. Jadi, hari ini, saya bercakap tentang menarik perniagaan dari belakang anda ke belakang anda dan menarik semua perniagaan. Okey. Jadi, boleh saya hanya mendapatkan perniagaan yang benar-benar yang menarik perniagaan? Atau perniagaan yang unik. Okey. Bukan betul. Okey. Kita memiliki 50%. Jadi, ia sangat bagus. Jadi, hari ini, ini adalah apa yang kita akan menarik. Jadi, saya sudah beritahu. Kita akan menarik perniagaan unik dengan Moka dan Chai. Semua ini adalah javascript kerana ia adalah js.com. Jadi, saya tidak akan menarik JUnit di Java, tetapi perniagaan unik dengan Moka dan Chai. Kita akan melakukan perniagaan api dengan Chai Http. Dan ini juga mempunyai menarik perniagaan anda dan menarik perniagaan anda dan menarik perniagaan anda dan perniagaan anda supaya anda dapat perniagaan mudah untuk menarik perniagaan anda dan kita juga akan menarik perniagaan dan perniagaan dengan web driver AI dan juga dengan menggunakan uI Lashes dan bahan bonus kerana kita mempunyai beberapa perniagaan yang menarik di js.com jadi kita akan menarik mereka dan juga meminta dia untuk melakukan beberapa demonstrasi perniagaan dengan aplik-tools seperti jas. Jadi, saya rasa untuk mulakan baga bagaimana kita dapat melakukan perniagaan 100% perniagaan. Ia seperti ini perniagaan dan perniagaan yang anda tak akan menarik. Tapi kita akan mencuba dan perniagaan 100% tak cukup untuk anda untuk membuat perniagaan anda tak cukup. Jadi, perniagaan yang tak cukup adalah sebab anda boleh anda tak boleh hanya menarik perniagaan dalam isolasi anda perlu menarik perniagaan apabila mereka bekerja bersama-sama jadi ini sangat kecil anda tidak mahu berdiri di depan dalam perniagaan dan kemudian mula menarik perniagaan anda seperti jadi ini tentu-tu perniagaan-perniagaan tidak telah di sini jadi itu adalah tiga layar perniagaan kita ada Oh, saya tidak boleh saya tidak boleh berjumpa lagi okey jadi kita ada tiga layar perniagaan yang adalah perniagaan unik di bawah anda dan kita ada perniagaan dan perniagaan jadi ini adalah dalam struktur perniagaan sebab apa yang anda sepatutnya anda sepatutnya menarik lebih dari perniagaan unik dan lebih dari perniagaan perniagaan dan perniagaan jadi sebab tiga layar di atas perniagaan mereka memarut lebih banyak pilihan anda dan sebab mereka memarut lebih banyak pilihan anda dan mereka juga mempercayai lebih banyak pihak mereka rendah lebih lama untuk mengawal jadi jika anda ingin menjadi sangat efeksi mengenai perniagaan anda lebih banyak perniagaan unik anda dan selama apa yang tidak dapat dilalui pilihan unit anda menarik perniagaan dan semuanya alih perniagaan sebagai Jika anda menulis semuanya dalam test UI, test anda akan terlalu mudah. Test anda juga akan terlalu mudah. Jadi ia adalah cara anda membalaskan semua perkara ini. Saya rasa ini adalah salah satu perkara yang orang akan berkenal apabila saya bekerja dengan pembinaan yang mempunyai zero test, seperti perniagaan saya, bahkan pelajar-pelajar kemudian, kita akan berfikir, ya, ya, kita harus menulis test. Tetapi semua, seperti itu, ada dua pembinaan. Jadi kita sebenarnya mempunyai pembinaan. Mereka berkata, kita patut mulai dari unit test. Dan satu pembinaan berkata, tidak, tidak, tidak, tidak, kita patut mulai dari pembinaan. Kerana pada akhirnya, ia adalah cara semuanya berkata-kata. Itu lebih penting. Dan kemudian untuk saya, ianya seperti, saya tidak peduli, anda memulai unit test atau api test, atau pembinaan test atau test UI. Seperti jika ada test, ia memulai sesuatu yang lebih baik. Seperti 1 persen test yang lebih baik daripada 0 persen test. Jadi, dan satu pembinaan yang baik, jika anda ingin menerima, jika anda menulis semua pembinaan ini dan anda masih pengetahuan, okey, keadaan mana yang terbaik untuk memulai pembinaan kerana ia sangat mengawal itu. Kemudian, saya rasa ia selalu baik memulai pembinaan yang terkenal, yang anda terlalu takut untuk membuat keputusan. Anda memulai pembinaan untuk itu. Jadi, untuk saya, apabila saya bekerja pada projek itu, saya sebenarnya tidak memulai pembinaan untuk test UI dulu. Saya sebenarnya menulis pembinaan untuk model pembinaan kerana kami memiliki pembinaan yang sangat kompleks untuk bagaimana kita patut memiliki pembinaan. Pembinaan perniagaan mempunyai idea baru setiap bulan. Jadi, mereka mahu mengubah pembinaan untuk bagaimana mereka mahu memiliki pembinaan. Jadi, untuk saya menjadikan bahawa logiknya masih betul, saya menulis pembinaan untuk saya mengubah, kemudian saya akan mengubah logik menurut pembinaan dari perniagaan perniagaan. Jadi, itu adalah pembinaan yang menarik untuk saya kerana jika pembinaan memiliki pembinaan, dan kami tidak memiliki pembinaan. Pembinaan YOLO SMANI dan GANAS pun lebih teruk. Jadi, itu adalah pembinaan yang menarik. Kita akan memulai pembinaan yang terkenal jika anda tidak dapat memikirkan tempat yang baik untuk memulai pembinaan. Jadi, kita akan memulai pembinaan untuk beberapa pembinaan. Jadi, pembinaan ini adalah mencari pembinaan kerana kita akan mencabar pembinaan. Pembinaan Pembinaan sebenarnya. Jadi, pada akhirnya, kita akan menjadi pembinaan. Kita akan mencabar semua pembinaan. Okey, kita akan memulai pembinaan. Jadi, saya perlukan anda untuk mencabar pembinaan ini. Dan memulai pembinaan dan memulai pembinaan NPM. Dan jika anda ada masalah melakukan pembinaan NPM, anda boleh panggil saya dan TAA saya, yang adalah Eugene di sini. Dan juga Aaron di sana, yang akan membantu anda jika anda memulai pembinaan NPM. Jadi, kami akan beri anda sekitar 10 minit untuk memulai pembinaan. Dan saya akan mencabar pembinaan jika anda perlukan bantuan. Adakah anda mempunyai water? Water? Water. Water? Thanks. One water? Okay, thank you. Okay, one water? It's okay, I'm fine, thanks. You want some water? Okay. Do you want some water? No, thank you. Okay. Water? Okay. Do you want water? No, thanks. Okay. Do you want? Maaf? Moka is global. Moka is local. It's not inside your install definition? It will be installed later, it's the latest steps. Oh, okay. It's like, they will install it as the... The DB is not populated yet, right? Yeah, the DB is not populated. They will populate it in exercise tree. Okay. Do you want to pass out the water? Okay. I'll pass it out. Yeah. Okay, so... Water? Yes, no? Yes. You need help? No. I need water. Oh, you need water? Oh, it's over here. What's the issue? Ah, no. It's not crone properly. So I'm just going to redo the crone. Okay. But the crone is not working. No, it's not working. No, crone. Crone is not working. So it's a different problem altogether. Oh, okay. I guess we just proceed with one again. Ah, okay. Okay. Okay. Hmm? We both... Their desk came in. Ah. Alright, bigger. Oh, yeah. He said writing is very small. Ah, this block is also not that big. Ah. Because I think it does actually do a trick for the dip. Yes. They just dive down there. Oh. So I can ask them for some more. Do we need green? No, no. This one is fine. Oh, okay. Okay. We're just going to move ahead first. And if you need any help, if you're lagging behind, you can ask the TAs to help you. So I'm going to go ahead and explain the structure of the project first. And we're going to start with testing with Mocha. So let me open up the project. So over here in our project, we have what we want to do is to test the Pokemon class itself. So the Pokemon class is just very, very simple. It just sets the attributes of our Pokemon. So our Pokemon class is inside models Pokemon.js. And if you open it up, you can see that the Pokemon has a number of attributes. It has an ID, it has name, it has types. You can set it as a bug type, a grass type, electric type. There are some other attributes that says how strong this Pokemon is, how fast this Pokemon is. Does it use any special tags? And whether or not it's a legendary Pokemon. So what you want to do is to make sure that we do a few simple tests like testing whether if we set the name of the Pokemon. Yes? Or zoom in. Is this big enough for folks at the back? Ken? Okay. So we're going to test the set name method of Pokemon. And when you set the name you should obviously check when you get the name it's the same name. So what we want to do first is to make sure that we're going to use Mocha to run to set out our test. And Mocha is a testing framework. What it does for you is to manage the setup, the execution, the tear down and reporting your test. So you can actually plug-in different assertion libraries to Mocha and Mocha can still will just run using those libraries. All it does is to catch whether the assertion library throws a type of error called the assertion error. And then it throws assertion error it would mark the soon as a failure. So besides that you also do the tear down and the reporting. So the reporting you can actually plug in any kind of reporter. So the reporter that we're going to use is just called the spec reporter but you can actually change it to a HTML reporter if you just want to see your test printed as a HTML document. So you just keep things simple. First thing first set do MPM install Mocha dash save dash and this usually have the script test script set out so you don't need to do this step anymore and the first step is what we're going to do. First exercise is we're going to test Hello Pikachu. So once we let's create a test after you have done your MPM install Mocha Okay, let me just delete this. So first thing first just do MPM install Mocha save dash if haven't already and what we're going to do is we're going to set up our test in the test folder. So some of the test has already been created for you. So let's write our test in unit test one dot Pokemon and how Mocha works is the test suits to define a test suit you use the word describe so we're going to say describe Pokemon and within describe Pokemon we're going to create another test suit itself to test to group the test for set name together so we could test every we could test whether it be set name with an empty value whether it produce an error or we can test if we provide a proper string whether it properly sets the the Pokemon name so these are two test cases but we want to group it into one test suit together so we're just going to create another test suit say describe the set name function okay so what we're going to do next is we're going to import our Pokemon class so Pokemon require from the go up one level two level models and Pokemon so now if you want to define the test script itself we need to say eat so this is the case itself and what we should what we want to say what we want to put in the first parameter is a description of the case itself so for this case we should just test it should set name when given non empty string and then we proceed with the function and we'll write our test script over here so we're going to create our Pokemon var Pokemon it goes to new Pokemon so the Pokemon constructor we're just going to leave it blank first and we're going to test the setting of the name through the name function instead of through that constructor itself so Pokemon dot set name and we're just going to call this one Pikachu and what we have to do at the end so every test has to test one hypothesis and also have to have at least some assertion so what we're going to assert here is to say I expect that the the name of the Pikachu is equals to the name of the Pokemon is equals to Pikachu so add assertion here so Mocha itself doesn't come with any assertion libraries built in but Node.js has an assertion library so we're going to import the Node.js assertion library cons require assert actually assert equals to require assert okay so I'm going to open up the Node.js assertion library so this is the documentation for the assertion library in Node.12 and what you can see is I think the the one that the assertion that we want is this assertion so we just want to say assert the value is equals to and what it does is it wants the input to be evaluated into true value so if it's not true it will print out the error message so what we're going to do here is assert Pokemon.name equals to Pikachu and if it's not Pikachu we just print out Pokemon name should be Pikachu we can actually I believe the message is optional so we can actually take this out and they would generate a default assertion message for us okay and to run the test if you already have this I usually already have this set up so script.test so we I have already broken it up into different types of scripts for unit testing for API testing and end-to-end testing but what we can just do is npm test to run our test over here and over here you can see my results after running the test it says yes it's correct we are able to set the name to Pikachu correctly so let's say if let's just break this test on purpose and just say that okay I think this supposed to be Pikachu instead of Pikachu and we can just run this test to make sure that it feels actually it's not correct hmm not to show why is this not not validating hmm can let's use the equal instead of double equal so we can also use the equal method which says this is what you actually get and what is the value you expect so let's try this and maybe this is better okay now this is feeling so the Node.js assertion library is a little bit weird sometimes so to be honest I don't like using Node.js assertion library by itself and I would rather use try so yeah I'm feeling this test on purpose yeah so if I put it just to make sure that the assertion library works sometimes you must check if the your test is valid so it's always good to just fail your test on purpose just to make sure that your test is working in this aspect yes another question we heard in Java that we were working the expected value left what do you think of say very long it depends on the assertion libraries you import actually so over here we are using the Node.js library so the documentation if you read the docs it wants you to put the actual value and then the expected value so we're gonna use another library we're actually gonna use the chai library next so the chai library let's you write test in a BDD style so BDD style let's you describe your test like regular English language so it's chai supports two forms of BDD style syntax one is shoot and another one is expect so that one would sound a lot more easier for you to read as well so we're gonna try importing the chai library next and to test our to write the same test in the chai style okay so let's get rid of this assertion library and we're gonna import the chai library instead so if you haven't already done so just do NPM install chai and save depth as well and while it's installing we're gonna import the shoot syntax so cons shoot equals to require chai and chai provides you a module called shoot but you can't just import shoot on its own you actually need to call shoot so what shoot does is that it extends the object class so this will extend the object class so that what you can do here instead of saying assert equals the actual versus expected you can say pokemon dot name shoot okay should be equal pikachu so we're gonna go ahead and run this and this is passing with the shoot syntax as well so we can take a look at the chai library itself to see more of the different kind of syntax that shoot provides us so you look in the API and you can click on the shoot and expect syntax you'll see that it's very English-like and what you it provides you a language chain so you can pretty much chain your test as if it's English so some examples is let me see if you can find some shoot yes one more so for those especially those with installation errors if you are lost at any point at any once you catch up if it's not obvious everything that was being stroke through on the key part with me is in that same repo so you can follow the steps in there also I think a few of you look like now that we have a typo in there regarding the body parting the dot dot slash meaning dot dot slash dot dot slash Ya I might have nested the test in one more level when I was finalising the workshop so it might a little bit be a little bit different in the actual documentation here so anyway the shoot syntax I'm having a little bit trouble finding the examples for shoot in the chai but you can see that is expect if you want to check equals I think let's find equal so equal is very similar to shoot equal is just expect the actual the value itself to be equals the actual value you expected to be so and you can do a lot of kind of assertions for shoot so we can do should expect the Pokemon name to be a string so maybe you could pass in a number and maybe you expect it to be close into a string you can also expect you can also pass in the Pokemon types if you pass in two types like the bug type and the grass type and then we can say ok go grab the type and make sure that the types exactly length of two so make sure that we didn't just add two types and we get one out so that is you can do a lot of kind of assertions so let's try doing your maybe they expect syntax instead so to import your expect class the expect assertion we do something similar as well we can require we need to require the module require chai and we require the module inside chai that is called expect and we can say expect Pokemon name to be equal Pikachu and run this again and make sure that it still works so it still works so this syntax so it depends on what what you are comfortable with you can choose the should syntax you can choose the expect syntax or if you just want to use assertion as well we can do that but it's always good to test happy scenario users will make mistakes so it's always important to test if your application throws a proper error message so let's try testing if we what happens if we set the name to be an empty value so if you try to set empty value on Pikachu or on the Pokemon it should throw you an error that says the name is required so you can create a new test case and says it should throw error if name is missing so we're going to create our Pokemon again and we'll set it to empty so what we're going to do is we're going to be using the Chai's assertion library instead of the Node.js assertion library to check for errors so the reason for that is Node.js assertion library seems to not work in the way that I expected to so Chai's the way Chai's checks for error it makes a little bit more sense to me okay let me find so you can test 2 scenarios you can actually test throws and test does not throw but we're going to test throws instead so throws accept function as the first parameter so the function is the the code they expect to throw the error so we're going to actually import the Chai assertion library first so so we are replacing this native assertion library Chai assertion library so let's go ahead and require Chai first Chai.assert and what we're going to do here is we're going to do assert.trows function and we're going to put this piece of code over here that should throw error into the first the function so when if you set name with empty variable this should throw an error and I believe the error name is called name cannot be empty so there's other types of assertion going on so like name cannot be string you can test that if you want to as well but you're going to test name is empty so the second parameter that assert the error message itself so it shouldn't throw a generic error it shouldn't throw like type error it should throw the proper error that says name is empty so that it's actually helpful to whoever's using this library whoever's using this set name method itself go ahead and run the test so now we have two tests so we should see two tests being ran our first test which is if we correct this it would so if we actually set the name and it didn't throw any error the assert.troll will throw an error will fail the test and say well we are expecting an error to be thrown over here but that didn't happen so this is how we should test your negative scenarios as well okay so it's very simple to write test for synchronous functions but then if you want to test callbacks and promises Mokka can handle that as well but the way you write your test for callbacks and promises it's a little bit different depending whether you're testing a promise or you're testing a callback so how Chai expects you to write your test for callbacks for example it gives you a done function so that when you finish doing your callback you can call and you should do your assertion and then after that you call the done function to tell Mokka that you're done with this test itself so for example if you are testing a function called chef.makeSandwich and we can pass and we expect the chef to make sandwich to either give us an error or sandwich like error could be like there's no sandwich and or to give us the sandwich back you could say like okay if error then call the done function with an error otherwise oh we we don't have an error but we expect the second parameter sandwich to exist and then once we done with your assertion we call it done function so if you are doing a promise instead we should eat similar but Mokka is able to handle promises on its own so all you need to do is to return the promise so let's say chef.makeSandwich is a promise instead of a callback you just say chef.makeSandwich then if the sandwich we got the sandwich then expect the sandwich to exist otherwise we will catch the error and then throw it back up and Mokka will just handle the error okay so we're going to try this with the PokiDex so the PokiDex say is the database of your pokemons itself so you're going to create another test we're going to start writing our asynchronous test in number 2 pokidex.js and let me check so let's try writing a test for the save function of PokiDex so when you save a Pokémon to the database and if the Pokémon doesn't exist we should get the ID the ID for the Pokémon should be set so we can set that up so you create a suit called PokiDex okay you can describe the save function and then our test is just it should add Pokémon to pokidex so the pokidex is inside our db folder itself so if you open it up the entire pokidex is a inheritance promises so you can see that we need to connect to our pokidex with a storage and we'll close it there's also a save function to add the Pokémon to the pokidex okay so let's create our pokidex let's also import our pokidex first and we need to connect our pokidex to a storage mechanism so we're just gonna so we're gonna because everything is is a promise it will actually be simpler and easier for us to re-using the async await method so we're gonna add async to the front of our function over here so async and then we're just gonna await for our pokidex to be connected to our storage await and we're gonna we're gonna save our pokidex our our connect our pokidex to a storage file there's we're storing our data in a with MySQL Lite so it will actually just save it to a file storage and test the sql lite tree yeah this will be fine okay so so we're gonna create our Pokémon but Pokémon again new Pokémon import the Pokémon class models Pokémon and then after we created the Pokémon we're just gonna say okay pokidex save the Pokémon to the pokidex and we're just gonna await this and at the end of it what we're gonna do is we're gonna assert that the Pokémon ID exists pokimon.id who even say that okay the Pokémon ID should exist I believe and the Pokémon ID is a string maybe I believe it's a string oh I think it's a number actually yeah should to be okay I think it should be a string yeah the ID yeah so we're gonna save the Pokémon to the pokidex and the pokidex behaviour is that if the Pokémon never existed ever we are gonna set an ID for the Pokémon okay cannot let me check this oops I think we need to initialise our yeah we need to create the DB first sorry about that let me check our instructions for creating the DB so there let me check if you if you guys get lost there is a test.solutions folder which I'm gonna cheat with and actually grab our DB setup function which I think is not here either yeah yeah so give me a bit of time to test if this works okay hmm oh actually the failure is because the Pokémon name is not the same I think I ran this test before next migrate yeah you need to run next migrate let me just check this out first okay okay so so what you need to do first is let's skip ahead to this segment here I need you to install next and to set up the database so the instructions here is npm install next dash G and then run next migrate up with the but change the environment to test itself so npm install next dash G so after you install that you're just gonna run the migration function which is next migrate up but change the environment from development to test okay why isn't it able to okay if you get this command that say you cannot open the database file that means you need to create your storage folder why is it still not able to yep so what this does is it's gonna run the migration steps and it's gonna become relevant later so in these examples we are just gonna run the test first beforehand but later on in data examples we are just gonna get the test to always roll back the database and to migrate it up and then to seed your database so first we are just gonna do the migration by hand first and then now let's run the test again npm test so this test is now passing because we finally set up the database and it's running the test to say that it should add the Pokemon to the database and the Pokemon ID should exist and the ID should be a number so it's anyone stuck so far with the okay guys a bit more time to get this set up because next can be a bit tricky so so I'm gonna repeat the instructions again to set up your database after you install next globally we are gonna run the migrate up and what migrate up actually does is gonna run all the migrations within this folder over here so if you look at the migrations folder you'll see that there is two functions over here one is up one is down up actually does the setup for you and over here it's gonna create the Pokemon's table with the incremental ID and the name and then it expects the name to be unique as well and it will create a JSON table JSON column and all the attributes and timestamps as well and then if you say migrate down it's gonna just drop the table okay oh no what happened here there's not much not enough power I wanted to charge that but it doesn't want to charge from here I think there's not enough yeah I think there's not enough too many you're not able to you don't have you're not able to connect to this directly yes yes you can right this is finished I forgot I have English not sure if it's still working because there's not enough power here because there's like busy chaining yeah yeah sorry which is could you scroll to the part where we drum database okay so could you go to the readme if you wanna jump ahead and go a little bit faster you could go to our readme ah okay ya so it's set number 2 uh exercise I believe ah there we go so you can start from here actually so you pukit x dot drop table and 3 yeah mmhmm and we're gonna do a more complex form later on oh yeah what do we do no such table okay so so what we have to do is to have you install next okay you have so oh I think you need to do run the migrate migrate up command again I think it's you're stuck there because he's complaining that the table is not set up migrate up again yes so it's ready up to date can you run the test again what do I do ya run the test mpn mpn test to run the test ya so now mpn test to run the test ya run do you have the second you're not running the pukit x test so where is your pukit x test ya so we are testing the pukit x so that we can test the assertions okay so aiding we can follow the read me where continue from this part here so you can continue from this part over here so testing promises so you can write your test for testing the pukit x so that we can actually test the the database itself ya okay ya ya last thing but there's mine it's definitely the skill right have you do you have the storage folder or it's or it says okay so can you I think it's dot slash because you're running it at the root ya ya ya okay now if it says insert you need to run the migration script to set up the database so actually the database has to be named test.sql because it's configured to test ya oops ya then you need to run the migration script actually so the migration script is ya but change environment to test so that you are migrating the test environment okay created a table so you can run the test again ya ya it works ya if you run it again you will get error the second time ya when were you planning to talk about the snapshot it will be last I think it will be after epi 2 I will try to actually skip some of the parts like call back so that so I think maybe in one hour ya ya so ya ya ya ya Kami bergerak. Ya, itu sebabnya. Ya, tidak. Jadi, kamu bergerak? Ya, saya bergerak. Jadi, Ok, jadi jika kamu mendapat keadaan keadaan ini, kamu perlu bergerak dengan migrasi dan berubah ke periuk. Ya. Ya, jadi bergerak. Jadi, ia sudah bergerak. Boleh kamu bergerak? Bergerak lagi? Ya. Jadi sekarang, sebabnya kamu sudah mendapat keadaan keadaan ke periuk. Bukan kamu mendapat keadaan keadaan keadaan ke periuk. Jadi, itu sebenarnya keadaan yang akan kita bergerak. Tapi kamu boleh bergerak dengan saya jika kamu mahu bergerak lebih cepat. Untuk membesar keadaan keadaan ke periuk. Tidak. Jadi, jika kamu mendapat keadaan yang berkata, kamu tidak boleh bergerak dengan keadaan ke periuk. Kerana nama Pokemon mesti adalah keadaan keadaan ke periuk. Jika kamu bergerak dengan periuk, Pikachu sudah bergerak kerana kamu bergerak dalam periuk pertama. Jadi, apa yang kita perlu lakukan adalah memasak keadaan keadaan ke periuk. Dan apa yang Mokka lakukan, ia memberi kamu keadaan keadaan ke periuk. Jadi, setiap kali kita bergerak keadaan ke periuk, kita akan bergerak keadaan ke periuk dan bergerak lagi. Ya. Jadi, sebelum kita bergerak, kita bergerak ke periuk Pokeducks. Kita akan berkata sebelum semuanya. Jadi, Pokeducks, ada sebenarnya banyak periuk. Ada periuk sebelum. Periuk seterusnya yang bergerak sebelum dan sebelum semua periuk. Kemudian ada periuk sebelum seterusnya. Tapi kita akan buat sebelum seterusnya supaya kita dapat setelah setelah periuk untuk setelah periuk. Apa yang saya akan lakukan adalah saya akan bergerak ke periuk Pokeducks ke atas sini. Sebelum semuanya. Baiklah. Sebenarnya saya tidak... Sebelum setiap periuk, kita akan bergerak ke periuk. Dan saya percaya kita ada... mari kita lihat. Kita akan panggil Pokeducks. Kami juga dapat selesai Pokeducks selepas setiap periuk. Kami akan bergerak lagi. Ya. Sekarang kita akan bergerak dan bergerak. Ia akan bergerak sehingga pikachu tidak lagi ada periuk. Setiap kali kita bergerak, ia akan menyebabkan pikachu ke periuk baru yang sekarang, anda akan mendapat periuk yang mudah dengan setiap kali. Baiklah. Ada sesiapa yang bergerak? Baiklah. Kita akan bergerak ke periuk api anda. Jadi mari kita mulakan periuk kita supaya kita dapat menyebabkan periuk api. supaya periuk api bergerak supaya kita dapat menyebabkan. Untuk menyebabkan periuk kita, saya fikir kita tidak dapat menyebabkan pasangan ini. We have to run the migration test script again for the development environment so that when we start the test, when we start our server it will start in the development environment. So you are going to test that. So run your migration test for the development environment and this time there is an additional command you have to run the seed command. So this is going to run the seed file that will add the first generation of Pokémon sehingga apabila anda mendapat api, ada sesuatu untuk anda bekerja dengan. MPM, mulai. Sekarang kita mempunyai test pada port 3000. Jadi anda patut dapat melihat ini. Okey. Jadi anda patut melihat aplikasi anda di sini. Dan api, kita akan melihat api.Pokemon, mulai. Ya. Jadi anda patut melihat api.Pokemon. Anda patut melihat sesuatu. about 151 pokemons. Jadi jika anda tidak mempunyai semua pokemons, anda patut menerima tangan anda dan dapat bantuan. Jika anda melihat cd.js, bagaimanapun anda menjelaskannya, apa yang ia akan berlaku adalah, ia akan mempunyai database pokemon. ia akan membunyai segalanya. Dan ia akan membaca pokemon.csv file yang mempunyai banyak pokemons. Tapi hanya pakej pokemon. Dan ia akan membaca cd.js, dan menginsertnya. Jadi kita dapat semua pokemons. Dan setiap kali anda mencari cd.js, ia akan membaca semuanya dan melihatnya. Jadi mari kita cuba menerima test api. Untuk menerima test api, ada beberapa plug-ins yang anda boleh mencari. Satu-satunya perkara yang baik mengenai cd.js, adalah yang sangat luar biasa. Jadi banyak pengalaman untuk cd.js yang digunakan. Jadi mari kita lihat di mana ialah dunia kita. Jadi, salah satu plug-ins yang digunakan di sini, adalah cd.js-HCTP yang kita akan menggunakan. Ada juga cd.js-JSON schema, yang anda boleh menggunakan untuk mendapatkan jika cd.js menerima cd.js, ia mencari cd.js yang mereka menunggu. Kamu boleh menggunakan dsp NINS untuk menerima memasak element para veri memiliki kautik nama самое Q Dait dan juga kwalt p força bidang. Dan kita boleh menggunakan p MEML para ni. Bagaimana nama menu dengan menu K, saya akan menggunakan gunakan K dan membuat versi yang sangat seronok dari Chai. Ia sebenarnya cukup menarik. Jadi Chai Doge, instead of saying, describe it as such, get tricks. Wow, very test. Ya, so it's just for fun. Ya. Okay, so let's start writing our API test. And before we write our API test, please install Chai HTTP. And now we're going to start working from a new folder again. Go to API test. And we're going to create a new, we're going to import the Chai HTTP to our application. Okay, so once you have installed Chai itself, you need to call chai.use.chai.http to use the plugin. We're just going to copy that. And then we're going to do the same thing and describe. And let's call this API test. And let's grab this and let's test our get API Pokemon. And then it should get 151 Pokemon. Okay, maybe it should retrieve. So let's take a look at the Chai HTTP documentation itself. And for, to you to do a post request to Chai, what you have to do is to say, okay, Chai.request, the base URL of an application, and then the path that you want to test. So let's just grab this. And our application is hosted at port 3000. So let's just change this to 3000. And we're going to get the API Pokemon's request. And then the last thing you have to do is to do send.send to perform the request itself. So this is also a asynchronous request. So you can either use a callback or you can, or you can use promises to handle this. So Chai.request actually returns both a callback. There's a callback version and there's a promise version. So let's just use the promise version. Say sync. And after you send it, we want to say, I believe it's a then. So what you should do is you then you expect a response. Otherwise, if there's an error, just throw the error out. So then now we can assert the response itself. So if we look at what sort of assertions does Chai support. So the Chai HTTP plug-in, it extends the expect syntax so that you can have expect to have status 123. So you just want to make sure that it has status 2000 first. Then you're going to run out of test again. Okay. Expect is not defined. I'm missing something. Sorry? Yeah, I forgot to put that in. So I think my documentation is missing one part. So you need to require to expect library first from Chai. And then you call Chai.useChaiHttp to use the plug-in and you extend the expect library. Let's run the test again. So we expect the response to give us back 2000. We can also expect the response to have... Let's just test the haters. So let me cheat a bit and look at our solutions. So let's add this in and take a look at this. So there's a lot of assertions you can do on your request. You can say, okay, expect the status to be 2000. Expect to have a content-type hater that should be a JSON in UTF-8 format. And we want to make sure that the response we get back is a JSON. And the response body itself, we want it to be a type of array. And let's make sure that we have 151 pokemons, actually. And the first pokemon that we should get its name, it should be barbasaur. If it's not in this order, then it's not correct because we seeded our data with the first pokemon to be a barbasaur. Okay, so I think it got different. I think I have seeded the wrong data for myself. So I actually have 721 data. Let me redo my... Okay, my seed file is kind of wrong because it's seeding me 721 pokemons instead of 151. But I'm just going to go with that and change my test. Okay, there you go. So if you want to test post request, it's actually pretty straightforward as well. So let's take a look at the solution for adding a pokemon. So if you want to do... you want to add a pokemon instead. So you can actually just say post the API that you want and then send the data over. And then you can do the same thing. You can kind of expect... Let's just add like... There's mule 1, there's mule 2, let's add mule 3 over there. Just add this. And it will send the pokemon, the mule 3 over to the API created. And then we expect the response to give us back the mule 3 pokemon itself. And the body should contain a JSON with the name of the pokemon being mule 3. Okay. So similarly for API test, because it's still interacting with our database, we want to set it up and tear it down again. We also don't want to always keep our database, our web server to set it up. We want to automatically get the test to start the server and to turn it off again. So to do this, what we can actually do is to use... Chai can actually automate... Chai HTTP can actually do this automatically for you. So all you need to do is to say, let's just listen to your application and then what it does is before each, it will start the server and shut it down. Instead of you having to say, the port of the server is at 3,000 and before you start run the test, you need to open up the server. So that's a little bit of a two-step process. So we're going to import our application. So const app equals to require the server value. So again, import our application and then instead of saying request the absolute URL, we're just going to say request the application and here it's requesting the application as well. And let's just run this. Oh, app is not defined. Hmm. How am I having some indentation error? Okay. So this is essentially the same as what we're doing before, but what it does is it will automatically turn on your server and turning off when you're done. So then we are going to set up our hooks again so to clean up our database as well. We're going to import each and I'll be for each again. Okay. So what we're going to do is we are going to previously we've been running our next migration script by hand in the command line but we want to be we are developers. We want to be as lazy as possible. We actually want the test to run the next migration script on its own. So we are now next to set up with the following configuration file which is the test environment configuration file. The configuration file is defined in the next file. I think the path here is wrong. It might have to correct that. So the next file is defined in your root itself and the root defines that the environment, the file name for development, and the configuration from there. And then what we'll do is we'll run the rollback script. We're going to run your next migrate down which simply just drops the database and then next migrate latest actually upgrades all your schema to the latest version of the migration and then what we're going to do is before each of the test seed the database again. So when you seed the database, it will just drop and put it back again. So I'm just going to copy and paste this and put it here. And also remember to import. So you don't need to import next because it's already here but we actually need to set the process to be test. So we just put it here. So this is what it should look like when your let's run the test again. Just failed. It cannot destroy of undefined. Or next is undefined. Why is next undefined? What's going on here? Okay, I'm not too sure why the previous code was complaining that next was undefined but I just copied my solution and pasted it again. So try this out and you should be able to retest your add function so we can actually try doing this 2x just to be sure that we're going to try add Mew2 in 2 different tests and you should not show us any error. So we're just going to try this just to make sure that it's okay. It's mine. Okay, for some reason I'm getting 151 instead. So 151 here. I added the addPokemonTest 2x on purpose just to make sure that the seed is working. So let me get my terminal again. So it's adding the Pokemon twice but it's like no problem the seed is working and it's carrying a database between each test. So is anyone stuck? I'll give you guys about 10 minutes before we move on to end to end testing. Let's go toilet as well. You will probably run into some errors so ideally try to set it up so that we can save a bit of time and then if you need some help you can go grab one of the TAs around here. So we can run the setup for exercise 3.2 if you have a bit of time. Some notes about using NEX no matter whether your project already uses NEX for the database you can just use NEX on its own to seed the database so that's helpful enough for you to get some of the tests seeded. So we have all your backend covered with unit testing and API testing so let's test your frontend itself. So for frontend itself we usually perform and one very strict way of defining acceptance testing is that the software needs business requirements but business requirement sounds very unrelatable so a better way to just define acceptance testing is does it work for the user so one thing that we want to make sure how we want to structure our acceptance test is like user stories so a user story should contain what the motive of the user what he wants to do in the application and if you want to just get started with acceptance testing you just cover all your happy flow first because in each cases there can be a lot of things it can be very exhausting but if you just want to get base coverage just do all your happy flow first and then we can cover negative testing to make sure it's because they are human sometimes maybe they are older folks like my grandparents or my parents and sometimes they will just not know how the UI works and do something wrong the application should be helpful enough to give an appropriate error message so that they can recover but that's again negative testing that is very exhaustive so if you want to start you don't get overwhelmed with front-end testing so there's actually many ways to set as your front-end besides acceptance testing there's also component testing which we will cover later on so there are a few tools to set up your UI testing so it can be very elaborate as well to set up your UI testing because if you think about it your consumers are using your application code in Firefox Safari, IE H then that's just the desktop they will be looking at it in mobile iPhone Safari mobile which is different from Safari desktop and then you have all the Asian devices that have Vivo and then the Chinese browser that's the UC browser with the scroll icon so there is a lot of infrastructure to set up if you want to keep it simple we can use different tools so there are providers like Browstack like source that provides you infrastructure so they don't have to think about it if you want a DIY which I will cover later on you can do so as well but just fair warning is not a walk in a park because for me to write this create this workshop even though I'm experienced in setting up Selenia documentation has changed in the last 2-3 years so I had to figure out how to set up Selenia all over again for the latest version of Chrome and Firefox etc that spec changes a lot and you really don't want to touch this if you can, you should try to avoid setting your own Selenia up so I'm just going to do a demo of how you can test UILicious and what we do as UILicious is we provide something like a code pen for you to test your application so for what we're going to do is we're going to start our server again so let's start our server and begin and our oops, I think I have something running yeah, port 3000 is already in use sorry, I have port 3000 open and the next thing you want to do UILicious requires your application to be exposed to the internet so what we're going to do is we're going to use Enggrok which allows you to slice the interface Enggrok so if you haven't already installed Enggrok you can just do MPM install Enggrok there are other alternative to Enggrok you can go ahead and start starting up start up Enggrok and you want to expose your port 3000 so when you say Enggrok HTTP 3000 it's going to set up HTTP server that listens to port 3000 and gives you a public URL like this so this is the public URL that I got f2282755.enggrok.io and if I open that it actually loads this application which is my own application itself if I actually turn off my application over here let's go it's still loading all the images so if I turn it off and I load it, it's just going to say it's not there, application is not there turn it on again so once you've set that up it's going to take a bit of time to load all the assets so sometimes it will complain that there's too many connections it's probably too many connections because of the images let me oh sorry I am actually going to set up an alternative because Enggrok throttles the number of requests that you have let's see just for yes so if you're having trouble setting up Enggrok and Enggrok is complaining that there's too many connections there's an alternative service called Servio and what you need to do is just SSH-R80 to port localhost 3000 and servio.net so it's going to tell you that it is serving my traffic from this URL oh it's not working oh I didn't start my node server oh yeah yeah I know I could servio start Enggrok because I know quite a number of laptops were having high mark issues so for your API test cases or basic anything in the if you're having high mark issues or let's say initialization command you can do before each this time out so the default is 2 seconds you can change it in 10 seconds this method can be applied for any other API or add on at your own use cases if something is supposed to take 20 seconds or longer than expected you can increase the default time out because the examples that you're given does not take this into account on our own hardware any if needed okay so in our application it's loaded in this public URL modus.servio.net and to test this application let's just test the search application you can go to snippet.yrrelations.com or you can just go to yrrelations.com and click on create a test and running a test on yrrelations.com and it's a lot like the import pen there's a tutorial over here you can use so what we're going to do is clear this so the first step we can do is just to go to our URL and just make sure that it's loaded and next thing you want to do is say fill in the name of the pokemon that we want to search so we can say eye.fill name and let's look for meal2 and eye.click if you want to go to you want to click on the search just to execute the search itself it's taking a bit of time to load up the server and when you're done searching it we want to see eye.c just to do an assertion that the number of results found is so if you look at when you go to the pokedex and you say meal2 oh there's no pokemon called meal2 okay it's a space actually without the space meal2 without the space so it's loaded the application so they really have to think about okay i want to set up my chrome and what we want to do is make sure that we actually see meal2 as the pokemon itself and maybe we just want to assert that pokemon that we see is a psychic pokemon or you can just say assert that the HP is 160% so let's say HP 106 so you can go and run that and what it's going to do behind the scenes is it's going to call infrastructure which is managed by my CTO which is Eugene i call him Eugene as a service because he abstracts infrastructure for me so Eugene as a service which is bad ass so it would actually set up the test in our back end and start the chrome the chrome in docker or if in the case of IV or AH or safari it's going to start a VM that's why sometimes it takes a while to start up browser not actually the browser is start up but it's taking a bit of time to load the application itself because there are 702 pokemon itself so what URIlicious does is that it actually waits for an application to be fully loaded before it starts running the next steps and some interesting bits about URIlicious is that you don't need to figure out the ID of the name is you don't need to figure out what is the the ID of the search button is you just need to say okay i click on search and okay i click on name it goes to mil2 so what URIlicious does is it's going to look for i.fue name it's going to look for the occurrence of name on your DOM HTML and DOM element and it finds name is just going to search around it within the DOM tree or it's going to do a search around in the DOM tree the elements that occur visually around the name text itself and it finds a text info field is just going to make an intelligent guess that okay that name field is probably related to be able to run test on URIlicious in fact you can write pretty crappy code and URIlicious can try to make its best guess on what you mean when you say or fill in the search name field and it will be very simple to write test because you don't need to think about what your CSS is so even if someone change the CSS for your search button or they change the CSS for your name field there's no the test wouldn't break and another thing about the behavior so this is a server-side application URIlicious is actually very good at handling asynchronous components so it works with any framework that for example if you are using Angular React in fact we use URIlicious to test URIlicious itself which is still on view so some metal layers of testing we use URIlicious to test URIlicious other websites so there's like 3 layers of testing yeah so it will still work if you have an asynchronous component it will automatically wait for the component to be loaded for up to 15 seconds so you can actually configure the timeout so if you are working on blockchain for example and for some reason you need the test to wait 10 minutes for the process to be completed you can just say command.set command timeout to be equals to 15 you can cover a lot of commands over here you can say you test drag and draw you can test status code as well filling in the field scrolling, clicking, accepting alerts so it's pretty easy so if you want to change the timeout you can say okay timeout is 15 seconds okay so it's pretty simple to set up a test on URIlicious but of course we want to figure out how to do this on our own as an exercise so what we can do if you want to DIY this you need to set up selenium and you need to install a web driver library itself so for browser automation there is a standard called the web driver protocol and it's a standard that is specified by the WC3 community that specifies how the browser should implement the drivers for test automation so you can think of this as printers and your selenium library as the printer dialog so your selenium library just give you a common interface for you to write the commands and you interface with the chrome driver and for firefrogs there is a gecko driver and a marionet driver and for safari there is safari driver i.e. there is i.e driver but sometimes they don't follow the specs so it's up to you to discover if the browsers don't follow the specs like sometimes when they opened up the select menu safari were just free so sometimes you need to figure that out on your own if you want to use selenium on your own but let's try that anyway if you want to so let's move on to exercise 3.2 and try setting up selenium on your own the fastest way to set up selenium on your computer is to use selenium stand alone which knows where are all the URLs to download your selenium drivers from so we can go ahead and say NPM install selenium stand alone the new browser just a quick word because this command is not exactly 100% stable so if any of you have any selenium setup issues i will try to go on to you because it's not exactly made for production so if anyone don't know how to configure selenium for production for environment x i can speak to you separately because the setup steps for id 11 it's completely different from age it's completely different from crawl so we actually covered that it's different setting up selenium it's different for mac so it gets a bit complicated so once you have done your NPM install selenium stand alone you can do selenium stand alone install so selenium stand alone install it's gonna install some default drivers it's gonna install your selenium driver selenium server it's gonna install your chrome driver and it's gonna install your firefox drivers and right now it's just taking the latest of each of the drivers and then next thing what we want to do is to install a whole bunch of things that we want from web driver IO so web driver IO is an implementation of it's a library that interfaces with the web driver protocol so it's gonna instruct all the different it's gonna set up the browsers for you and it's gonna shut it down for you and it's gonna send the commands to the browsers so you can take a look at the API at your leisure but we're just gonna do something simple like search for pokemon again so install the bunch of stuff over here so you're gonna use mocha framework as well and then the step 2 is copy over the wio config from sample.js or you can just rename it from sample.js to wdio.config so you can just rename this so let me just run through what we have set up over here so over here we have we are gonna run web driver a local instance of web driver IO and it's gonna point to the test that we have defined in part 3 test and over here we have defined maximum instance of 10 and our capabilities on this machine that we have should be 1 instance of firefox and 1 instance of chrome and we are just gonna log out all info if you find it very noisy you can just set it to error so you just at least know when salient fails it's gonna connect to salient stand alone and we're gonna use mocha as well so that it's more consistent and that's pretty much and also we need to so we're actually not gonna use mocha as the test run so we're gonna use wdio as the test run itself so wdio you need to tell it to import char again so in the before statement you need to do the same thing at the top import char global.expect char equals to expect and also you can do char.shoot which would extend the object of prototype with these shoot language chains okay so then the last part what we're gonna do is we're gonna do start writing our search pokemon test so this is gonna be a little bit we're gonna set up define our scripts again just describe our end-to-end test describe our so we're just put in the test again it should search for u2 and actually all browser test they are asynchronous but if you use wdio as the runner instead of web driver so web driver runs in 2 modes it can actually run in synchronous mode so we're gonna get wdio to run in synchronous mode i can't remember if there's a flag over here but it will run in synchronous mode so we don't have to think about your weights again and what it does to you is the browser object itself so we can take a look at the api so if you want the most basic thing we should do is just to go to url so the simplest command is just browser.url url itself so we're just gonna grab that and let's just go to localhost3000 and we can just grab the title of the browser just to try maybe browser.get title and what we can do is expect again title to be pukit x so if you want to run the test because i've set up the end to end test to run with a different test runner instead of running with mocha by itself it will run with wdio we actually need to set up a different script for testing so you need to run the test colon e2e so run test colon e2e so let's go back here so i should kind of expect so it's running in Firefox and Chrome and over so if you're running test on localhost the trouble is that you cannot touch your machine when it's running its test because it's going to interfere with the test itself but what you have seen previously is it just starts the browser and if Firefox browser in parallel and starts executing the command and you can see it's very fast as well it will just open up the browser, get the title, close it so sometimes you might not be able to see what's happening and on top of that the screenshots are another set of commands itself but you have to DIY the screenshots if you want to do that so i think i have some trouble with this, expect i'm doing something wrong ah it's not to be to be equal pokedex, so i run that again so we have to test passing, we are just going to go to the url and expect the title to be pokedex so that's a little bit boring, we want to do a little bit more stuff so let's do something like fill in the so browser so to fill in what you need to do is to send the value you need to use the send set value set value command itself so you need to select the element that you want to interact with and then set the value itself so to select the so if you are using web driver or most libraries, they will expect you to provide a css selector or expel selector so over here in our application the pokemon the pokemon name fill is actually has an id of pokemon dash search dash form dash name dash input and i'm going to say okay grab this id and dot set value to be mu2 and the next thing we have to do is to say okay we need to click on that button we need to click on the search button which is this button with this particular id pokemon dash search dash form dash submit dash btn and the command to click on it is click so after you select it you click on it click and then what we're going to do is the next steps will be actually get the to check the pokemon card itself to see whether it has the text mu2 so pokemon okay let's just take a look at this okay we're just going to be a little bit lazy here and just test for the pokemon count itself so the pokemon count is inside a class a bowl element with the class pokemon count so we're just going to get pokemon count and get text so get text is going to get the value of pokemon to so count and we're just going to say expect count to be equal 1 so 1 is in text because when you get text it's not going to be a number unless you do parse text and then we're going to run this again in chrome and firebox so it's super fast maybe you guys have missed it when it actually access when it's completed completed a search so i'm going to run this again but you can see that it's parsing so it got grab the text grab the count and assert that it's equals to 1 so you get eyeball this for a moment it's going to film mu2 click on search grab text and close it so it's super fast so this doesn't give you screenshot so if you want to make sure that everything passes you either look at the console if something goes wrong you need to run the test again and eyeball it until it's done so that's how you set the end-to-end test on your own and if you want to have more questions about setting up the salam server on edge, on safari, on IE you can talk to Eugene Eugene if you ever want to test other browsers okay so that's basically the end of our workshop for end-to-end testing i'm actually going to get our guest Jill so Aplitus is a visual regression testing tool i will let Jill introduce visual regression to you okay yeah yeah so what should you consider between a different framework you should first of all look at the browser support so one of the very popular ones you will hear of and in fact i think Jill will show you is Cypress so Cypress supports only Chrome so if you want to test your browser you can use Cypress and then Cypress actually doesn't use the web driver protocol it uses the chrome dev to protocol which is why it is lightning fast so if you want performance and you don't care about testing other browsers besides Chrome then Cypress might be a suitable tool the thing about most other testing tools compared to UILicious is that iD or add a class or every single one of the elements that you want to test so if you want to test the search button you can't just say you can't just say add a click search because it doesn't really work you actually need to explicitly say select the button with the iD search form submit-button i think it's really up to you to check each and every one of the frameworks to see whether you're comfortable with it the other one is another difference is some tools actually like Nightmare.js if I remember they want you to add a async await for every single one of the commands so maybe you don't like async await that much so there's very small differences between the style of writing your test okay terima kasih maaf pindah di ufas oh jadi i'm not going to talk about ease modules now i'm going to talk about my share of its subject with this testing i come from aptly tools i have about 20 minutes before i rush to the airport and go back home the other home so i want to really do an explanation of what visual testing is about and then do a quick demo of how we do it at aptly tools so first of all what is visual testing webdriver.io which you're going to use in a second and Cypress and Selenium WebDriver and lots of others do functional testing what does that mean you click on a button you check that the button does what it's supposed to do right click on add to cart you check that the item was added to cart you click on this you check that so you're basically clicking on stuff or typing stuff and then checking lots of elements on the page to ensure that the functionality works correctly but as somebody tweeted about a month ago look my CSS didn't load the page looked like shit yet all my functional test passed which is true your tests you've tested your unit code your business logic you've tested your API logic and your integration with a database you've tested the functionality of your front-end code what about so you've tested all your code except two parts the HTML and most importantly the CSS none of the functional tests test the CSS none of the functional tests test how your application looks like and that is as important well not as important but almost as important as functional testing and in these days of responsive design you're mostly web developers i'm guessing whose application is responsive responsive as in supports multiple widths right an increasing number and it's going to grow more and more now i've seen a lot of developers change the CSS and do this with the browser and then change the CSS and then do this with the browser but are you really checking or are you just yeah looks okay we're not really checking we're definitely not checking all the minor variations and i was talking here at JS Conf Asia to a designer and he says yeah come on some guy changed the CSS and the button moved three pixels and i notice it because i'm a designer and i go to the developer and the developer says come on what do you care about three pixels developers we don't see that okay we do not see that and we need to see that and if we do it manually again and again and again we won't see that we will get tired which is what visual testing is all about so visual testing is all about looking at the visual aspects of your application now it's not easy it's not easy doing that i have a talk i did a talk at JS Conf talked about the four elephants in the room there are four main problems in CSS first of all how does wait i'm jumping ahead i have totally this is the beauty of a conference you know she came to me and said i have a testing workshop why don't you do a demo so i came totally unprepared i will do a demo but sometimes i'm going to jump like crazy so how do we do visual testing a lot of people come to me to the booth and they think that we look at a screenshot we look at the page and say yeah this looks good we don't do that other people think that we feed a design system into our application like the margins should be this the fonts should be this etc and then we check the page for correctness we don't do that either it's basically impossible because the rules are so huge that you're basically rewriting the CSS again what we do is what we call visual regression testing we change that what was still is we're testing that nothing changed between the last time and the next time and the next guest will also be talking about snapshot testing which is not visual and which basically checks that the HTML itself the HTML elements, the divs and the spans that doesn't change from run to run we're doing the same but we're doing it visually so running a test in visual is very similar to WebDriver.io the test you click-click-click using browser automation in the test you say navigate to this page and then click on this and then click on that you take a screenshot the first time the test runs that screenshot is the baseline this is what should be you look at it manually you let the designer look at it manually they all say yeah we're okay and then the next time the test runs we compare the screenshots and the test passes if they're not the same two things can happen either it's a bug which is what usually happens yay it's a bug we found a bug, we're good we fixed the CSS, we're done or well it's a feature if it's not a bug it's a feature it's a feature we added things, we changed the styling according to the design so we need to approve it and that is how visual testing works click-click-click using browser automation screenshot, click-click-click screenshot, we do lots of screenshots on all the states of the application or specific to components we can do also component testing and then compare the screenshots to the previous screenshots if there's a problem we alert and you can tell us whether it's a bug or a feature that is basically but what's the problem there are many OSS tools that do that first of all if you're using WebDriver.io behind the scenes you're using Selanium Selanium for reasons I cannot understand chose not to do full page screenshots so every time you take a screenshot you're using Selanium you're taking only the viewport, the window so if you want to do a full page screenshot you need to do the scrolling stuff and it's really really complicated so taking a screenshot using Selanium is very difficult, all the other tools really easy that's the one elephant it's not a big elephant but it's still an elephant the other one is the comparison comparing a Mac version from a Windows version is basically impossible comparing Chrome 74 to 73 is difficult comparing Chrome 74 to Chrome 74, same machine different GPUs doesn't work and why? because each one of them renders stuff a little bit differently there are anti aliasing stuff the way you render JPEGs all kinds of weird things and you start getting false positives you start getting false positives and you start moving the slider zero error rate which is false positives or I accept 5% error rate or 10% error rate and you keep moving that slider to the right and what do you start getting? false negatives or false positives that's the second problem what Aplitulz does is we have a team of four algorithms people that all they do is deal with visual algorithms that do diffing it's complicated but we've basically solved that problem of visual diffing between screenshots the third is managing those screenshots if you're doing a lot of screenshots and you have 50 and you're changing the header now you need to check that all the header changes and all the screenshots are exactly the same okay you have to go through each one of those screenshots and manage that and accept this and reject that and do all kinds of stuff so managing those screenshots is a problem the fourth one I think is the most problematic you want to run the test on Chrome but you want to check it on Chrome on Firefox on ipad width you have css breakpoints you want to check them on each one of those breakpoints how do you do that and keep your tests running in not running hours but running minutes how do you do that that's for me the biggest problem so let's see a test let's see how we solve those problems and then I run to the report okay so this is the web driver IO test okay should I make it bigger yep there we go now I'm not going to run it because we still don't support web driver IO5 appletools and this is web driver IO5 so I'm going to show you the code but I'm going to run it under Cypress but it's the same thing so what we do let's ignore the eyes thing and this is the visual testing tool eyes you get the metaphor it's actually really cute I like it browser.url navigates to that URL and then we click on the check box called dragon I want to filter and show only the dragon pokemons I don't understand pokemon so I may be wrong here but I need to catch them all right and then I click on the form submit button okay I click on it so that it submits the shirts it leaves me with only the dragon pokemons and then I take a screenshot I take a screenshot and compare it to the previous to the baseline screenshot then I click on a specific card click on the card and take another screenshot this is basically what I do I also initialize eyes and I do an open session and that's not very interesting in Cypress it's exactly the same but differently wait I want to wait there we go it's exactly the same but differently instead of dollar you get side.get click click but it's the same test so let me run this is running Cypress so by the way if you install Cypress if you want to add eyes functionality just npm install eyes and then you have the new command so but all tools are exactly the same if it's eyes, if it's other commercial tools if it's open source tools they all do the same this is Cypress it's a really cool tool and we're running notice that the test is finished running but we're still running because in the background we're running all the screenshots and making sure that everything's okay it should take about 20 seconds 30 seconds 20 seconds okay now what do I want to check that this passed but I can look at the screenshots and this is Pokemon and I have the three screenshots the two screenshots and this is the second screenshot okay we're taking full page in this case Chrome 74 1024x768 perfect, I've seen the screenshots now we talked about the whole responsive with stuff so let's do something else we've tested under Chrome 1024x768 let's add some more chromes like 800x600 1900x1800 let's do some firefox stuff and IE okay so now we have oh let's do a chrome emulation of iPhone X and iPad okay and run the test Cypress is very annoying and that I save it and it immediately starts running the test because it's really fast it is really fast so I'm running it two screenshots I have about 40 to 30 screenshots for all the responsive widths and all the different browsers okay it should take roughly the same amount of time it's still 25 seconds let's look at um the apti tools eyes stuff and there we go the pokemon you can see it running on all these browsers the same amount of time now as you can see here we have this is a bit too big i11 1280x1024 let's look at smaller one you can see that the responsive design works here we have three columns and here we have four columns okay so we're basically testing responsive design using this application but all the screenshots all the renderings not the test the test is running on this machine once but all the screenshots and all the renderings are running on what we call the visual grid so that it can can run the test we do not run the test themselves that's for UILicious that is for browser stack etc if you want to do cross browser functional tests don't come to us okay um okay the thing let's do a bug let's add a bug um a visual bug let's change the css oh look i'm exactly what i want instead the color the submit button the search button instead of this i'll do purple whatever and save and rerun the test it should take again roughly the same amount of seconds running through all those browsers all those responsive width and let's go to eyes running there we go we found diffs let's look at them they're all in the same place we can do the cool demo thing okay but if we look at it it's exactly that problem i'll remove this you can see the baseline you can see the difference between now notice um oh wait not demo it's a really really okay now what caused this bug some css or html change but what we can do sorry is click here or not sorry let's start click here what we will see is not just a visual diff but a css and html diff we're seeing the bug because what we do because we're running all the tests in the background we're getting all the html and css to show the screenshots we can diff it we just this is the bug this specific visual diff if we had different diffs each click would show you the different diff that caused this bug no idea how this works that's why we have a 4 people algorithm team to do this kind of magic but it is magic and it will work the last thing is don't forget we need to approve or disprove it or reject the change we can do it one by one or we can group all the changes and let appletools tell us hey this is all the changes it's just the same change just approve or reject it once as you can see it's not infallible it did it into 3 groups because it's not you know it's still only 4 people algorithm team and not a 10 people algorithm team but it will get better and 3 is much better than like 30 so we're good here we can accept or reject the change and then continue on so this is the basics of visual testing write a test using web driver IO whatever tool you have add using whatever tool OSS or open source commercial add those checks to check the screenshot it will check against the baseline and then if there are diffs and reject the changes this is the base of visual testing i think it's one of the important tools in your tool to set as testing and thank you very much yes right now so i try to keep things very very shortly yesterday we were talking about testing she discover what it was and ask me to do a little introduction of snapshot test because it's not included in the it was not included in the component testing snapshot testing but i couldn't figure it out how to set it up for park and i thought you needed to use react to set it up so i gave up until it came along i will explain this now so just a little question who here has ever used just before oh very few people okay basically just is a test framework which is written in facebook a lot of people that use react just to test their UI code i'm here to talk about the snapshot test feature we implemented 3 years ago now in just and despite being implemented in just there are other framework that took the code from just because it's all release and all is monorepo so a lot of part can be reused and i think ava has implemented so if you use ava you may be able to use it i'm not sure about the other mocha but i will try to explain how we work in zest because that's what i know better so why the snapshot test first we wanted to test ui because that's what all ui developer want to do right the problem we do that is that the only solution that kind of work is end to end testing end to end testing as some issue because in order to do like basic end to end test you need to first open a browser wait for the browser to load navigate to the page wait for the page to load done to be ready select some element usually like a text or a button do some interaction with the button wait for animation to finish or some api to be called and then if everything didn't break do a screenshot of that and then run this test over and over to see the difference like we see before in the previous talk now this is also very slow because all these things needs to happen in order to have the screenshot if for running one test it takes 30 seconds running thousand of tests will take a lot of time and developer usually don't want to wait that much in order to ship their code so we thought what if we think what we want really to test usually is a function of your input and it generates the same output and in react there is the virtual DOM concept so all the UI is a tree but this doesn't really apply only to react in VJS for example is the same or even if you use anything like in the example of today is only server-side render but at the end of the day when you call the index page it will generate the same HTML so if you can take that tree or that output of our function and somehow serialize it and store it we can compare on the next run and since we can do that without connecting to a browser we just need to check that code works once by visually looking at that and then accepting our output and when we run the second time if we find anything is wrong it will tell us before even we run on the browser because it can compare with the previous output and just is able through snapshot test to catch all these things now imagine if we have multiple developers working on different teams and they share a common UI component library for example and everyone is happy and is using a button but somehow someone in a different department decide that the normal button doesn't work anymore they want that to be purple and with rainbow on the bottom so we change the UI component because they want that it works for them and it's perfect for them but they don't know that a department in a different place is using the same component and when they run their test everything works because they run their test but of course after deploying the other department say what's happening here everything is broken why is my button now like this now if you have a very small test for each component each base component you can avoid this because when the department change the button he runs all the test and he runs all the test in the UI components library and he will be able to catch that another part is using that and is maybe not the case to change everything and can revert that otherwise if you say do you like that button you can just talk to them and say oh yes we like that as well you can just proceed so this is why we build the snapshot and snapshot is not just for UI you can apply that to everything everything is a function you can run that function you have an output you can run through a serializer an example of this is i don't know if anyone here has used pretier do you know pretier pretier use snapshot for the test case pretier is a linter that automatically change your code to apply some rules rewrite that so everyone is using the same rules and there is no more comment you forgot the space here you forgot and it should be there instead of there in order to do that we run a lot of case they write some javascript they feed the javascript to pretier and then they generate the output and by using snapshot test they can compare all the input and output and when they change they can see regression immediately without even even have to run against all the code base so i have prepared a very little example of this hopefully it will work this is not perfect because i hacked that together in a few hours so okay i don't think that it will work yeah i think this is so basically i took the example that everyone is was looking at today and i create test for jest solution but basically rewrite the test using jest and the only difference is that 2b is like 2b capitalized instead of 2.b there is basically just use expect you can use expect in other framework as well and so the way you write the expectation slightly different and i wrote just the first two and then i rewrote the end-to-end test and i try to make this is overly complicated because you don't need to do this of course but in order to show up what you can do with jest just allow to mock so in this case here i mock express router so when we register the route it will save the route and then we can call the route directly on the unit test and being a unit test it doesn't have to spawn a browser it doesn't have to wait it just call it usually you don't do this but in this case i just want to show to show that it's possible to in any different occasion you might have different configuration different library like view it all works differently but in this case there's no react there's no javascript in the framework it's just server-side render so what i did here was just to show that we render the application this application is Pag.js which is a template library so it just render through Pag and then just for fun i load that to Cheerio which is kind of jQuery for Node.js in order to show that the title is Pag.dx just to show that before showing the snapshot i want to show what usually we do just search for something and look that is correct search for something else and look at this correct so this is using what the server-side returns and at the end they just snapshot everything so when i run this it generates a folder called snapshots and it saves the snapshot here sorry and basically this is the output of the snapshot and it's human-readable because i parsed this through js-beautifier so since it's HTML it just pretifies the HTML so everyone can just check this if you have a in GitHub you will see that like very sorry let me change it here HTML for example you will see like this for example and then it's very easy to compare what is your expectation of and if your expectation is correct then you can proceed and just usually it's very fast but here i'm running under Bash on Windows which makes everything slower because of the way Bash on Windows 1 works from Bash on Windows 2 which will be released soon by Microsoft it will make this like order of magnitude faster because all the file system API ran out pass through a security level so each time you open a file it's very very slow but still it takes like 8 seconds for running this and to end test if i now change the test so in this test i had to mock the process and to be production because the database is only available for production in this machine if i now change the test like this and rerun i can show you maybe it can zoom or maybe not so now it's running the same test again but this time it should not be able to find the database and oh in here actually here it is failing on the first expectation because there is no Pikachu anymore sorry so i will just show the snapshot because otherwise it doesn't run i have to fill this time because waiting 10 seconds run all the test is very boring ok so now here we have the visual diff of what's happening so we can see that the previous snapshot at all this data but now there is nothing here because these are all removed and this is all the add and we can see here there is zero pokemon instead of finding Pikachu because right now it's not connecting to the database and immediately i know that there is something wrong here and i can see what is wrong here if instead let me check let me change this back so it connects to the database again and search for charizard i never run this test i don't know if it works and also right now i'm running i suggest all the time manually but you can run in watch mode so as soon as you save you will run the test and show immediately and it's very fast so i suggest to try that and now here we can see that the difference is still not finding the pokemon but anyway the difference i think it's not written correctly but it shows all the difference between previously and currently so my point is that just gives you this ability to do snapshot test i just want you to know that it's possible to use this also in another framework there are some catches for example if you have something you render something with the current time for example that wouldn't work normally because if you snapshot now it will only work now and not like in a second you can mock that just as very good mocking support so it's very easy to mock dates to return always the same date sometimes this might be a bit too noisy in that case you can write different serializer to remove the part that change but you don't really care if it's changing or not but overall it's a good solution and i'm using this right now i'm working in Rakuten and we use this a lot we also basically a lot of UI developer have some UI component library and they use something like style guide or something similar to that and basically when you do that you have this website where it shows your component with different variants for example if you have a button with the icon or without the icon you can just see that you spawn up this website and see with storybook or style guide you can see the component in all the variants and since you already instruct how to render that component you can run just snapshot and that was what we do therefore i think both for style guide and for the other there are plugins for automatically run just and run just snapshot so you know that when you finish with your component and you run the test you update the snapshot you know that it should be correct because if you have some HTML and if you have style in the HTML as well it will be easier to see regressions and basically there are this automation already available so please try it if you didn't try it before it's not just for react you can use it for view you can use it for angular thank you the last thing we want to do old spectrum of testing which is quite comprehensive so we have functional testing which is your code in javascript you could have functional testing for your application for whatever language it is then from that case java next layer is api testing so in this case api testing it tends to be more unified so you could there are other tools to sound like postman itself for what you all use you could technically use that to api test even let's say a java application because at the end of the day an api is a HTTP server so it doesn't matter what's your testing code or development code you could actually have it separately after that it's the component testing so this is where you're taking a snapshot of the output and then you're comparing it historically after that it's end to end testing so things like ui-licias or web driver and if it's not on so things like ui-licias and web driver will help let you know that your application is not working functional integration testing but one thing that I joke about for example you can have white tags and ui-licias will say everything is okay because the button worked on the flip side tools like api2 will let you know that something changed so perhaps do something or you can have all these tools and however one thing that I see increasingly a problem especially in Singapore is the very habit of or I set this up I write this test I run it yeah it's great 6 months on the road 6 months ago so one of the things where you run your test is equally important that you run it and in particular when you're talking about test that includes integration things like stripe and all that you should be running it regularly be it daily, weekly, monthly whatever schedule it is best is always with together with your commits and build but however different teams got different practises so very quick run-through on CI CD pack lines is that here have Jenkins or GitLab see 1, 2, 3, 4, 5, 6 so yeah how many use Travis CI oh okay 1, 2 so so I'm not going to go to so there are multiple CI CD2 Jenkins is pretty much the older grandfather one it's the open source one you can install it anywhere you want if GitLab is the newer thing right now but as version control plus CI plus CD plus Kubernetes control plus a long list of other things and Travis CI is the popular open source one for the Git Hub project so you can actually integrate into any of your Git Hub project and you have your free CI CD2 and what is most common so I'm going to use Travis CI as an example what is most common is that in your repository how they work is that you integrate to your repository and you have Travis.eml for GitLab is GitLab.eml and for Jenkins and Jenkins.eml so what you can do inside there is actually that very same bare script commands that you have been running to run your test first if you need to install dependencies you could set up the script to install the dependencies so you can do installation steps you can do this by separating out so your system will know to actually catch these installation steps finally you can do the execution so this could be your npm run or even in the case of your malicious you could use it to trigger our CI2 to actually run all those steps all those complex processes like for example running nggrob and then getting a URL and then testing it can also be automated through the CI process and once you have that you can always integrate it with Slack and it should notify you in case anything go wrong unfortunately so unfortunately because what we realize was that we launch our product previously a lot of people came to us you need CI, you need CI, you need CI CD and then when we launch it we realize only 3 people using the CI2 then when we went around asking most of them say ya we said that we wanted it to work with Jenkins but we haven't had our Jenkins server yet so if you really don't have that at the very basic simple one you could actually have set up on our platform for your malicious sign up a login flow and you can set up monitoring so monitoring is where you are able to schedule any job that you previously saw that you return select the browsers that you want to run it on and set it to run it at a certain interval and to notify you by email by webhook which can be used for Slack for example and you can schedule it to let's say run every night 2am which seems to be a rare common thing regardless of what country you are at and there onwards so for example in this case the Netflix laptop one so this is actually an actual Netflix test that we run continuously and surprisingly even Netflix sometimes fail so like if you took at 5th of June no this is also like when it went through somehow I'm getting a spaniel in Singapore I don't know why but these things actually happen and sometimes test is not just about running once it's about running it again and again and again on your dev environment until touch maybe because you created too many users just today the talk we had your index ran out of numbers run it continuously until your site breaks and you fix it and yep that's pretty much out of time so yeah please continuously test whatever testing tool you do keep testing yes we have a CLI 2 chain which you can call through the CLI CD so I mean you can call it through back that's how we integrate CLI CD we plan to have better direct integration but that's a future plan or now we have a CLI 2 any other questions?