00 concurrency have allocated to it it will start running you see that it start running again and everything continues as expected. So, there was a network failure in between and because of that network failure everything stopped executing but it picked up again when the network was available. So, that is how the resiliency is achieved so you can see that all of this you can see all of this invocation logs and everything where if you go to the events tab you see the validate order function you can see the invocation logs so you can see that this particular event was delivered this was the response this request is a response and see what the order status is are we still getting spammed with orders looks like it stopped. So, keep a watch on this link this analytics app link after the talk is over also you will see that how the system will handle the scale without any intervention. So, I have not done any tweaks which matters this particular amount of load this was something that was working for 1000-2000 orders and see for yourself how the system will handle it. It's nice to see all this in one talk but we have also formally or not formally just put it down in one place if you can go to prefactor.app and you can read about all these principles this architecture principles that I have just introduced right now. So, we use real time GraphQL for faster iterations we use event revert for resiliency we use async serverless for scalability so you can check out this link prefactor.app and you can learn more about this architecture that's it, that's it from me the product that I use right now for Suda GraphQL engine that is what we do we build GraphQL on Postgres check out the GitHub repo star eight it's open source we released this three months ago and we have got a huge response it'll be awesome if all of you star it and show them show us more love have you guys got the stars from school like notebook they'll stick stars right very good star not saying the same thing but that's how we feel anyway please meet me after the talk any questions what do we have time for questions let's take a couple of questions and we'll definitely star your repo please show the same enthusiasm you've shown to place those orders if you did that we could get some 200, 300 more stars hi so you have talked about what are the actually benefits of the GraphQL and how it is like handling so many orders phones like and drawbacks of using it like what are the disadvantages so I mentioned at every step when I pointed out all the benefits I also point out the cost what is the cost associated with this it's not technically drawback it's the cost so you need a GraphQL server with subscription and building a GraphQL server with subscription is not easy it doesn't come for free unless it's a GraphQL engine which is open source and free but anyway so it's a huge effort so you need if you want to do this on your own it's a mammoth level task and if you particularly want to know about the cons the cons are there with any real time asynchronous system you need to be able to handle certain race cases and edge cases which will not appear in any synchronous system right the moment you introduce asynchronous actions or asynchronous pattern in your architecture you need to be able to handle all the scenario that all the other problems it introduce doesn't make sense so with GraphQL per se I can't pick out there are issues with the client libraries any new system has its own issues but it's getting better because the system is working towards making it better any other question sorry I had a question from what I've seen where you use GraphQL typically what happens is that the GraphQL query gets sent to your server over HTTP post which sort of makes any type of CDN or any HTTP based caching completely useless have you figured out some way to kind of is there any patterns so that I can get the best of both worlds where I get kind of the power of GraphQL as well as I'm also not losing out on all forms of HTTP caching so this is one you can say this is one of the cons certain things you will be able to cache in your server there is one way which people have tackled this which is to send the query in a get request in a query parameter which is a hack you will have done it but the community itself is working towards better caching mechanisms but typically you would not need to worry about it unless at scale you need to worry about this but it's a problem that is being actively worked on there is no solution right now that's a great talk Shahid thanks for listening everybody again that a low person that's a good applause if anyone are still interested to know more about GraphQL discuss about GraphQL there is a BOF at 440 outside of it so he will be present so you can ask all the questions you have and we will take a coffee break whatever you like so we will meet back at 430 so let's start the session so our next sorry our next speaker is an entrepreneur two startups at a college and he was also called as Guruji in his office like everyone takes advice from him he loves cats and dogs he has three cats one is Sushi and I don't know two names so he also loves manga and other anime things so he wants to talk about the out of writing test for the backend and stuff so let's listen to him thank you hey everyone thank you so much for coming out today and staying till the very end my name is Deepak Pathanya I work as a product engineer at Postman the API development environment you all know and love and today I'm going to talk about the art of writing mature tests I'm available on Twitter as Deepak Pathanya which was supposed to be a clever wordplay on my name but now that I say it out loud in front of so many people doesn't sound as clever but yeah I'm there on Twitter so yeah you can talk to me about APIs tech or life in general I'm pretty chill like that so let's get started so a little about why I decided to compile this talk in the first place so during my initial months at Postman I was working on this module which was supposed to be really really performant we were constantly trying to figure out different implementations to you know extract that last juice of performance out of this module and we were actually trying out good strategies but there was just one problem tests were holding us back every time we tried out a new strategy I was writing and rewriting a lot of tests and then modifying them all because of a slight change in the codebase because the tests were because the code tests were not able to accommodate that change they were too rigid about the internal implementation I was spending more time fixing tests than writing actual code at one point which I thought was a huge red flag I was going through tons of fixtures to debug failing tests at this point I thought something had to be done but then things got a little worse I realized that I was mocking and stubbing and faking and spying and you get the idea right my tests were actually trying to use everything that is available to write tests out there they were actually just as complex as the code I was writing and I was hoping that the flaky tests don't show up again in the pipelines because some of them I couldn't really reproduce on my local system so I had no idea how to proceed there and at one point I was just staring at assertion failures and stack traces aimlessly so at this point we decided that there has to be a better way so we tried out a lot of different testing strategies and some of them started to make a lot of sense as a benchmark we noted that from going from fixing about a hundred tests for a minor version release we went from fixing less than ten tests for a major version release so we thought this things actually work so we decided to compile all of these small things that you can do without changing a lot of different things in your existing suit so since my title is so click-beaty I would like to explain what not to expect in this talk so this talk is not going to be about a comparison between different testing libraries and frameworks and approaches out there I would assume that what you have you're happy with it if you're not then there are tons of great libraries and resources and articles online would be able to outline these differences much better than I can in a 30 minute talk this would also be not me preaching about writing testable javascript from the beginning I would not tell you that your tests are bad because your code is bad because I can't preach about something that I don't do myself either so yeah what do you expect out of this talk then well you can expect some small actions to improve your current tests without making a whole lot of drastic changes in your current frameworks so let's get started so these are some common mistakes and how can you avoid them the way I've structured this talk is basically it's a 12 point talk sorry that talks about before and after of some different common testing scenarios that you might come across I think to note here is that all the before versions that I outline here are not bad actually they work and they work very well it's just that as you scale some of them might not scale with you also I've tried to be as a framework generic as I can but for the purposes of this demonstration I'm using chai and expect I think to note here is that you can actually do these suggestions in any of the testing frameworks just for the demonstrations I'm using chai because I love the beverage so yeah let's get started so before the first point there is this 0th point which is the test monolith this is the term monolith has been thrown around a lot today so yeah I just wanted to ride on to the wagon so the test monolith is basically this code that has high coupling and no isolation all of the tests are coupled in such a way that you can't really isolate them to run them independently these are actually neither unit nor integration what I mean by that is they make DB calls they call third party services they assert on multiple values and they don't really fall into any of the categories because they give you the worst of both worlds you don't get the isolation and speed of a unit test and you don't get the coverage and confidence of an into an integration test either so why I mentioned this as the 0th point is that because this is something that we're trying to avoid throughout all of the 12 points would kind of build up to this so that if you followed you would be able to avoid the test monolith hopefully okay let's get started so the first thing is asserting a deep equality so we'll basically walk through this code and see what's wrong with it so this is a normal test that tests for user details verification it says that the returned user from a DB call should include all the required keys which is a valid thing to test so we have a user ID we will not get into the details of how this user was created we're simply calling the DB service to get this user once you get the user we're asserting it that it should call with this right ID1 and name debug now this might seem like a perfectly valid test and it is but there's a small problem with it this so whenever you're dealing with deep equalities and strict checks there's a very very high chance that you will be fixing your test later as people who work in startups we work on things that are under rapid development so you might be adding a lot of different keys you might be removing a lot of different values from the response objects that you send from one function to another and if you're very strict about the object that you're checking in your test code it is bound to break so tomorrow you say okay I want to add a username field as well to my users all of your tests that checks for the user response strictly like this would start breaking because this actually says that your response should exactly be like this right so a little slightly better way to go about it would be to do something like this we have the exact same test here when we call the when we get the user by calling dbservice.getUserByID rather than asserting on the exact structure of the object we just say that it should include all these keys now I promise that I would not get into the details of one framework but this is something that is present in most BDD test assertion syntax I've just given the example of chai so you can find something like includes contain and something like that in your testing framework choice as well so just a simple fix of you know not asserting on the exact deep object but just checking that it includes all the required keys you want can actually make a huge difference when you start rapidly working on your projects moving on skipping tests so skipping tests is something that we all have done in the past or it is something that is actually required in some cases so for example in this case I have a listen ordering test and it is that it should allow moving a listen to the beginning I'm assuming that's just a listen linked list or something and I'm testing that moving to the beginning should be allowed it's a perfectly valid test but for now we have skipped it so what's wrong with it there might be something that is actually not ready for this test to be done right but the problem is we haven't specified what that thing is and we haven't specified when this test is ready to be unskipped I've actually seen open source code bases in which there was a skip test from two years ago and none of the future developers had the heart to touch that because they didn't know what that does right so a small but nifty solution to this is specifying something like this we are saying that moving a listen to beginning is currently not supported because of some limitation and we are specifying a to-do that says that unskip this once head pointer is introduced so the next guy who comes along and reads this if he sees that ok head pointer is now ready he can unskip it and get on with it this is just a small change that I've seen gets accumulated over time like I've seen 15-20 skip tests that nobody had the heart to touch because nobody knows what they were supposed to do so yeah just a small thing that gets a long way when you're working with teams next slide too many fixtures so fixtures are basically just dummy data that you use to send in your tests and assert on the responses right we've all seen that large json object that we have a fixture object of here I'm seeing that we have too many fixtures like for example in this one I have a user that has the role as admin and I've second user that has the role of user and similarly I have so many other users with some different properties that I'm using in different tests but the first one I might be using it in a test for checking admin privileges the second one I might be using for checking non admin privileges or something like that the problem with this is once something actually breaks the next guy has to go three levels deep to debug what that was right so imagine the scenario you had a test that called the fixture data dot u1 and it suddenly starts to break now the guy goes to this fixture file he looks at u1 it then looks what all properties it has it then looks at the test and sees what key what what method would might be breaking that actual test and then he goes on to debug that right and if you have like two thousand of these objects for different scenarios you have like some technical depth you need to get off so a better way to do this would be to construct an object with the minimum required properties so here as I mentioned I'm checking admin privileges I'm checking that the admin should have access to remove members something right and I decided to construct an object with the minimum required properties that gets my job done so the only difference between the first two users apart from all the name and avatar differences but their role right so I can construct a bare minimum object that I pass to that function and check the same things rather than calling in you know fixture fixture value so what this does is since I'm specifying it in the test itself it's very easy for the next guy to debug it and we use u1 in the test code and see how I mentioned with the minimum required properties right because some of you might have some policies in place that allows the checks that a user should have these properties should have these keys and stuff like that right so the minimum required properties with which you can construct objects to be used in test is a nice thing to have moving on so conditional logic so this one is actually a little bigger let's see through it and then see what's actually going wrong here so this test is basically checking that on violating thresholds we should add the user to the mailing list right so like if I use a violate some sort of thresholds we add them to a mailing list to say that hey update your plan or something right so what we're doing here is we have a current user current usage of that particular user that we get through a random number and based on the number that we get the user's current usage might be above the threshold or it might be below right if it's below the threshold we assert that the mailing list does not have this user and if it's above or equal to the threshold we assert that the mailing list has this user this is actually a valid test wherein you're just checking that if the if the user actually violates the threshold is added to the mailing list but then again there's something wrong with it so the wrong thing as we have already mentioned in the point is conditional logic your test should ideally always test one execution path if you have a test that is checking multiple execution path you should ideally break down into two tests that enforces that to take one of the parts so like let's look at the better way of doing this so here we have some value above threshold specified as thousand we are using that value in the current usage and in the test we are simply asserting that the mailing list has this user in the next test I can have a value that is below threshold that checks the alternate execution parts so this is a simple thing but what is what it's doing is it's making sure that your test always goes through one given execution path there is no uncertainty involved next so following poor spec naming conventions so we all know that naming variables is a hard problem to solve in tech right but the same is true with naming your test specs as well so what I've seen most people do is that they use the name of the function in the describe block that they're writing so if I'm writing a function that adds a user my describe block would say add user and but as a thumb for writing better descriptions the describe it block should always form a proper sentence because even though you specified say the name of your controller or anything in the describe block the next guy who comes along might not have the context right so if reading the describe it block makes perfect sense to him it makes his job so much easier and a single test description should include the unit of work the scenario in the expected outcome let's see some of the scenarios wherein this is being followed and violated to get a better idea of it so let's see this so here as I mentioned we're using the function name as the describe block description in the eight block I'm specifying that it's a test for number seven two double three right now the seven two double three could be a GitHub issue could be a Jira ID could be you know God knows anything right so if this test decides to fail tomorrow the guy comes along the next day I was looking at your code comes along it tries to figure out what seven two double three means it then looks at that particular issue sees what went wrong there then looks at the test then sees what actually changed from there to now which might have caused this test to fail and then fixes it by this time you've lost one thousand users right so a better way to go about it would be to use the spec convention that we have stated right now so yeah something like this doesn't really make a lot of sense because what if you were using something like Jira earlier and right and then you decide to transition to something like aha or something you have a different issue tracker now how do you decide what this ID actually belongs to moving on so we have this particular test here which again uses the function name as a describe block text and it says that it should return 200 for proper input it should return 400 for wrong input this I've actually taken from a very famous open source library right and it just says that it should return 200 for proper input and 400 for wrong input both of these tests pass right in the first test somebody had used a value of say 5 or something in the next one somebody had used a value of I don't know 8 or something right as the next guy who comes along it's up to my curiosity what I make out of those number is it that this particular function works only for odd numbers is it work for you know multiples of 5 or something I don't know right since I've not specified what the proper input here is or what the wrong input here is I don't really know what the context is so it actually leaves a lot of things to the imagination of the next guy and this is very famous quote that says that always write your code in a way that the guy who ends up maintaining it is a serial serial killer and knows where you live so if you follow that principle this is not what your test fix should look like so a better way right so this is a scenario in which I'm specifying that dispatching an active bucket should empty the active bucket and add it to the process list right now this is actually following all of the principles that we've talked about so far because we are specifying what the unit of work is what the scenario is and what the expected outcome is so the next guy comes along and sees that it's failing immediately knows that something's wrong with the dispatching logic of the active bucket and he can go ahead and fix that he's a happy person so are you next so deeper implementation levels so let's look at this again and see what might be wrong with it so we have a function we are testing for a function that adds a user to the database is saying that adding a user should add them to the database so much for good naming we are specifying a user with the bare minimum requirements that we talked about earlier and in the async waterfall we are adding the user first in the next one we are calling an internal queue in which the user is added first and then flushed to the database and we are saying that the internal queue should include that particular user and this looks like a perfectly valid test right we have a scenario wherein we add a user it gets added to an internal queue then gets flushed to the database and the user is added to the DB so much for writing good tests but there's something wrong with it well we are at a deeper implementation level then at what we wanted to be how does that mean and how does it make sense well it would in a minute so yeah here's a better way right we do the same thing we add the user to the DB but now we stay at the same level by doing a DB verification now rather than checking whether the user was added to the internal queue properly or not we actually get all the users and see that the user is part the user we just added is part of all of the users from the DB what does this do and why does it make a difference right so consider the scenario wherein your internal queue flushing logic went down right so any user that you add is actually not being added to the database but all of your tests still pass because in your test you simply asserted that the user should be added to the internal queue properly this is a very simple naive example but the thing that is trying to highlight is you should always stay at the same level of implementation if you're trying to say that an action went through and rather than just checking that the endpoint returns 200 verify that that action reflected in the DB that way you're not screwed if there's something wrong or if there's a discrepancy between your database and how you're returning your JSON right is it making sense okay nice okay so yeah we expect that the users include this particular user uncertainties so yeah we have this particular thing wherein we are testing for string handling we are saying that it should ensure that large strings are handled properly it's one of those functions which formats large number of likes into like say 10 10 m 10 million likes to 10 m or something like that it's just formatting likes and the way this function behaves is if it gets a string that it cannot handle it throws an error right that's the assumption so here's how we're testing it we are basically creating a very large string using this iterations variable that we call in the loop and we get this very large string x which is just the repetition of the string 1 2 3 4 5 then we call it in format likes and we can and we see that if it actually throws an error or not right if it does we return the done call back with an error otherwise we do right so this basically just says that if your format likes function through an error your test fails some of you might be wondering why we don't have any assertions here that is because of how we have handled the error in the catch block we're simply throwing the done call returning the done callback with the error which makes the test to fail if it actually throws right now there's something wrong with it because if this test fails there is an uncertainty in my mind did my format likes function go wrong or did my string generation function go wrong right it might be so that this method that I used to generate large strings has gone wacky and is not generating things properly anymore did that go wrong or did my actual function go wrong well you have to check and know right and that is what you don't want to do when things are breaking so a better way to do this would be to just you know specify a static string so that you trust your tests you know that I specified a static value in my test and if that is breaking and the error and the test is failing and something is wrong with my format likes function for sure the last thing you want when your things are failing in production is to be uncertain whether my tests are wrong or did I do something that might have caused this right you want to be certain about which thing you want to target when things are breaking and this allows you to do that so we just specify a hard coded string and use that in our function separating declarations from usage so this is something that is not really related to how tests work it's something that you might come across when you're debugging failing tests and it is something that used to get on my nerves so I decided to add this here so what I'll see is I have two variables at the top bonus points or anyone who knows what these variables mean can come and talk to me and in this describe block we have tests that have vars declared up top the first block do not use Luffy or Zorro the second block uses Zorro not Luffy and the third block uses both Luffy and Zorro but we've still declared all the variables at the top so that they're available in the describe blocks the next guy who comes along to your organization might see this as a practice any variable that you want to declare for usage in your test you declare it at up top this actually leads to a snowball effect I've seen test files which when I open I have 150 lines of variable declarations and then my describe it block starts so the last thing you want when debugging a failing test is to scroll all the way up see which variable is failing and then try to debug it I've tried that split view and all of those things but when things are failing you just need your piece of mind so a good way to do this is to use the scope that describe blocks provide you so has like a yeah so the good way to do this is to just specify all the variables close closest to their usage right so you if since the describe block provides their scope of a scope of their own if there's a variable that is supposed to be used in this particular describe block specify it at the top of that block it actually makes a lot more sense to you know scope them closest to the describe block they're being used in rather than at the top moving on dependence so let's look at what this test is doing and then we'll see what's wrong with it so we have a describe block that tests for all scenarios of updating a user status in the first test we are saying that it should allow updating role of the user so we create a user here we pass that user ID to the next block and then we verify in the db that the update went through like a good tester right good thing but has something that we did wrong we actually in the second one we update the user and verify it in db right we use the same user that was created in the first test block in the subsequent one hoping that since they're in the same describe block they would always be executed again so that way when my first test run I have that created user I update its preference I can use the same created user in the subsequent test well this actually leads to dependence in tests ideally all of your tests should be able to run in isolation when you're fixing only one test something like an only clause should work with each and every test and setup and teardowns are there for your rescue so here's that same test again in a better way so in the updating user status we have this before method that actually runs before before the test in this particular describe block so the order is the describe blocks runs first and then the subsequent ones so if you see I'm using it dot only here and it actually works because before this test ran we actually had that user creation in the before block so even if I run this in isolation my before block would still run and I would have access I would have access to that user which I'm trying to update unlike the first case wherein the user was created in the first block and then reused in the subsequent one this actually brings us to the next point which is extra setup so we just saw how setups and teardown can help us remove dependence but they can also hold up and act and kind of choke your pipelines if not used in the right way so let's look at this particular test we are testing user updation flows in the first one we admin privileges we create admin add a non admin user and in the after block we delete the created user notice how we're using before each here instead of before so this actually runs before every user so that even if we create and delete them we still have access to them in the next test block in the first one we simply create the admin and non admin user and it uses the created admin user and the second one it uses the created non admin user right the seems like a perfectly valid test the thing wrong with this is we're actually creating the admin and non admin user before each of the test runs right so in this particular case the flow would look like what the flow would look like is we create two users one of them is used in the first test then we delete both of the users then we create two users again one of them is used in the second test and then we delete both of them again right these are just two tests imagine 5000 right so if you have a lot of code in your setups and teardowns which is not exactly being used by every test in that particular describe block and you're running a lot of things for each of your tests right and as you scale your pipelines would run for 30 40 minutes so your developers would simply push something go out eat something come back see that the pipeline has failed rerun the pipeline and do that for the rest of the day which is not something that you want right so here's something that you can do in a better way so here what we have tried to do is we have tried to scope out the different uh checks that we wanted to do into two separate describe blocks now since describe blocks follow scoping each of the describe blocks would have only their particular lifecycle methods run so the first one would have set up for admin users and all of the admin related tests would go to that describe block similarly the non admin users would go to the second block in this way the first test would verify whether the admin can update team billing cycle would have only the admin user being created before it is before it runs right so this actually accumulates this actually allows you to scope out different tests in such a way that only those tests who need common prerequisites are grouped together in a describe block moving on so asserting on values without explanations let's look at this uh so we have something called spy here so spy is basically just a construct that allows you to look at a function and see everything that's happening to it how many times it has been called what arguments were passed to it each time and things like that you can read more about spies I'm using synon here right so I have a spy on db update and a spy on db destroy and I'm creating an admin user and I'm deleting the user here and in the assertions I'm saying that the spy on db destroy should have a call count of one and the spy on db update should have a call count of two right this test works everyone is happy but then one fine day this decides to break the assertion message that you get would simply be the spy on db update has a call count of one rather than two at this point the next guy who sees it since he has no context of what all goes in the db update method uh in the what all happens when you do the uh admin deletion he has no idea what might be going wrong right in the worst case scenario he might actually change that call count from two to one make the test pass and then push that again hoping that was actually wrong earlier and now you have fixed it right so something like this can easily confuse people because you're just asserting on random values without explaining there and if something like this starts to fail you simply have a message like expected four to equal three right which is very confusing for the next guy so a small thing here would actually go a long way we do the same thing we create the admin user we delete the user but then we specify what each of those calls actually meant in the first case we specified the db destroyer would be called once for the user who's actually being deleted and in the second one we specify the db update would be called twice one for the team members being updated and since this was the admin user the ownership had to be transferred to someone new so one db update call goes through for that right now if this fails then the the guy knows that okay either the team member updation logic is going wrong or the ownership transfer thing is going wrong I have to go and check one of those things right so he's a clear way of debugging what he has to rather than just speculating what could have been okay last point too many assertions so let's see what this huge test is doing we're saying that we should verify that a user with role admin can delete the team we are creating a user asserting on the return response like a good tester we are verifying in db that this action went through we are then updating the user to grant delete access and then we are verifying in db again that the access was granted we are then deleting the team this user belongs to and then as a good tester we are verifying in db that the team was deleted right this looks like a great test but there's something wrong with it so at every step we have a lot of assertions right we are creating a user then we are verifying it went through we are updating the user's permission we are updating that we are checking that it went through and then finally we are actually doing what we wanted to right a good way to go about it would be to use something like stubs right so what a stub is a stub is basically a function with a pre-programmed behavior so you can specify that this function should always do this if a stub is wrapped around the function then the original function is not called the function that you specify in its place would actually be called so here I'm having separate tests for user creation and updation which is very important I'm saying that I'm pretty sure that the user is properly created and the user is properly updated because I have specific separate tests for them and they work and I'm confident about my tests in this particular test I would simply stub that the user is created and has the required access right so I'm saying that whenever db service.getUser is called rather than calling the actual function just return this user that has all of the granted access and then I'm getting the user deleting it and then as a good guy I'm verifying that it was deleted in the team right so this basically says that you should have some sort of abstraction in your tests so that if you actually are doing multiple things you can abstract out some of those things and stub to reach that particular point which brings me to the next thing which is abstraction in tests so consider the scenario wherein we have an initial state some setup a branching state and then we transition we go to different parts path a b and c right ideally there should be separate tests that assert that one user can reach the initial state properly there should be a test that stubs that the user reaches initial state and then should check that it reaches the setup state properly another test that stubs whether he reaches the setup and can reach the branching state properly and another test which reaches the branching state and then test for each individual parts so the point that I'm trying to make is if you're testing a thing once make sure you tested only once if you have a test that tests for user creation then every subsequent test that requires a user to be created should not be doing that again and again so if you have to reach a particular branching state to reach multiple parts use stubs to ensure that you have already reached there and then actually test only the thing that is required in that particular path which brings me to test design so test design is nothing fancy I'm not going to talk about TTD because it's not it does not really make a lot of sense for some of the startups wherein you are rapidly changing things you write tests for something you make them fail you make them pass you write the code tomorrow some other requirement comes the exact the entire code base goes away right so TTD does not make a lot of sense in some of the cases so something as simple as test design where you're laying down constraints to define boundary where you are identifying the different actors scenarios and all the permutations from the beginning and writing them down as described blocks and then writing the test and just filling those described blocks later makes a lot of sense this allows you to think first and test later so that you have already prepared a spec of what your test should look like and when your code is ready you simply fill in those specs and what all does this give to you right you've done all of these 12 points you've mastered the art of writing mature tests what all does this give to you well onboarding new people isn't a nightmare consider a scenario you have a huge project right and I decide to join tomorrow I see this massive code base I come to your desk and I'm like please explain to me what all of these files do right you don't have the time or patience to do that but if you have good test suits with proper naming conventions where in describe it blocks make proper sense you can just try redirect me to that and say experience what I've seen is you don't really need mocks at all in majority of cases this is just my personal experience right what I've seen is a stub that has a pre-programmed behavior can actually suffice in most cases you use mocks only when you're actually trying to assert on the response that that gives right so for example if you're making a third party call to get some data and you need that to backfill your test in that case a mock makes sense right because you're trying to say that rather than actually making that third party call this is what that call would end up returning but if you're using something internally the example in the examples I showed you're using something like a get user or DB service or calling an internal method that was supposed to do some computation their stubs make a lot more sense because you know you can just specify that this is the function that should override this implementation and since I talk mostly about unit test they should not ideally include third party calls at all so in those scenarios mocks don't make sense but yeah if you have any third party calls which you would like to assert on the result of then mocks make sense there so that's the main difference that I find that for any internal thing that you're calling stubs suffice but any third party calls go with the mock So in your 11th explanation where you're explaining why the test code written equal to one equal to two was not a proper one the solution was that they can write some comment over that so that the end user can understand should I be there otherwise if I have to rely on the comment I can write the same comment in the code itself instead of writing on the test block or somewhere else describe and it would be explanatory so that's a great question actually so my counter argument to whenever someone asks that is I use tests to onboard people like I mentioned onboarding isn't a nightmare if you have good test specs so if I'm redirecting someone to look at the tests I would want them to minimally look at the actual code so if I in my test description itself I have I ideally tell them that close all the describe it blocks and just read the sentences that they make right say oh dispatching the active bucket should do this should do this in this scenario should do this in this scenario and stuff like that right so I ideally tell them not to open the it blocks at all but in worst case in scenario you would like to see what's happening expand the it block and there if they find a comment like this they don't have to go to the code right so just for out of my personal experience I've seen that specifying these things in the test allows you to onboard people better because if that guy goes into that code file to read that comment now isn't he's in a new rabbit hole right he starts to try to decipher what that code is doing how things are being working how things are integrating together and he actually gets confused a little so in my experience I've seen that specifying things at the test level itself makes more sense in these cases hey I'm here at the back so can you hear me yeah I can okay so great talk I like the idea of designing test cases before actually writing them thank you I have a question on the documentation so let's say I have written test cases for like five to ten files and somebody is joining my team now so I would want that team member to go through documentation first rather than going into the test cases and looking at the assertion so let's say comparing to a code there are if you add jesphoo not jesphoo jes I think I forgot so there are if you like comment blocks on top of your methods jesdoc yeah that's all you can use any npm package to generate documentation easily is there anyone for test cases as well yeah so jesdocs actually make a lot of sense we do use them heavily for some of the things but what I've seen is that when you are working in a fast paced environment for a module that might not be even available tomorrow because expectations change in startups right in those cases you don't really have the time and patience to write those beautiful jesdocs in comments right so something as simple as a normal comment where you're specifying what I'm trying to do here or the describe it blocks making proper sentences would suffice there right if I'm writing a module that is being open sourced or that is going to be well maintained throughout I would definitely recommend going with jesdocs because you can have a simple npm command to generate the documentation when you do any more changes right that can be a part of your publishing pipeline whenever you publish update the documentation by picking from the latest comments so that makes a lot more sense for modules that you know are going to stick around but when you're just hacking something quickly for something that is rapidly iterating things like these make more sense okay so my question is around do we have any tool to generate documentation of test cases similar to jesdocs probably I haven't come through one if you if you do then please tweet about us please tweet about it I'd be happy to look at it thank you okay thank you deepak patan here I mean deepak patan here that guy had a question do we answer that we'll cover up okay cool thank you so I think I'll force my back end developers to write test when I go to office one day I don't know what about you guys so our next speaker is hey month he's an ambidextrous guy and he also got a Guinness record so he says that he had a virus in his brain and he's acting weird since then I don't know why he's acting weird you need to find out now so he's also a polyglot google developer expert as well as he spends most of the time in free and open source software movement like helping dug dug go and other open source software so let's welcome hey month can hear me guys Namaskara GS Fu thank you for being here for such a long time I'm going to end the day with a story story of ved my son who wanted to learn some serious JavaScript then I suggested him not to read so light versions of JavaScript but to read something serious JavaScript for babies he did read that and his first assignment was to read a file as simple as that he said well that's easy I'll just do a read file sync give me the file name I'll read it okay but it blocks he said okay he learned some more and he came to the call back version instead of the read file sync he started using read file and then gave a call back to it with the file name after the file is read there's a call back if there's an error you would call back with the error and result this is the normal drama we all of us have done so far okay that's not bad now you want to process a file the same file you have read now you have to do some process on it how to do it said okay that's easy again I think he started with a simple function call process and for which a data and the call back is passed and the remaining pattern of reading a file and checking for and handling the call backs and then returning the call backs and again a call back in the process continued you rang I heard you like call backs so you can put your call backs in your call backs and call you back when your call backs are done right this has been the common slide most of us use from Mozilla where it explains about the pyramid of hell this is an example where you want to cook some rice you pour some water bring it to boiling temperature lower the heat add some rice set time out and how many call backs we already have to eat our rice promises when you know then you know right promises are some objects that can that resolve that gives you some result and it's kind of promising you that I'll give you some result on a period of time right it can go through different states it can be fulfilled or rejected if it's fulfilled then you'll change it with then if it's rejected it will go to the catch the fun part is with then also you can handle both rejection and fulfillment and finally it is settled and you have some operations and the idea of promises is you return a promise and then you change it so again it's like you could change your promises with then some catches right after you catch also you can do it then it's a simple example where you do a new promise and you pass in a function with resolve and reject to it if everything goes well you resolve it if there's some problem you reject it with what the problem was then you can do a promise dot then and the first callback that comes in would be be successful if it's resolved or else it will be rejected here's the simple node module I've written called lie-fs but today if you're on the latest versions of node you can use the promise if I version of fs fs slash promise which comes as a neutral within node but with live dot fs what basically it does is it promise if I is all your fs methods so in this example if you want to know the stats of your temp directory you can just do fs dot slash fs dot stats on temp and you get a promise you can also log it or error it out if there is an error but there's a problem again with promises if you're not careful you end up with something like this well there are mitigations similar to how you can escape callback else you would name your functions name functions keep your promises separate all those things are there but it's not it's not guaranteed that everyone would practice that you would have seen many of the code bases having this kind of a thing here's one more real word example where you connect to the database and get the user information and get the user settings and then finally enable access so it almost looks like the callback hell but with more of a chaining of then how many of you know this guy awesome yeah so that's tj tj wrote a blog post a few years back he said streams are broken callbacks are not great to work with errors are vague tooling is not so great in the community it's not so great and community conventions it's kind of sort of up there I for a very long time I thought tj was a company the amount of code he was churning but luckily I happened to maintain one of his repose it extras then I believe that ok tj as a person exists but I was seeing this pattern even though he quit note he was he was pretty active on this project called kovages which I'll be talking about and why tj also felt and I think he saw the future welcome to Jurassic Park I think await I think is a keyword when used next to a function it indicates that whatever you return in a function would be a promise it could be as as simple as return one so if you have a sync function and you say return one it would return a promise that would resolve to one and I think functions of the function are only those functions where you can use this await operator right and what is await operator await is an operator that suspense the execution in the scope so what I mean by that is suppose you have an async function and you are waiting for a promise to resolve it kind of suspense is the execution the order of which it's executed assume like pausing the flow only within that async block right and then it will wait until the promises either resolve or rejected if the promises rejected it will throw so in 2016 I said years 17 or years 2017 will be look the code where we write would look like sync but run like a sync and in 2015 at 3 in the morning I said I said like script await is no fun till it gets an easier way to capture rejected promises in 2014 I kind of did a talk on async await when it was in a proposal state and people said like dude it doesn't make sense but today this is how we can define an async function the emoji is just for the fun of it if you want to define such kind of function you have a plane object and put the emoji in the string then you can still define and you can see async function and see await it's normal like the normal function and you can use an arrow function or you can use a generator here's an example from the codebase I think I can point to this alright that's fine this example is from the spec what it is basically doing is it takes an element and set of animations applies the animation on that element and finally returns the final value after applying the animation on the left is the promise way of doing it we basically have a promise resolve you could also read you can rewrite this with produce but you basically have a promise dot resolve as your initial promise and then for each of the animations you you do it then apply the animation save the result and finally return it if there is an error you will catch it of course if you were to rewrite the same thing with async await it would look like this right you have an async function you have a try catch block and for each of the animations you just await for the animation to complete and you have the return value in this it looks so intuitive right you can just if you can just take it as an example read what's happening on the left and read what's happening on the right or for you it is the left and right and then then it's so intuitive to read it looks as if you're writing an asynchronous programming but because there is await it is asynchronous in nature all right demo time so I had written this you know kind of a xkcd comic fetcher how many of you follow xkcd okay awesome so what it it does is basically get fetches me a random xkcd cartoon you're not able to see that all right this screen is not coming up there probably because I'm on fullscreen or it's tough to see the big screen and type enable the mirroring but this is not working this is a second sorry for that all right so basically this endpoint gives me a random xkcd cartoon it gives me the URL and then gives me the title right now let us go through a journey of fetching this URL from the console and see how the journey goes through we start with XHR it's big now we do a new XML HTTP request the name is XML HTTP request no more we are doing XML calls or it's an HTTP it's more like Gulab Jamun neither it's Gulab nor Jamun right but but we over lives as JS developers for this like this is like gift from Microsoft where the people enable the XML HTTP request we do XHR. open which takes a method in this case it is get and that's not the URL this is the URL to which we are talking and then I'm not sure how many of you are aware or have used this last parameter the last parameter makes this a synchronous call a synchronous network call right that's where Chrome spits directly on your face saying that hey don't do this and if you were tried if you try to set the response type on this you can't do that because it is synchronous right now we kind of say on load end we will console log image yes console log image XHR dot response dot data dot what what is the thing we were getting response dot URL right and then we send right we got the response it said title and URL console log image what we got was this yeah this is how it should have rendered right now it's totally from the server nothing is mocked it's not my fault we do a new XML HTTP request again and this time let's kind of make it synchronous quickly right we again open up with get but we will not pass this false here and then on load ended we will take this and let's quickly log what are we getting on as response right response dot data dot URL and then we send so it's not data dot URLs for sure right so we open again all right that's the good way to do it and we have done an open we'll do a send so it's URL it should it should have just been XHR response dot URL right it's a string okay very attentive audience at 5 p.m. all right we open again and we send all right that was perfect so we got the point right we'll we'll go to the next one and we'll pass it out there so that so we started with XHR we did a synchronous call then we did a synchronous call we saw the network request call happening now is the time for jQuery right with jQuery what do we do we do a get json right and then our URL I better define this as in API somewhere right I will call this API and pass this here and we do dollar dot get json okay and then we pass the API and then we pass the we get the call back right which has the data in this case will the data be passed or not is it passed now we do image and data dot URL okay so we have the image in the console all right now this was jQuery so we did the synchronous asynchronous jQuery and finally what's up next yes we would do FH API and it returns a promise so we would do it then and say we have a D and this kind of gives you json and then you do it then again call this response and console dot image response dot what would it be here URL right and then if we would probably need a catch if there is an error right let's see okay there we go that's neat so how do we take this further now let's try I think a bit of this right now we will remove this we will say await fetch one gotcha here you can't you can't really use await in the top level there is a proposal for top level await what do I mean by top level is basically you need to wrap this line in an async function as mentioned earlier because this def def console if you use a top level await it kind of gets wrapped with an async function so you can do do an await on the def console without wrapping it in an async function right we do an await we get a response right this would have a json on it isn't it we will do an await of that we get the data we console image this right dot url making the request so we wrap this entire thing this is fine right yeah no as in where the url is coming that's fine so we wrap this entire thing we get this okay there we go it's a really bad way to do it as we noticed having await await await in a line again this is just for the demo purpose to show what we are awaiting for and thanks for being an enthusiastic audience and highlighting all the scripted mistakes right awesome so we we saw we kind of read we kind of saw the journey of starting with the synchronous to asynchronous to jQuery kind of a thing to an await today we kind of saw how we do this it's kind of clear okay so here's a quick quiz question on what would left print or log and what would write log by intuition the left looks like it would log abc right right right yes no yes but no it will not it will end up logging see be a but why what's the difference between these two the key difference is we are awaiting there's a written await the other one would print abc right so it's a key point to remember that when when whenever you're awaiting if you're if you're returning something out of await which is kind of an obsolete this just to show that how await kind of makes a difference if you're returning something in the try which has which has a promise and your functions are saying make sure that you're awaiting for it that's when it waits for that promise to get resolved in this case it doesn't really right so that's where you know how the how the pause kind of a mechanism is working and suppose you have two async functions right you kind of await for it rather you could use promise dot all and say await await of promise dot all and you to us in functions whatever it responds a returns would be R1 and R2 so there is all there is also a proposal for await all which kind of got rejected and at the very beginning when the proposal was there there was this proposal called await star which was doing this but even that's not there and in the in the previous talk also we saw this I think that waterfall being used a lot right now if you were to rewrite async dot waterfall async dot series with async await how do you do that on the left you have waterfall where you have await await async function one the results of that is in R1 and then you have await async function to result of that R1 is passed to this so you'll get the result of R2 so it's behaving more like a waterfall on the right you have the series which is pretty simple you can return an array of awaits and if you have an async in async iterator you can use you can you can iterate it with an await this is because you can't do an await of for each right it is not it is not like asynchronous where you could use await and wait for things to get resolved or whatever processes you are doing that's where you have to use this loop called for await off and if you have an iterable in this example is just a simple iterator where it kind of returns and results to promises and you can await for each of them and log it out so the other example is where instead of you using promise dot all always you can have an all higher order function where you pass in the parameters and do promise dot all there if you want individual you can just pass like P1 P2 all your promises or you can just spread it out and send all the request and get it back to an array and also you can use await on any thenable function as in this case you're seeing it's just an object which has then the blabber loop is like resolve and reject you can just await on that and it just console logs 42 so it need not be a promise it can be any thenable function so if you have a class which has thenable in it you can easily wrap it in an async function and await for it and if you are if you are using express and if you want a middleware which has async of it you have to be you have to do bit of a circus where you have to wrap your middlewares with an with a promise which kind of resolves that function so basically pass your middleware to that it's kind of it kind of wraps it with the promise and send it over rather there is this project that I was talking about when TJ was interested on Kova.js which basically started with the generators and now it has async of it as you can see the pointer moves every time there is a next await next it goes to the next chain middleware automatically so you need not wrap your middlewares just use await it's it's a very lightweight module you could you could try using it and the pain part if you have absorbed is you have to wrap all of your awaits if it is throwing with a trycatch right or you are there is or you could say promise dot something and then do it dot catch again but isn't it painful to have a trycatch block everywhere where your await might throw so here is a wonderful module called await to JS you just require it to as to and say await to of promise dot resolve which kind of gives you error and result a race right? So it's pretty straightforward. You can do as many awaits you want without putting it in a trycatch block and there is other fantastic module called proximize. So instead of you writing food or then then then chaining all the dense or instead of having await await awaits you could proximize your foo and then say bar bars cues and you will get the value directly. But it is like a simple chaining. It's almost like you're accessing your object properties right? So proximize is one such wonderful tool and if you want to know more such modules you can subscribe to my know more you love the week. So another final gotcha the couple of minutes of gotchas like so you might be wondering if I want to use a sink away today most of you would probably run it through Babel or something right what happens when it transpiles you have a while one right? It is using regenerators and there's a while one running because the browser has not implemented it and it has no other go but rather to implement a state machine in itself and the loop keeps running. So to mitigate this there is this wonderful plugin called it's experimental I think the PR is approved but not yet merged. It says like but you can still use it. It's Babel plugin async to promise. If you see here on the left you have your async function on the left on the right is the transpiled data right? So it looks as good as having promises unlike compared to the previous one you had a while one with regenerators and things. The other thing the the VA team is working on is when there's an error they've made it better today as of today on node soon to know where exactly the error happened previously. If there is an error that was thrown it would it would just say d8 1 colon 44 and you have to figure out where the error was thrown but now it's improved and it says like async promise all and that's where exactly the error got thrown right? And Benedict posted this last night. It's it's the benchmarks for you know async await and parallel promises so you can you can see it for yourself on version 8.72. That's how fast it is. If you are not into real micro level optimization this is perfectly good to use. And here is the last fun thing that you can do if you are if you are on VS code you could enable this by enabling the even for type script and for JavaScript you could convert a block of code which uses promise to a sink of it. You saw that? Yeah, so you can just highlight the block refactor it all your promises one shot into a sink of it. You could probably get bonus points using this plugin and say like hey I wrote the entire project with a sink of it like kudos to me. And support on browsers. These are the supports and browser. And if you're on node you're like really good if you're you're like good if you're on seven and above eight you're really good if you're on 12 you're like a hundred percent like all the sink of it features are there. That's it. You can tweet me on new month. Catch me on incident.com. Hope you liked it. Thank you guys. We can take some questions without a time but maybe a couple of them. Sorry for one announcement. Tomorrow make sure you get your badges because they're not going to be reprinted. So get those and also the feedback form that have been given to you. Can you drop them? There's a box outside. They're laid out in trays near the alleys over here and there. Please pick up one on your way. And we really appreciate your feedback. Let's keep the questions. Hey, hey. Lovely presentation. Thank you. So my question is you said that Coa started off with generators and then sort of went back or settled on a sink of it. So in your general work in a day to day work, what is your your comparison between generators and a sink of it? For example, if you're using Redux Saga, it's very much uses generators today, right? So do you see generators as the next step or kind of a too much of a step? It would be more like a parallel track. It's not like a next step because both of them are like side by side. It's on your description whether you're taking for generators like you could do an yield star with generator, but you can't do an like await all or await star. It doesn't make sense, right? So if you're using a lot of iterators and you have to do a lot of next calls, generator would be a good use case. Like for example, I wrote this blog post where I'm traversing trees with generators, which is a simple thing, but we generated it. It looks even more intuitive to traverse a tree. So if your use case involves something where generator is beneficial, it is better to use. But I think of it as a way to go. It's kind of it went through a lot of churning and it's kind of complete. Now there's like nothing much to add or remove from it. So I think it is a safe bet. Thanks. Amen. So when you talked about await all, which basically just wraps a promise dot all. What benefit do I get out of that? Like if I had multiple promises and I passed promises to a promise dot all and I wrapped that same thing to an await all, what benefit do I get out of that? No, rather than having a promise dot all everywhere, I thought it's a pattern to just have an all there at the beginning and then you could pass individual promises or set of promises and then spread it out. Okay. Yeah, kind of makes sense. Thank you guys.


This time we'll work backwards. We'll start with these four numbers in one's complement format and show what they look like in decimal. So my first number is 27 in hexadecimal, which looks like that in binary. The leading bit is a zero, so this is a positive number. That means I can just read off the bits as is, and that will be the magnitude of my number. So I have a 32 plus 7 gives me 39, and as mentioned, it's a positive number. So 27 in hexadecimal corresponds to 39 in decimal in the one's complement format. Second number is FFDA, which looks like that in binary. Now in this case, my leading bit is a one, so this is a negative number. That means that I can't just read off the bits and be done. I actually have to apply the one's complement operation to convert this back into a positive number so I can read the magnitude. The one's complement operation says to flip all of the bits. So I can read this as being a negative number now. Now I have 32 plus 5. This gives me 37 in decimal, and this is a negative number. So FFDA corresponds to negative 37 in decimal. Our third example is one C. This time, our leading bit is a zero. That means this is a positive number and we can just read off the bits. So I have a 16 plus 8 is 24 plus 4 is 28. So one C corresponds to positive 28 in decimal. Our last example is FFC3, which looks like this in binary. And because the leading bit is a one, I've got a negative number. I'll need to apply the one's complement operation so that I get something I can read. Now I just need to add up the value of these four bits and I'll know the magnitude. 32 plus 16 gives me 48 plus 8 is 56 plus 4 is 60. And remember, this is a negative number. So FFC3 corresponds to negative 60 in binary.