 Boleh saya mulakan? Boleh kita mulakan? Masih seperti beberapa orang, masih belum di sini. Boleh kita tunggu? Ya, kita akan mulakan. Kita akan mulakan. Baiklah. Jadi, selamat datang ke tempat saya sekarang. Jadi hari ini saya akan bercakap tentang Testing di PHP. Saya akan menyebabkan banyak perkara yang berbeda. Tapi sebelum saya teruskan, saya akan berkata ini adalah kali pertama saya melakukan sesuatu seperti ini. Jadi, jika saya membuat kesilapan di mana-mana, saya minta maaf. Jika ia terlalu susah, saya minta maaf. Saya minta maaf untuk apa-apa pun. Jadi, pertama tentang diri saya. Nama saya Hanif Normand. Saya seorang penerbangan senior software pada 2.359 media. Sebenarnya, mempunyai banyak aplikasi mobil. Kadang-kadang, aplikasi web. Terutamanya aplikasi mobil. Sebenarnya, saya belum bekerja di PHP dalam sepanjang tahun sekarang. Semua-satunya di node.js sekarang di syarikat kita. Tapi saya mempunyai projek PHP menjaga. Jadi, itu pendapat saya. Jadi, mari kita bercakap tentang test. Saya rasa salah satu perkara yang penting yang saya dengar daripada penerbangan yang belum bermula test atau mempunyai sesuatu protokol test adalah bahawa mereka berkata bahawa mereka tidak mempunyai masa untuk test. Mereka lebih suka bekerja dengan lebih banyak kemampuan. Mereka lebih suka bekerja dengan kemampuan atau bekerja dengan kemampuan, masalah dan sebagainya. Mereka lebih suka bekerja. Tapi perkara yang penting adalah terutamanya perkara yang mereka bercakap tentang bekerja dengan siapa yang telah dipercayai jika mereka mempunyai test. Sebuah pelajaran yang telah dibuat beberapa tahun lalu oleh Microsoft dan IBM berkata bahawa memperkenalkan protokol test memperkenalkan masa yang telah diperkenalkan daripada 14%-35% Jadi masa yang telah diperkenalkan memperkenalkan daripada 14%-35% tetapi kemampuan diperkenalkan daripada 40%-90% Jadi jika anda semua boleh berfikir tentang itu bagaimana masa yang telah diperkenalkan kemampuan yang telah diperkenalkan setelah anda menerima kode. Mereka hanya memperkenalkan bahawa 40%-90% kemampuan yang telah diperkenalkan kerana anda memperkenalkan 35% masa yang telah diperkenalkan Jadi saya tidak tahu tentang anda semua tetapi untuk saya dan pengalaman saya itu sebenarnya dalam perjalanan-perjalanan yang lama adalah kemampuan positif semasa saya akhirnya menerima masa dari memperkenalkan terlalu banyak atau lebih dari memperkenalkan terlalu banyak Jadi mari kita mempunyai beberapa perkara dulu Apabila saya mengatakan menggunakan perkenalkan apa yang saya betul-betul berkata Pertama, saya bercakap tentang perkenalkan otomater Saya tidak bercakap tentang kawasan QA anda akan melihat perjalanan, kemudian menerima kemampuan yang telah diperkenalkan untuk kemampuan rendam Jadi ini perlu diperkenalkan dan otomater adalah baik kerana anda memperkenalkan kemampuan kemampuan, kemampuan, kemampuan dan sebagainya ia boleh diperkenalkan kemampuan yang sama lagi dan lagi dan lagi Jadi jika ia gagal anda tahu ia adalah sebagainya yang menyebabkan masalah, sebagainya dan jika anda tidak dapat memperkenalkan anda boleh menerima lebih banyak kemampuan lebih banyak perkenalkan perkenalkan ia akan berada dan akan diperkenalkan dan ia akan berkongsi Apa yang saya bermakna adalah perkenalkan itu akan selalu berada setelah anda menerima jika anda menerima kodin standard dengan perkenalkan dan sebagainya ia akan selalu berada Jadi itu adalah pertahanan dari pertahanan jika anda menerima sebuah buku baru anda boleh menerima sebuah buku baru ia bukan sesuatu yang anda menerima sebelumnya sebab semua perkenalkan anda sebelum itu, semua perkenalkan anda dan itu sebuah perkenalkan yang boleh diperkenalkan dari awal projek anda beberapa bulan kemudian dan ia akan mengalami dan sebaiknya jika anda menerima perkenalkan, anda akan menerima perkenalkan anda dan ia adalah perkenalkan kemampuan anda jadi perkenalkan yang baik ia membunuh buku tentu saja perkenalkan juga sangat baik jika anda menerima perkenalkan yang baik perkenalkan anda sangat baik ia mempunyai perkenalkan yang beritahu anda bagaimana perkenalkan anda dan sebagainya, ia adalah dokumen yang sangat baik untuk menunjukkan perkenalkan kemampuan anda bagaimana kemampuan ini bagaimana kemampuan ini, bagaimana anda boleh menunggu untuk melakukan apa yang sepatutnya sebagainya terutamanya dalam kemampuan yang baru seperti BDD dalam perkenalkan kemampuan anda dan sebagainya ia juga menerima perkenalkan kemampuan yang baik kemampuan yang baik yang sangat baik dan betul-betul mempunyai perkenalkan dan perkenalkan jika anda mempunyai perkenalkan kemampuan anda sebagainya anda akan lebih percaya untuk perkenalkan kemampuan anda sebab anda boleh berubah sesuatu dan berubah sesuatu lagi sebab anda tahu bahawa ia masih berlaku tidak kira apa yang anda lakukan jadi ia menambah kemampuan yang berlaku ia mengubah perubahan ia berlaku dengan mengubah jika anda mahu mengubah sesuatu sejauh-jauh anda mempunyai perkenalkan anda anda tahu ia masih berlaku anda mahu mengubah bagaimana anda mahu mengubah bagaimana bagaimana anda mahu mengubah bagaimana anda mahu mengubah jika anda melakukannya untuk perkenalkan model anda atau perkenalkan database anda anda hanya membuat perkenalkan anda dan anda boleh melihat perkenalkan yang berlaku yang dipercaya dan anda boleh mempercaya bahawa ia masih berlaku dan anda juga membuat perkenalkan yang tidak menunggu perkenalkan yang boleh digunakan tentu-tentu ini di bawah kondisi yang anda menulis perkenalkan yang baik dan anda juga mempunyai perkenalkan anda jadi ini sebenarnya digunakan banyak oleh orang jika mereka tidak memperkenalkan memperkenalkan perkenalkan anda bermakna anda mula membuat perkenalkan yang lebih baik dan anda mula memperkenalkan perkenalkan yang lebih baik dalam perkenalkan anda juga boleh memperkenalkan anda untuk membuat perkenalkan yang lebih baik sebab anda perlu memperkenalkan sesuatu anda harus memastikan ia tidak berkumpul dan itu berlaku untuk membuat perkenalkan ia berlaku untuk keperluan-keperluan semua itu mari kita bercakap tentang perkenalkan yang berlaku untuk membuat perkenalkan yang lebih kecil jadi pertama adalah perkenalkan unit yang adalah anda membuat perkenalkan kembali kembali ke kecilnya itu bermaksud untuk membuat perkenalkan dan perkenalkan kembali ia berlaku bersama jika anda mempunyai perkenalkan yang lain jika mereka berlaku dengan baik mereka masih berlaku dengan baik apabila mereka bersama dan berlaku jadi dalam perkenalkan yang lebih praktikal mungkin anda mahu mempunyai perkenalkan model anda dengan database anda jadi itu perkenalkan 2 sub-system yang berlaku bersama anda perlu pastikan itu berlaku kemudian ada perkenalkan kembali juga dikenalkan sebagai perkenalkan fungsi perkenalkan kembali ini adalah perkenalkan kembali perkenalkan anda dari perspektif penggunaan jika anda menulis perkenalkan kembali anda perlu pastikan perkenalkan kembali ia menyebabkan perkenalkan yang diberi dalam cerita penggunaan pertama, mari kita masuk ke lebih banyak detail dengan perkenalkan kembali perkenalkan perkenalkan anda banyak perkenalkan anda mungkin akan menjadi perkenalkan kembali di perkenalkan kembali anda menggunakan semua kecuali perkenalkan anda sendiri dalam perkenalkan tanpa mempunyai apa-apa jadi perkenalkan kembali ini penting kerana anda tak mahu mengenai sesuatu yang lain jika anda mengajuki cahaya A apabila anda memperkenalkan kembali B anda sepatutnya mengajuki cahaya A apabila anda memperkenalkan kembali B anda tak harus dipencang jika anda ada apa yang lain dan diperkenalkan kembali semasa kepada jenis kemungkinan itu memperkenalkan sesetengah data d由a kembali A sepatutnya anda baik tidak memperkenalkan jadi anda sepatutnya hanya melakukannya yang menunjukkan bahawa fungsi kerja itu berlainan. Ini adalah unit test yang akan menjadi salah satu cara untuk mengubahkan perhatian apabila saya katakan persistensi. Tests adalah persistensi dan ia terus. Sebenarnya, ia tetap di sana. Jadi, kebanyakan itu akan menjadi unit testing. Kerana segala-galanya segala-galanya, kadang-kadang anda mengubahkan cara yang berlainan. Jika anda mengubahkan struktur data, biasanya anda perlu mengubah segala-galanya. Tetapi, kebanyakan fungsi yang membuat sebuah kebanyakan yang membuat logik biasanya akan berlainan. Jadi, ini mengubahkan kebanyakan. Tests yang mengubahkan sebuah kebanyakan yang telah diperkenalkan sebelumnya, akan selalu di sana. Kemudian, apabila anda membuat perubahan, anda akan menyebabkan sebuah kebanyakan baru, anda tahu bahwa kebanyakan itu tidak akan berlainan lagi. Atau, tidak di kondisi yang sebenarnya berlainan. Dan, ia menghargai desain yang baik. Seperti yang saya menyebabkan sebelumnya, kerana anda mengubahkan kebanyakan, anda perlu mengubahkan kebanyakan dan fungsi anda untuk bekerja di kebanyakan atau lain-lain. Jadi, saya tidak pasti bagaimana anda akan berada sebelum selama minggu, Pak Kelbui telah mengubahkan kebanyakan pada kebanyakan kebanyakan. Jadi, dia telah membuat perubahan dengan anda. Jadi, itu sebuah kebanyakan kebanyakan kebanyakan yang membuat perubahan lebih mudah untuk membuat ini. Tetapi, ia juga bermaksud jika anda membuat perubahan pada kebanyakan kebanyakan dalam kelas anda, ia juga sebuah desain yang baik. Anda mengubahkan kebanyakan anda dari kebanyakan kebanyakan. Jadi, ia tidak mempunyai kebanyakan yang mempunyai kebanyakan kebanyakan dan meminiti kebanyakan. Anda mempunyai atau sesuatu yang lain. Jadi, jika anda memperbaiki anda boleh mengambil perubahan yang diperlukan pada kebanyakan kebanyakan. Kemudian, kita akan memperbaiki perubahan kebanyakan. Seperti yang saya katakan sebelumnya, perubahan kebanyakan adalah memperbaiki perubahan kebanyakan. Satu-satunya, dengan satu-satunya, mungkin juga sebuah fungsi yang akan menyebabkan fungsi yang berbeda dan juga menyebabkan perubahan kebanyakan. Walaupun, beberapa orang akan menyebabkan ia tidak berlaku. Banyak masa yang akan berlaku dalam kebanyakan kebanyakan dalam Javascript, ia akan menjadi perubahan kebanyakan anda. Jika anda perubahan kebanyakan anda, ia akan menjadi perubahan kebanyakan anda. Kerana perubahan bergantung pada banyak perkara, perubahan kebanyakan, perubahan kebanyakan kebanyakan, perubahan kebanyakan neighbourhood, perubahan kebanyakan dan segalanya. Jadi kemarin, perubahan kebanyakan Ancikan juga akan menjadi perubahan kebanyakan. Sebenarnya, suatu kebanyakan tersebut jika anda melakukan sesuatu macam BDD yang akan saya cakap lagi apabila anda terselamatkan kebanyakan, entah masa yang tersebut, anda akan kira-kira untuk memerlukan perubahan kebanyakan atau perubahan kebanyakan tapi perubahan kebanyakan lebih popular. Jadi, anda melihat semua layanan yang berlainan dari aplikasi anda Pada layanan pembentangan anda, layanan logik bisnes anda dan layanan data anda Ini juga adalah cara yang baik untuk memastikan bahawa kode anda berhasil dengan pakaian 3rd party Jadi, lagi, database adalah contoh yang besar Anda akan mempunyai pakaian PHP MySQL untuk memastikan bahawa ia berlainan dengan ORM Untuk memastikan pakaian 3rd party, anda akan memastikan dengan database sendiri Untuk memastikan bahawa semuanya berlainan Kemudian, kita akan bercakap tentang pembentangan mengenai pembentangan fungsi atau pembentangan pembentangan pembentangan Jadi, ia berlainan dari perasaan pembentangan pembentangan Jika pembentangan pengenangan pembentangan ini melalui periksaan ini, ia harus pergi ke pembentangan lain Jadi, itu plantaran pengenangan pembentangan Jadi, jika anda beritahu peneritangan pembentangan pembentangan Terutamanya, anda bercinta dengan pembentangan anda atau pelanggan anda Jika anda menggunakan peneritaan untuk periksaan ini, okey, yg menggunakan peneritaan Ini adalah tempat yang membuat peralatan pembentangan untuk memperkenalkan peralatan itu So there's all kinds of really cool tools you can use for this, for example like Selenium web driver where you can basically emulate a browser and then emulate a click on an element on the web page and things like that, input of forms and stuff like this. So you can automate this although on mobile it's a bit tricky. Integration of all the elements from user interface to database. And it's usually the last step, when I mean last time is before deployment, before like going live, so to speak. So now we move on to test driven development. So this is something that came out within the past decade or so, where it becomes really popular now. And you know I believe the hype, right? I think it's important to follow this, basically because I've also experienced this myself and experienced how it has helped my development process. So what is TDD? Test first software development methodology. So how many of you know what exactly this means? You write your test first, then you write your code. So technically you think about the functionality whenever you write code anyway, right? But it does change how you think about design. At first, but it takes some practice but after a while you get a hang of it. So it's basically the key thing here is the iterations. Like you can see the, wow, you can't see it. Okay, never mind. So it's basically the red part there. It says test, write test, and then test fails, test passes, refactor. Then test fails, test passes, refactor. So it's a cycle, right? You go through this short iterations of writing test, writing code, and then refactor. So you write the test first and it will fail because you haven't written the code. Then you write the code, the implementation until the test pass and then you refactor. So refactoring is basically, make it look nicer, remove like repeated code, that kind of thing. And then you write another test or you maybe expand on the test you've already written. So in terms of what I've spoken to before, requirements can also be, can be a test. So if your requirements for certain piece of software is to make sure that all input are numbers, then you can also write that as a test. So that's one of the things that most people do when they start TDD is they write the requirements as a test. So requirement A, this test here, you write it down and then you write the code. So usually sometimes you have to write smaller test than that because your code, you don't usually just write one function for one requirement. So that's supposed to be TDD, but never mind. So the three rules of TDD. So you are not allowed to write any production code if there is not a failing test warranted. Basically it means always have a test first before you write a code. So technically speaking in TDD, the only rule, the only hard rule. But I've added two more because I think it's a good idea. So the second one is you are not allowed to write more of a unit test than is strictly necessary to make it fail. That means the simplest test you can to make it fail. So for a function, when you start out when a function that doesn't exist yet, that pretty much just means calling your function and then assert whether it's true or not. It will immediately fail because it doesn't exist yet. So that's simplified. And then you are not allowed to write more production code than is strictly necessary to make the failing test pass. So again, write the most simple code you can to make that test pass. So since the original test basically just checks whether it exists or not, just writing a basic function will already make that test pass. And then you go on to the next step which is refactor. Usualy by the first step, nothing much refactor. So then you move on to make the code more workable, right? So let's let's try that out, shall we? So in short, it just has the person focusing on the outcomes that are expected when they're writing the code. Because if you write the test first, the test is, you know, the expected outcome so it's actually you're thinking about the outcome. Ya, because usually when you start on the project or start on the feature, you pretty much you have the expected outcome, right? And then you figure out what inputs you need, then that's usually when you write the functions, right? So this basically just codifies it, put it on paper, so to speak, so that you can run a quick test on it. So can anybody can everybody see this? Dap. Ya, let's switch. I actually don't use atom. I'm only using it for this presentation. Eh? Oh, your code. Oh, ya. Lora is like... Ya, okay. Okay, so let's... No, this is the wrong thing. Let's okay. Let's do this. So can everybody see, right? No? It's clear, right? Okay, so let's let's do a TDD exercise. So I have a I have a class here that I've set up. Very simple class. It's supposed to be an implementation of a set. The set data structure. If you don't know what a set is, it's basically like an array, but there's no indexes. There's no index. That means there's no sorting. Right? So we're going to do this with TDD style. We're going to build this TDD style. So on the left here, on the right, sorry. On the right, it's going to be our test that I've already set up. So I'm using code exception for the test, which I will go into a bit more later. And this is the class we need. So let's think about a set. What will be the first? What will we need for a set? What will we... What are the properties we need? What are the methods we need for a set? Pardon? Like an ISMT, right? Okay, so let's start with that. So first we write a test. So in PHP unit, which code exception is built on, it will only run test functions that begins with the word test. So that's a key thing here. So you can't just write whatever it has to start with a test. That is empty written through. So that's the test. So as you can see, it's a very long function name. But generally speaking, you want to keep your function names only as long as necessary. But in test, forget it. Be as descriptive as you can. For a test, be as descriptive as you can. I would usually for any other language other than PHP, I would actually prefer underscores between the words because it's easier to read. But it doesn't work with code exception. Code exception screws up the formatting if I do that it that way. So I'm just going to do it camel case like this. Snake case like this. So test is empty. Alright. So Nen. I'm sorry? No, there is there is a true put inside. I don't to make it generalized as a coding style of the HPW. The tool is it? Ya, it's there too. It's called PSR2. Oh, yeah. That's the that's the coding standard for like styles, right? It was like a formatting style. So like if you what he's talking about is the PSR2 2 koding standard. Jadi jika anda melihat bagaimana saya membuat kelas keklarasi dan fungsi Jadi kiri keklarasi berada di lantai baru, dan indentikannya selalu ada 4 spesies, tidak ada tab yang dipercayai Jadi ia sebenarnya adalah perkara yang cukup standard yang sebenarnya diutamakan di website PHP The Right Way jika anda melihatnya. Jadi ia sebenarnya adalah idea yang baik untuk diikuti yuk memandungkan parameter kekeluianan yang adalah banyak supaya bagaimana anda memandungkan juga yang anda 내�angkan pada perkeluaran Dari ochi kita awal-ahal adalah pemerintah untuk pembinaan bareng Kita bukan pokoknya didaguh, kita mendengar capabilities medicis untuk 춮uskan yang hanya akan membuat rejayan Motherboard Kami akan menerima test itu. Dan ia gagal. Seperti yang dipercayai. Sekarang kita boleh mempunyai fungsi itu. Jadi, ia mempunyai. Ia ada metod atau propiti? Balan? Metod itu lebih baik. Tetapi ia hanya akan menjadi bulian. Ia akan jadi betul atau salah. Ya. Baiklah. Kita akan menerima hal yang mudah. Saya akan menerima hal yang mudah... ...dia tak adalah penerima. Penerima atau penerima? Ia adalah penerima propramsi perjalanan. Tapi, itu mungkin mempunyai pertimbangan. Tapi juga boleh mempercayai. Kita boleh mempercayai metod yang betul. Dan kita akan menyebabkan hal yang mudah. Tetapi sekarang saya mahu menerima hal yang mudah. kerana ingat, hanya sebarang kode seperti yang anda perlukan untuk membuat periuk test jadi implementasi yang paling mudah sekarang adalah hanya sebuah kode jadi mari kita pergi ke publik ia dimulai dan anda tahu, kode yang paling mudah yang kita boleh membuat ia terlalu mudah ialah sebuah kode ini, kan? kemudian kita bergerak saya tidak tahu kenapa ia begitu mudah, biasanya lebih cepat daripada ini ok, tidak, ia menggunakan periuk test mengingat periuk periuk, ia hanya periuk test di sana jadi ia menggunakan periuk, kan? jadi sekarang kita bergerak jadi apa yang kita boleh bergerak? tidak banyak, ia hanya kita hanya bergerak seperti mungkin tiga kode jadi itu tidak begitu banyak untuk bergerak tapi mari kita beritahu, itu berlaku sekarang jadi apa yang akan kita perlukan untuk periuk? set kode, set data struktur apa yang perlukan yang terbelakang kerana kita? bagaimana dengan mencuba order? anda mahu mencuba elements untuk set Core jadi mari kita perlukannya jadi başkan jika lagi saya tidak boleh mengalir apa yang anda cakap saya fikir, saya fikir tuan nenema itu ada sesuatu yang ada di jalan mana yang ada? mana yang ada? saya fikir tuan nenema itu ada sesuatu yang ada di jalan Sebenarnya, itu patutnya yang kita butuhkan untuk menetapkan, kan? Jadi, menambah element ke set. Jadi, kita buat set ke set. Kemudian, kita katakan set ke satu. Kemudian, bagaimana kita beritahu bahawa ia telah ditetapkan? Mungkin kita perlukan sesuatu yang lain untuk beritahu bahawa ia telah ditetapkan. Ya, mari kita pergi dengan yang itu. Jadi, ini. Tunggu. Dan, tentu saja, saya menunggu. Ia akan gagal. Akhirnya. Tidak. Tidak, maafkan saya. Saya tak menunggu. Saya tak menunggu. Saya menunggu sekarang. Kita pergi. Ya, saya tak menunggu. Saya minta maafkan saya. Baiklah. Sekarang, kita tahu bahawa ia gagal. Jadi, mari kita menambah method. Jadi, public. Menambah. Jadi, sekarang menambah. Jadi, bagaimana kita beritahu bahawa ia telah ditetapkan? Apa yang baik untuk menetapkan bahawa ia telah ditetapkan? Baiklah. Dan array. Jadi, sebab saya tak mahu orang dapat mengawal. Saya hanya akan menetapkan sebagai pribadi. Baiklah. Jadi, ia akan menjadi array. Ini. Data. Equals. Value. Baiklah. Kemudian. Apa yang kita perlu lakukan? Ini. Baiklah. Saya menerima fungsi public. Maaf, terlalu banyak javascript. Baiklah. Javascript tak perlu menambah. Apa? Javascript tak perlu menambah. Tapi javascript juga tak perlu menambah fungsinya. Baiklah. Sekarang, ia menambah. Sekarang, menambah. Apa yang kita boleh menambah? Apa yang kita boleh tukar? Ia tautan untuk menjadi ujian. Jadi, ia tautan untuk berjumpa dengan kita. Data keluarannya ialah tautan. Isu mana? Ia tautan. Jadi, kamu mahu jilakan ikatan tahulahnya? Kita lihat data array. Siapa yang berjumpa semula? Kita berjumpa tak tautan ialah data. Bukan kata-kata? Ya, kata-kata tidak ada kata-kata ini. Untuk mengikuti kata-kata, ia sebenarnya kata-kata, tapi kata-kata ini tidak ada kata-kata. Okey, data ini tidak ada kata-kata, sebenarnya itu akan berkerja. Mari kita lakukan itu. Jangan lakukan begitu. Jadi, saya akan beritahu, bagaimana data ini tidak ada kata-kata. Ya, maaf. Itu cara yang baik. Saya minta maaf. Tidak ada kata-kata yang baik. Okey, itu satu yang baik. Ada apa lagi yang kita boleh lakukan? Atau ini baik untuk berikan fungsi sekarang? Ya, itu baik. Saya minta maaf. Tidak ada kata-kata yang baik. Ya, okey. Tidak ada kata-kata yang baik. Jadi, itu berkerja di PSP? Ya, saya tahu. Saya tak tahu apa yang berkerja di PSP. Apa yang kamu fikirkan? Atau kita bergerak? Untuk memperbaiki cara baru? Periksa kata-kata. Jadi, kata-kata yang baik. Untuk dapatkan kata-kata itu. Okey. Jadi, mari kita mulakan dengan kata-kata. Kata-kata jika tidak. Kata-kata tidak. Kata-kata jika ada kata-kata yang baik. Saya minta maaf. Kata-kata jika tidak. Kata-kata? Kata-kata. Ya, pasti. Jadi, kata-kata yang baru. Mari kita mulakan kata-kata. Kata-kata. Kata-kata. Kata-kata. Mari kita mulakan kata-kata. Dan tentu saja, baiklah. Jadi, mari kita memperbaiki kata-kata. Jadi, sekarang, bagaimana kita dapat kata-kata itu? Saya minta maaf. Kata-kata. Baiklah. Kata-kata? Ya, sebab sebenarnya, kata-kata yang paling mudah untuk membuat kata-kata ini, ini kan? Ini adalah kata-kata yang paling mudah untuk membuatnya lebih mudah. Ya. Tapi, kata-kata, kata-kata, kata-kata kata-kata. Apa yang anda fikir ini untuk? Apa yang menggantikan tentang kata-kata? Kata-kata, kata-kata, kata-kata, kata-kata, kata-kata, kata-kata, kata-kata, tapi jika kata-kata tidak di dalam kata-kata, kita mesti membuat sesuatu. Ya, saya tengok. Kata-kata, kata-kata, kata-kata, kata-kata, anda menggantikan kata-kata, anda akan meningkat dalam kata-kata. Apabila anda cuba, kata-kata, ia sudah di dalam kata-kata. Ya. Jadi, apa yang lebih... anda ingin dapatkan keadaan? Anda hanya ingin memulakan kata-kata yang anda ingin memulakan? Saya tidak tahu. Kami membuat kata-kata. Apa? Saya sudah lakukannya. Kenapa? Ini adalah contoh TDD. Apa pun. Jika anda membuat kata-kata, ia diberi. Jika anda membuat kata-kata, ia diberi. Jadi, ada sesuatu yang perlu berubah, jika ia berubah. Ada sesuatu yang perlu berubah, jika ia berubah. Jadi, kita perlukan satu cara untuk membuat itu, untuk memulakan kata-kata dan melihat kata-kata ini. Atau seperti Michael, yang lain yang Michael cakap, dalam kata-kata. Kami membuat kata-kata. Kami membuat kata-kata sekarang. Jadi, kata-kata ini adalah kata-kata yang pertama daripada kata-kata. Jadi, kata-kata itu. Jadi, sekarang masa untuk membuat kata-kata. Jadi, Michael cakap sebuah kata yang baik. Jadi, jika ia tidak berubah, jika ia tidak berubah, jika ia tidak berubah, kita tidak akan berubah. Jadi, jika ia tidak berubah, kita sudah mempunyai kata-kata. Apa? Tidak ada salah. Kita lihat. Adakah itu kata-kata untuk kejutan? Sebenarnya, sekarang kita mempunyai itu. Kamu memulakan kata-kata sebelum memasuk kata-kata. Ya, itu benar. Saya buat itu salah, bukan? Ya, tapi, ini hanya untuk contoh bagaimana kata-kata akan berfungsi. Jadi, kamu memulakan kata-kata, dan kemudian, kamu memulakan kata-kata. Jadi, ia mengambil lebih banyak masa. Ada lebih banyak kata-kata yang perlu kita memulakan dan memulakan. Tetapi, seperti yang anda lihat, saya memulakan ini. Semua salah saya terdapat lebih awal semasa saya memulakan kata-kata, kata-kata, kata-kata yang perlu kita memulakan. Jadi, semasa saya memulakan lebih banyak masa, ia lebih baik dalam langkah lama. Sebab apa yang berlaku jika saya memulakan kata-kata itu? Semua salahnya yang saya lakukan dalam keadaan saya dengan javascript, keadaan dan kemungkinan dan sebagainya. Semua berada di sana. Kemudian, saya memulakan kata-kata. Kemudian, saya perlu memulakan kata-kata yang perlu saya memulakan dan memulakan kata-kata. Kemudian, saya memulakan lagi. Saya tidak tahu apa yang saya lakukan sebelum saya memulakan kata-kata. Awal ini akan dimulakan Xadiyah. Jadi, terutamanya saya tidak memulakan sekarang saya memulakan kata-kata saya mengenai pengalaman seperti raya. Saya memang meratakan bahawa saya outsider kata-kata itu dan mau kamu tahu Stand Groove ,прatusnya, akan diri dengan SUBSCRIBE. Beri yang generator untuk memulakan kata-kata itu pada hydraulika saya. Saya memulainya untuk mebabkan So it's an assurance kind of thing also and I'm not sure whether you guys, this is a good example or not for you guys to understand that you kind of change the way you think about writing a new class and new methods when you write a test first. So like I think that somebody points out, you write the specification, you literally write a very hard specification for your functions first and then you write the test to make sure the specification pass. So like I said, I'm not entirely sure how obvious it is. If you have any... It's all outcome driven. Yes. It's all outcome driven. You have a very specific outcome in your mind. You write the test for that specific outcome. So I also need to make it a point to just say that how iterative it is. You have to keep going back and forth like that. So eventually I will say if I want to create an exist class, does exist or something like, a function in there, I will probably have to change, I will probably move out that in array check to its own thing. So because I don't want to call in array twice in the same class or something like that. So exist will be just in array and then I go to this exist. So those are iterative changes. And then you can do those iterative changes because that test is still there. So even if I change in array and then move it out to its own function called exist and then use this exist in the get function, as long as that test pass, I'm fine. So it's an iterative process as you go along, as you build up and as you refactor. So that's my brief introduction to TDD. So next I'll talk about behavior-driven development. So this is even newer than TDD. And also getting quite popular. So what exactly is BDD? Behavior-driven development, in case you weren't paying attention. Ya, behavior. So it's practically speaking, it is essentially the same as TDD. You still have that iterative process of test first, test pass, refactor, test fail, test pass, refactor, that kind of thing. So that iteration is still there. The difference is test defined by behavior instead of functionality. So instead of saying for like our earlier example that is empty returns true when just it's initiated. You write it's empty when instantiated with no value, it's empty returns true. So it's a very specific, not specific, but more like plain English kind of a description for each test. So you describe, it provides like a good template for behavior or functions and your application as a whole. Ya, and then the key part here is you usually assign a scenario to it. Like when this is this and this is this, then this should be this. So you assign a whole scenario to your test. For example, on the side here, this is what is known as story BDD. So it's a very specific way of writing specifications for your test. So this is popularized by I think Cucumber for Ruby. So this format has a name, it's called Gherkin. Ya, because Cucumber. So as you can see, this basically describes your features, then those are the rules, and then the scenario is what you are actually testing. So when you write a test, so for example, for Cucumber and I think for PHP, that's BHAT, what you'll be specifying is actually all of those, but your test will actually be described, will be establishing the scenario. So this is story BDD, but unfortunately, I can't go much into story BDD because I don't use it that much. I'm more used to the other kind of BDD which is spec BDD. So this is the scenario that I was giving to you. So in spec BDD, it isn't so... How will you describe that? Not so worthy. Not so verbose, as story BDD you have that exact format, you have to keep that format, you have to specify the rules, you have to specify the user role and things like that. But for spec BDD, it's something like this. So this could be the scenario for an integration test because just from the description, we can tell it's going to involve more than just one function. So given the user has an item in the shopping cart and that item costs $50, when the user clicks purchase, then the user should be charged $50. So all that is very integration testing. You're going to combine together a lot of different elements. But it's a very nice way to specify requirements. And if you remember earlier, I talked about how it's a good documentation. With BDD and BDD frameworks, you can write down your test like this and when you write, when the test output will also be somewhat similar format. So what's good about that is that non-technical people can also see that and know that this requirement is met like non-technical project manager so maybe your stakeholders or your clients you can run the test or they can run the test themselves and see that all these scenarios that are built up is passing and it's very easy for them to understand a scenario like this. So for another example, this is let's say for a unit test also can be done in BDD style. So for unit test is that for example the set class that I created. So given class set when instantiated with no values then property is empty should return true. So this is the spec BDD way of specifying a unit test. And again, even for somebody who's not so technical not a programmer maybe just a top level QA guy then you can see they say you can somewhat get what you're trying to do and you can really understand what you're trying to achieve. And then you can also see that I've highlighted the words there in green. So those are I would call keywords. It's not a must that you have to use this but it's a really good idea to keep to the BDD standard that has been established. I think this was established with RSpec, right? RSpec on Rails. So Rails established a lot of these things then PHP tries to catch up, I guess. So this is BDD style scenarios and testing. So TDD versus BDD not really mutually exclusive. Actually it's pretty much interchangeable for most frameworks that are available today for testing is really how you name the test functions. And then there are some frameworks that gives you a bit more leeway in how you want to describe your test. But generally speaking the main difference is really just how you specify your function names because that's the key thing here is that's how you describe it. And as I've mentioned before the main advantage for this is easier to understand even for technical people like developers if you see something that's easy to understand if say you picked up on a project that your friends or your team member did and he writes his test in BDD style it's very easy for you to just pick up on what exactly he's trying to test and what exactly should be the outcome. And thinking in behavioural terms can cover for TDD's shortcomings. This requires a bit more explanation I think. TDD's shortcoming is not really a shortcoming it's more of the person who runs the test that's the shortcoming which is the mindset of functionality versus behaviour. It's hard for me to to explain it properly in words. Basically it's when you think of behaviour you tend to be a lot more all encompassing. So it's a higher level perspective of your applications even when you do unit test it's one of the reasons why a lot of BDD test tends to start with integration test instead of like how we do unit test usually for like TDD typically BDD people usually tend to start with integration test very similar to how I show you the first scenario example where given this scenario this should be the outcome so if you look at the the diagram there on the side so we start with with BDD sorry, I choose a black colour background for some reason BDD on the left hand side is where you write the feature so that's an integration test you usually write the integration test for like a feature set like the shopping cart feature set first you write the that scenario for integration first and then as you start working on that feature you start building up on the unit test which is the TDD part but still technically BDD because you'll be using BDD style language so it's it's pretty much interchangeable there's not much work you have to put into it to go from TDD to BDD you only test on code that's not directly invoked by the feature you only test for code that's directly invoked by the feature so you go to a feature level each feature might have 6 different or 5 different scenarios you're going to say feature 5 or 6 and they all invoke this first layer top level of code whatever it calls below you don't care but you check the results so that's so that's why I say so you start with that first integration test first but I still recommend that we do the unit test first but in BDD style that's why I highly recommend that if you want to start now do BDD because writing that first integration test is really, really helpful it really eases up a lot of things because even if you're too lazy you pick up somewhere you had a very long day you had 5 meetings in the morning for some reason and then you have to sit down on your computer and then you have to finish up this feature you're probably going to be really lazy to write those new unit test but as long as you have first write that integration test you're covered because it will behave as expected no matter what you do so a lot of frameworks now will help with that like PHP spec now there is code exception also have have something called specify I think the new package specify that can help you write things like this the problem with integration test is stack order change a lot of change a lot of 470 years change a often so you have to write it Ya, I mean that's the downside of integration test right but that initial test so good practice is you start that integration test and then you as you work on it you start building up the set of unit test so that's good practice so in the end if you have to change the integration test the unit test will still pass and as long as the unit test still pass you can slowly change until the integration test pass again so that's the best case scenario but as long as you have the integration test you can be more than reasonably confident that your code will work so it's better than nothing and I think it's it's a lot easier especially for you have a work with teammates that are quite you know they don't really want to do this you keep you tell them about BDD and you're like okay right they don't really want want to do it so it's just tell them okay just do this thing first build it up and then you you can work from there then you can work on your build type because integration test you have some set up cost right because especially if you are if that feature request to a database and usually that means you have to set up the test database so you have test data in there right so there's usually bit of upfront cost for integration test so you do that first get that out of the way and then you build up and after that start building up your unit test which is much much simpler and more straight forward and BDD can run at spec level so it can run 20 times faster than your seladium integration test there's no like no ya but selenium i would i would put selenium under acceptance test ya so integration test for me is even if i just test a model that integrates to the database that's integration test right so if you want to put the front end into it with selenium and everything but that's more of a user acceptance test because selenium is this like it's like a fake browser that you can control the user it's a driver ya ya you can click you can emulate clicking on elements of your of your front end with it but that's beyond the scope of this i'm afraid actually i wanted to but my docker committed suicide so now i don't know maybe later Michael get help your what my docker committed suicide no oh iya no you're going a bit too dark there man right so now i want to talk about conception actually i've prepared like a whole example project for this but like i said my docker stop working right and i couldn't get it up in time for this presentation so i'm just going to show you some stuff i guess so if you've seen earlier that how i write how i write the test i was using conception to write my test ya sure you see that okay ya so i run i use conception it's my preferred testing framework for PHP at least but as you can see it automatically i don't know if you have use PHP right use PHP what's the test output it's just and then you have to you have to ya la so you have to specify the output type and all this so for code set by default this is the output you will give the test the test suite class and then the function name and you will switch the camel case into an actual center so that's why it's really long all the function names because code set will just turn it into like a proper centers like that we just separately roll out with spaces in between so code set is good just not because of this if it's just this then i can live with PHP unit also but the good thing about code set is it does unit testing it does integration testing and it also does acceptance testing you can get package modules for Laravel symphony Zen framework and we will work with all of those different popular frameworks and even for like the less popular ones i don't know slim it will work too just with a bit of work with the bootstrap files to make sure you unload all the required files properly and it's also really easy to set up a new test for example when I created the test for that set user IBC just went never mind right so is vendor being code set generate test unit then I give the class name which is you have to specify the class name which is the full package name so just now I set up as app utility set but I've already created this so it's going to come out of an era so let's let's test something else let's test user the user class here oh I already created that test too so you can generate test with just some lines like that so there's different types of tests so you see that I type out generate test unit so code session comes with different types of test suites so to speak so there's test which is just now we use for the test for the set testing also which is basically an extension of PHP unit so specifically for unit testing but they also have the set type which is for acceptance testing and it's it's a lot more calculated to set up but you can write really nice code let me show you it's too big right so look here this is how you would write like an acceptance test in code set once you write once you generate the test file it's basically you're going to use like how you would describe yourself as the user or rather the test itself will describe itself as a user so i equals new functional tester scenario so then what they provide is language that is quite intuitive so for example they have this one i and on page then you specify the route that you want to go to then i click which is login so what they will do is they will look for the word login and then if there is a login that is not a button you will try to click on it and nothing will happen so but the good thing is there is this click function you can specify this login as a CSS selector style so that means you can do like if it has an ID a CSS ID on it the stylesheet ID on it you can just do hash then login or the ID name of whatever then you will go to that element and then perform the click and the same thing with the fill fill function too you can also specify the fill you want with CSS selector and then so the first part is the the element you looking for and that second parameter is the value you want to fill it up with and then you click enter and then i c hello mile so it will look for the h1 element with the words hello miles in that specifically it will look for that so if it sees that then the test pass passes and then there's also a special function for example like that you can see at the bottom that is a that's a special function for symphony 2 framework where you can see you will hook into the mailer mailer class then will check whether you send the mail to it so this is an acceptance test that you can specify very specifically and you can specify also for it to run this using selenium web driver so when you run this test using with the selenium module enable you will actually see like this browser open up in the background and then you will start to traverse through automatically and it's really weird at first when you see it but it's it's really cool also because automatically you just run through all the elements of your website and run the test and then it sees it will look for for this H1 element and then you will see this so these C functions also accepts CSS selector styles for the elements that you're looking for so basically just look to make sure that this element exist and it has this tags inside it you can also specify other HTML tags inside inside this instead of it doesn't have to just be it doesn't just have to be like this spring it can be another HTML element inside that should be in there and alert like bootstrap style alert class element inside you can also specify in that way so this way you can specify a whole range of acceptance testing so if you're wondering just now why I said I don't use story VDD it's because code set has this right and it's very easy because my job also is mostly mobile so on the occasional stuff that I have to do like a web front end I'll just use a selenium base tester instead of like say story VDD because well to be honest I'm not really familiar with like cucumber and gherkin so this is why I like so then another thing that codeception has is are really good extensions alright so first up is this one is no no this is wrong sorry this is specify so this is one that I've only discovered quite recently actually just a few weeks ago and so far I have I like it can we see right so compare this to the no stop right so compare this to the earlier test that we have done before so we have test validation right then a set that model is instance or this user instead of model then you look at after that is specify username is required then function then verify specify then verify so does this look familiar right so if you don't don't see it this is basically BDD style language right so they can basically do given validation right for model the user model specify username is required so like I said the should the those green letter highlights that when and should those are good standards but it's not a must right so how I would write this is probably specify user should return username is required right so I can specify also above that as when username when user is empty then validate username is required so you can you can do this all in just this one thing here one function that test validation so that means you can test different scenarios in one function because previously previously you have to specify different test for that and it's not that it's annoying or anything like that it doesn't make logical sense when it's all testing for the same thing just different scenarios right so we specify you can do this you have one test that specifically just says validation which is to test validation and then you specify the different behaviours that you're expecting from it yeah it should no no no if this fails right if this fails the rest still will still continue for test right yeah yes yes yes yeah so that won't happen even though it will it will initially run it as like a normal PHP unit test up front here when specify it's called right you notice it's actually a callback function right yeah so even if this verify here fails right the rest would still be called because it's all as part of a callback inside this main test so it will still work as expected like any sort of like testing framework that you have so this had a mistake to to specify to verify a callback function yeah but this is just an example anyway so it's not yeah what you had a question test cases in one function right using provider i'm sorry provider providers yeah PHP unit has a provider to provide a data but that's you can do that right but there's actually you can still do that here for code section because code section is still built on PHP unit right so why i prefer to do it this way is basically because it is a it groups together more logically right so i'm testing i'm testing one one validation there and then it's just after that all this different test instead of putting it into different different functions i'll just put it into this different specify function calls because technically speaking it's still it's still you're still testing the same thing just different scenarios they're a way right pardon provider is in a way that it will just run in a simple function so let's say as an example now at test foundation there are 2 input parameter okay which is the input and aspect result and provider is just an a way of these two i mean you can la this is just an example so that is very like personal opinion way to do it right you can do it that way too i i actually would probably mix it a bit mix it a bit just because i like this format again this is my personal opinion on how to test so providers are useful right but you can still specify inside this probably i haven't tried it yet because i only discovered this quite recently but it's a very opinion related thing so you can use it i'm just pointing out that this is a very very spec style of testing that i like the thing is we can make the sensing with the HP init and provider annotation but HP init is so stable because i have during 2 last year i met many issue because version of ah ya that is actually one of my my pet so especially with Laravel especially with Laravel you have to be careful with versions when you include codeception into your projects so technically speaking if you find that one version of codeception works with one version of Laravel you have to it's it's recommended you lock that version in your composer.json file because there's there's always been this compatibility issue with codeception and Laravel because it's a new new framework the conception is ya but but so far if you don't use Laravel actually Laravel or symphony so far that i've seen this issue Zen i don't use Zen that much so i can't really comment on that i haven't encountered this issue with slim so far slim is fine but that's probably because most of my slim packages is i specify myself it's not part of default slim ya with Laravel is it the Laravel module or front end ya i usually i lock that version the version number in once i'm done because technically speaking also when i do a project i tend not to update the package it's not major version updates and when i do ya conception has been a headache in terms of that but i feel that all the being able to include acceptance test into your automated test suite is really valuable because i think main reason is just i just don't want to have to go through the click click click click click ya ya it's working right i guess i'm too lazy for that ya exactly with Jenkins you can run it automatically also i'm not sure about Travis CI but circles CI you can do it also and so ah another useful extra module for conception which i like is a aspect mock so any of you familiar with like mocking frameworks for classes mocking classes like mockery use the PHP unit mocking classes is it so the most popular is actually mockery mainly also because i think it works really well with Laravel Laravel is really popular and mocking is pretty much based on mockery anyway but they don't use mockery for some reason they should i think eh there's a different there's a different discussion for a different time so but one of the problems with a lot of the standard mocking frameworks now is you can't mock static static function calls you can't mock static classes so but aspect mock can do that and then i find this especially valuable if you're ah why i started to love this basically is because i took over an old Laravel project which had a lot of like people who misunderstand facades working on it so i end up having a lot of static classes with a lot of static functions basically classes with just static functions and that's really annoying to test so thankfully at that time i discovered aspect mock so aspect mock uses this go aop library to work so what it basically does is i'm amazed they can do they manage to make it work so fast when they do this it will go through your source code and it will wrap all your source code in like an object wrapper of its own and then when you call that function check with your specific specify ah your code for the aspect mock and if you specify a replacement or a different functionality it would replace inject that functionality into your source code when you call it at runtime and i'm still amazed how they manage to make it work so fast because i have no idea but the good thing is that you can pretty much mock static classes which is something that we've i've never been able to do before aspect mock so the keyword part here is this test double so test is basically you want to you want to use aspect mock as test which is the most useful way because you don't want to type aspect mock all the time so you create the mock double of the user model so what this does it will take the source code of the entire user model class wraps it in this object wrapper and then it sees that next argument which is table name my users so what it will do is basically it would replace in runtime it will replace all instances of the value for table name with my users at runtime so if you do like a user model table name see that's a static function call and you can still mock static function calls so now really the only thing should if they can do if we can mock private private functions they'll be like but if you can mock private functions then I think there's a bit of a security loophole there but it can be useful so this is another code exception add on I would say you can actually use it separately but it's made by the same people and it's really useful especially if you have legacy code that has a lot of a lot of calls to static methods useful useful and that's about all for my presentation so anybody have any questions no? anybody have any comments Isa my explanations are bad ah yeah but so much of the time you spent in testing in testing alright so this is I'm going to tell you it's going to be a danger zone right so if you're like me and you really you really like reading into new tag and new code like you know follow down the rabbit hole kind of thing it can get dangerous when you discover new things like this so I actually spend a lot of time just reading up on new things what I can do with what I can do with coding at first but once I figure it out and manage to do I do spend more time writing actual code than test but you have to you have to remember that the down the upside is that you also spend less time writing fixing bugs so ultimately you probably overall spend more time just generally speaking but less of that time will be on fixing bugs and in the long term especially if you're talking about like past the initial phase of a new project you you do have the certain level of confidence that your code works because of all this test and you can also have a certain level of confidence that all these previous bugs that you've discovered previously won't probably won't show up again and if they do you'll catch it immediately in your test so the key thing here that I will take away to prevent all this is automation automate your test running automate your your deployment so like for example like most of my projects nowadays I use CircleCI I'm not sure you're familiar with CircleCI so basically CircleCI will look at my repository on GitHub every commit to master or development branch it will take my code and run code run or whatever testing framework I do and it will run the test and then if the test fails I immediately get an email saying eh your test fails fix it so that's a very good idea to do it so even if you you miss out on just running the test after you complete the code before you commit your code you forgot to run the full test suite CircleCI or TravisCI will do it for you and it will immediately notify you if you want to that your test has failed if you want to go like one step further I know there are some companies out there that has like big screen 50 inch screens TV with like little things there and like it's all green and then the moment one thing goes red and somebody shout eh your test fail there's companies that does that and it's actually a really good idea if you're willing to invest the kind of money to that because you will immediately know if a test fail and you will really know to fix it so that means usually they automate deployment also and if the test fails then it won't get deployed that means it won't get out to like to your users I hope that answers your question because I can't remember it just had to yeah it is initially it will be very very hard because you have to like get into that flow of things but once you once you get used to it you will slowly build up because it's a different way of thinking and that takes effort but once you're used to it right you kind of get used to it you will you go along smoother I mean you will still take more time writing writing new features and things like that because it is extra work but the benefits in the long run is much better it's like familiarizing yourself with many new tool right it's going to take some time to prepare for the learning curve it's a slight learning curve but once you familiarize with the way of doing things the way of doing things in that learning curve as long as actually to one way is to try to reuse that learning curve is to achieve parallel and one person to write a castle person write a code production code to make up way of doing things so it reduces the mental strength any other questions so thank you thank you