{"id":391,"date":"2016-09-23T20:04:00","date_gmt":"2016-09-23T20:04:00","guid":{"rendered":"http:\/\/fluentreports.com\/blog\/?p=391"},"modified":"2016-10-13T20:44:37","modified_gmt":"2016-10-13T20:44:37","slug":"nativescript-testing-unit-testing","status":"publish","type":"post","link":"http:\/\/fluentreports.com\/blog\/?p=391","title":{"rendered":"NativeScript Testing: Unit Testing"},"content":{"rendered":"<p><a href=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/ns-road-signs.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-393 aligncenter\" src=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/ns-road-signs.png\" alt=\"ns-road-signs\" width=\"1920\" height=\"1357\" srcset=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/ns-road-signs.png 1920w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/ns-road-signs-300x212.png 300w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/ns-road-signs-768x543.png 768w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/ns-road-signs-1024x724.png 1024w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/ns-road-signs-624x441.png 624w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/a>I got to give a talk on NativeScript testing to a great group of people at NativeScript Developer Days.\u00a0 <a href=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/20160920_190247.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-387 alignright\" src=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/20160920_190247.jpg\" alt=\"20160920_190247\" width=\"270\" height=\"152\" srcset=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/20160920_190247.jpg 5312w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/20160920_190247-300x169.jpg 300w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/20160920_190247-768x432.jpg 768w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/20160920_190247-1024x576.jpg 1024w, http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/20160920_190247-624x351.jpg 624w\" sizes=\"auto, (max-width: 270px) 100vw, 270px\" \/><\/a>Despite my silly technical problems at the beginning, we managed to get back on track and I was able to present all the critical information that was needed to get everyone up and running.\u00a0 I did manage to miss my last slide; so I will make sure to have all that information at the end of this post.<\/p>\n<p>For those who are interested in doing testing and weren't there; or those who were in the talk, and just want to get a quick refresh, or if you just prefer the information written down; then this set of blog posts is for you.\u00a0\u00a0 I plan on doing a multi-part series on this as I want to cover what I did in my talk in the first two blog posts; but then expand the series to show Angular Native unit testing, how to unit test controls, and how to write unit tests for the NativeScript core.<\/p>\n<p>You can view the #NSDevDay video <a href=\"https:\/\/www.youtube.com\/watch?v=tu5h2NxTzIo\">here .<\/a>\u00a0 You can download my slide deck from the talk <a href=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/NativeScript-Testing.pdf\">here<\/a>.\u00a0 And you can download the entire app that I wrote for my talk, including all the tests from <a href=\"https:\/\/github.com\/NathanaelA\/carder\">here<\/a>.<\/p>\n<p>The posts currently planned in this series are:<\/p>\n<ul>\n<li><a href=\"http:\/\/fluentreports.com\/blog\/?p=391\">Unit Testing with Mocha <\/a><\/li>\n<li><a href=\"http:\/\/fluentreports.com\/blog\/?p=396\">End to End Testing with Appium<\/a><\/li>\n<li>Unit Testing with Angular Native (Part 1)<\/li>\n<li>Unit Testing with Angular 2 (Part 2)<\/li>\n<li>Unit Testing Visual Controls<\/li>\n<li>Writing NativeScript Core unit testing<\/li>\n<\/ul>\n<h2>Unit Testing<\/h2>\n<p>So our first type of testing we will discuss is <strong>Unit testing<\/strong>.\u00a0\u00a0 Unit testing, for those of you that are un-aware of what it is -- it allows you to take a part of your code (typically a class or module) and you test it.\u00a0 The best way is to treat it like a black box.\u00a0 You don't care how it is implemented internally; you only care about the interface it exposes (i.e. inputs and the results).\u00a0 By treating it as a black box; this allows you to re-implement\/rewrite\/refactor\/fix it or do any other internal things to the class without the rest of your real or test code caring about the actual internal implementation.\u00a0 Because your class is self contained it makes your code a lot more de-coupled and stand alone.\u00a0 This typically means the code is better engineered and more maintainable.\u00a0 In a nutshell, unit testing, is basically throwing as many different types of inputs and then verifying all the outputs and\/or execution of your class is correct.<\/p>\n<p>Now some people like to develop the tests before the code; this way they think of the scenarios that they need to handle; create all the tests (which of course at this point will all fail) and then implement the code.\u00a0\u00a0 Others build the code and build the tests along side the code, or build them after the code is complete.\u00a0\u00a0 There are pro's and con's for all sides; and that is really a whole different blog post. \u00a0 In my opinion it is better to just make sure you do it; not the when of doing it.\u00a0 One other recommendation is that when you get a bug report; you write a test for it. This way once you fix it; then in the future that specific bug will never happen again as your tests will always be checking for it.\u00a0 Remember the idea is to test for everything you can think of, if a bug slipped through -- that means you failed to test everything and so by adding those \"bug\" tests, now hopefully you are actually testing everything the class can do...<\/p>\n<p>The really cool thing is NativeScript actually has built in unit testing.\u00a0\u00a0 The neat thing about the built in unit testing, is it actually runs fully inside your NativeScript application.\u00a0\u00a0 This allows you to test anything that you have in your application including any added plugins, or custom code.\u00a0\u00a0 To install it, you just do <strong>tns test init<\/strong>.\u00a0 This will ask you which testing framework to use and will install it.\u00a0\u00a0 I prefer using <em>Mocha<\/em>, and so the tests examples will all be mocha based; but again the framework you use is your choice.\u00a0\u00a0 One thing to note is that the assert functionality is actually provided by the <em>Chia<\/em> library in each of the testing frameworks supported by NativeScript.\u00a0 If you really prefer a different assert library there are ways you can change it, but that is out side of the scope of this blog post.<\/p>\n<p>For all your unit tests in NativeScript, they are all located in the <em><strong>\/app\/tests<\/strong><\/em> folder.\u00a0 To then run all your cool tests\u00a0 you will type <strong>tns test android<\/strong> or <strong>tns test ios<\/strong>.\u00a0 TNS will then build your app and launch it in test mode.\u00a0\u00a0 Once each test completes; your console will tell you which tests passed\/failed and then finally how many passed\/failed like this.<br \/>\n<pre>NativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 0 of 6 SUCCESS (0 secs \/ 0 secs)\nNativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 1 of 6 SUCCESS (0 secs \/ 0.005 secs)\nNativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 2 of 6 SUCCESS (0 secs \/ 0.007 secs)\nNativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 3 of 6 SUCCESS (0 secs \/ 0.008 secs)\nNativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 4 of 6 SUCCESS (0 secs \/ 0.009 secs)\nNativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 5 of 6 SUCCESS (0 secs \/ 0.083 secs)\nNativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 6 of 6 SUCCESS (0 secs \/ 0.085 secs)\nNativeScript \/ 19 (4.4.4; Samsung Galaxy S5 - 4.4.4 - API 19): Executed 6 of 6 SUCCESS (0.217 secs \/ 0.089 secs<\/pre><br \/>\nLets get to the actual creating of tests in Mocha.\u00a0 In my sample <a href=\"https:\/\/github.com\/NathanaelA\/carder\">carder <\/a>app; I provided a sample test file. So lets look at the unit test file I provided. The file is located <a href=\"https:\/\/github.com\/NathanaelA\/carder\/blob\/master\/app\/tests\/carderUnitTest.js\">\/app\/test\/carderUnitTest.js<\/a>.\u00a0 The first thing you will see is that I include the class I plan on testing.<\/p>\n<p><strong>var cards = require('..\/cards.js');<\/strong><\/p>\n<p>Pretty hard to test it, without requiring it.\u00a0\u00a0 So in case it isn't obvious you still need to require the file(s) that contain any plugins\/classes\/module you need to test.<\/p>\n<p>Then the next part of the code you will see is;<br \/>\n<pre>describe(&#039;Cards&#039;, function() {\n\u00a0\u00a0 \u00a0describe(&quot;current card&quot;, function() { \n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0it (&#039;should return ace of spades&#039;, function() {<\/pre><br \/>\nThe first line of this, we use the <strong>describe<\/strong> command to give the test a name, this allows you to know which test group passed or failed.\u00a0 You can also nest <strong>describe<\/strong>'s inside of <strong>describe'<\/strong>s to allow you to have sub-groups of tests.\u00a0\u00a0 Finally you will see the <em><strong>it<\/strong><\/em> command, which is the actual test. You can have as many <em><strong>it<\/strong><\/em>'s as you need in a group to test the full functionality.\u00a0 So walking specifically through this test; we are saying the main test group is <strong><em>Cards<\/em> <\/strong>(I name it after the class I'm testing); the following <strong>describe<\/strong> is I'm testing functionality I'm testing the <strong><em>current card<\/em><\/strong> function; and finally what my expectation of my test, which in this case is that it should return ace of spade card.<\/p>\n<p>Then next we add our add my actual test code;<br \/>\n<pre>\/\/ Reset Card deck to known state\ncards.resetDeck();\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\n\/\/ The get &quot;Current Card&quot; function\nvar result = cards.getCurrentCard();\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\n\/\/ My Expectations, that it should be\n\/\/ a Ace of Spades on a reset card deck\nassert.equal(result.suit, &quot;Spade&quot;); \nassert.equal(result.value, &quot;Ace&quot;);<\/pre><br \/>\nIf either of the last two lines are false, then the test will fail and it will then mark this test as a failure in the log.<\/p>\n<p>As you can see creating this test was fairly simple; Reset deck, grab the card and then verify it.\u00a0 If you scroll down in the test file to the end of it; you will see the <strong>random cards<\/strong> test.\u00a0 As you can see that test is a bit more complex.\u00a0 Your tests can be as simple or complex as you need.\u00a0 Typically the simpler your tests are the better, as then it is less likely that your test is actually the broken part of the code if it fails.<\/p>\n<p>One other feature of Mocha is you can actually do ASYNC tests; so if your code is promise or callback based; you can also test it.\u00a0 By doing this:<br \/>\n<pre>it (&quot;Test promise&quot;, function(done) {\n\u00a0 call().some().cool().func()\n&nbsp;&nbsp;.then(done).catch(function() { done(false); });\n});\n\n\/\/ or\n\nit (&quot;test callback&quot;, function(done) {\n\u00a0 someFunc(function(err, results) {\n\u00a0\u00a0\u00a0\u00a0 if (results) done()\n\u00a0\u00a0 \u00a0 else done(false);\n\u00a0 }\n});<\/pre><br \/>\nNotice in the <strong><em>it<\/em> <\/strong>function, it has a <em><strong>done<\/strong><\/em> parameter now.\u00a0 The done() function is passed in for you to call when the async code has completed.\u00a0 The mocha unit test detects if you tell it to have a done parameter and will switch that test to be fully async.<\/p>\n<p>Note: If you are using my <a href=\"https:\/\/github.com\/NathanaelA\/NativeScript-LiveEdit\">NativeScript-LiveEdit<\/a> plugin, the watcher has had the ability to start these tests instantly on Android (Without having to use the slow `tns test android` command) for quite some time.\u00a0 So anytime you change any of the \/app\/tests\/ files; it will automatically launch the tests and you will see the results almost immediately.\u00a0 However, I have recently added a couple new features to the watcher; you can hit inside the watcher window a \"<strong>t<\/strong>\" to start testing immediately; or the \"<strong>m<\/strong>\" to switch modes (i.e. default-auto-test, always test, and never test), and the \"<strong>n<\/strong>\" to force it to launch the app in normal mode.<\/p>\n<p>Now all of this can be totally automated and it is highly recommended to be completely automated in something like local git hooks or some CI environment so that when you commit a change the unit tests are done.\u00a0 The sooner your tests run the quicker you find any breaking code after you make any changes.\u00a0 It is always very re-assuring when you have to fix a bug in your class and then\u00a0 re-run your tests and everything passes...<\/p>\n<p>Depending on your CI environment and how frequently you commit, you might consider having the heavier tests run once every three commits or based on a keyword put in the commit or in a issue tracking system.\u00a0 Again, the idea is the more tests you can do and the more testing coverage you have the better off you are.<\/p>\n<p>If you need help setting up a automatic testing and\/or CI environment or you would like some training, please <a href=\"http:\/\/master-technology.com\/contact.php\">contact me<\/a>.<\/p>\n<p>Resources:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=tu5h2NxTzIo\">Talk Video<\/a><\/li>\n<li><a href=\"http:\/\/fluentreports.com\/blog\/wp-content\/uploads\/2016\/09\/NativeScript-Testing.pdf\">Talk Slides<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/NathanaelA\/carder\">Carder Example App<\/a><\/li>\n<li><a href=\"http:\/\/docs.nativescript.org\/tooling\/testing\">NativeScript Unit Testing docs<\/a><\/li>\n<li><a href=\"https:\/\/mochajs.org\/\">Mocha Testing Framework<\/a><\/li>\n<li><a href=\"http:\/\/chaijs.com\/api\/assert\/\">Chia Assert Library<\/a><\/li>\n<li><a href=\"http:\/\/appium.io\/\">Appium <\/a><\/li>\n<li><a href=\"https:\/\/github.com\/admc\/wd\">Appium Web\/Mobile Driver<\/a><\/li>\n<li><a href=\"http:\/\/nativescript.tools\/product\/8\">My Book - More Testing Info<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>I got to give a talk on NativeScript testing to a great group of people at NativeScript Developer Days.\u00a0 Despite my silly technical problems at the beginning, we managed to get back on track and I was able to present all the critical information that was needed to get everyone up and running.\u00a0 I did&hellip; <a class=\"more-link\" href=\"http:\/\/fluentreports.com\/blog\/?p=391\">Continue reading <span class=\"screen-reader-text\">NativeScript Testing: Unit Testing<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":""},"categories":[15,82],"tags":[16,83],"class_list":["post-391","post","type-post","status-publish","format-standard","hentry","category-nativescript","category-testing","tag-nativescript","tag-testing","entry"],"_links":{"self":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=391"}],"version-history":[{"count":4,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/391\/revisions"}],"predecessor-version":[{"id":409,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/391\/revisions\/409"}],"wp:attachment":[{"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=391"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/fluentreports.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}