Lightning Testing Service
Need for Lightning Testing Service
In the 4th slide, I have explained about the need of Lightning Testing Service. However, the most important point that I believe why Lightning Testing Service will be important in future is that with the introduction to Lightning, we started keeping most of the data at client side i.e. in our browsers in javascript objects. As we already know that making test classes of our Apex code is important to deploy our code to production environment but as of now, there are no official guidelines by Salesforce to test your client side lightning components too but this can be implemented in future.Jasmine and Mocha - Testing Frameworks
Live Demo - Lightning Testing Service
Installing LTS
LTS - Basics
To get started, open my repository and move to the boilerplate branch. There you'll see that in the src folder, we have aura and static resources folder. In Lightning Testing Service, our all test functions reside in the static resources. So, if you see the static resources folder, it consists of a number of files with .resource extension and all of these consists of javascript methods that are used for testing our lightning components. If you observe carefully, you'll see that except ltsDemoTests.resource, all the other resource files are already present in your org as the come with the LTS Package and test the lightning components that are in the package itself.
Now, I have test methods as well as I have lightning components to test but where should I see the test result ? It's time to move on to the aura folder where you'll see 4 subfolders out of which jasmineTests and lts_jasmineRunner folders should be present in your org as they are a part of the package. jasmineTests is basically the application which you can launch and see the results of all the tests on our components. The code for jasmineTests.app is as shown below:-
<aura:application > <c:lts_jasmineRunner testFiles="{!join(',', $Resource.jasmineHelloWorldTests, $Resource.jasmineExampleTests, $Resource.jasmineLightningDataServiceTests )}" /> </aura:application>So, as you can see above, this application is calling ltsJasmineRunner component and passing all the test files in a single attribute. These test files are actually present in the static resources as we have already seen. Considering the ltsJasmineRunner.cmp, it is developed by salesforce so that it'll show the test results by executing them. We won't go in deep for this as we'll be using this to see the test results only, we'll not be doing any modifications in the code or anything else.
Rest we have in our aura folder:- ltsComp that we'll be building, initially it only consists of a simple heading and an empty controller + helper too and secondly we have ltsDemo app which we'll be using to see our component as we work on it it is just calling ltsComp and doing nothing else.
<aura:component > <h1>Basic Component for Lightning Testing Service</h1> </aura:component>You can have a look at the ltsComp component above. It's just having an h1 tag initially. If you remember we have made a separate tests file named ltsDemoTests.resource in our static resources which consists of this as given below:-
describe("LTS Demo Test 1 will always pass", function() { it("True is always true", function() { expect(true).toBe(true); }); });So, as you can see above, it is having a describe function which is used to group related specs. A spec is basically a test case which is defined by calling the global jasmine function it. Spec and define both are functions with a string as the first parameter (can be a heading of that spec normally) and a function as a second parameter. The second parameter in describe i.e. function consists of a number of specs defined by it and the second parameter in spec i.e. function consists of a number of expectations which are built by the function expect that takes an expected value and an actual value in to be. A spec with all true expectation is a passing spec whereas a spec with one or more false expectations is a failing spec. The above expect function has true in it's parameter as well as in toBe parameter so it will always pass. and you'll see both statements. Change the second true to false and give it a try..!!
That's all in basics of Jasmine. You can move to part 1, part 2, part 3 branch of the repository in the respective order and see the change in code. When you'll move to part 1 you'll notice that in jasmineTests.app, only our ltsDemoTests resource file is called that consists of test cases defined by us as given below:-
<aura:application > <c:lts_jasmineRunner testFiles="{!join(',', $Resource.ltsDemoTests )}" /> </aura:application>You'll also notice a change in ltsComp.cmp as you can see below:-
<aura:component > <h1>Basic Component for Lightning Testing Service</h1> <aura:attribute name="myName" type="String"></aura:attribute> <aura:handler name="init" value="{!this}" action="{!c.doInit}" ></aura:handler> {!v.myName} </aura:component>and in ltsCompController.js also:-
({ doInit: function(component, event, helper) { component.set('v.myName', 'Rahul Malhotra'); } })And finally, a change in ltsDemoTests.resource too.
describe("LTS Demo Test 1will always pass", function() { it("True is always true", function() { expect(true).toBe(true); }); }); describe("Lightning Component Testing Examples", function() { afterEach(function() { $T.clearRenderedTestComponents(); }); describe('Rendering c:ltsComp', function(){ it('String contains text', function(done) { $T.createComponent("c:ltsComp", {}, true) .then(function(component) { expect(component.get('v.myName')).toContain("Rahul"); done(); }).catch(function(e) { done.fail(e); }); }); }); });As you move through part 2 and part 3 also, you can see changes in component i.e. ltsComp.cmp and ltsDemoTests.resource as I'll be adding more and more test cases you can execute those tests and view result in jasmineTests.app, one extra part i.e. LTSDemoCtrl apex class will be added in part3. However the changes in the component itself can be viewed in ltsDemo.app
In the above code, we are checking whether the name in our attribute is changed or not as we are doing this in init handler which is called as our component is initialized. You can move to part 2 and part 3 branches yourself and see what's added in here. However if you want a detailed explanation for part 2 and part 3 code too. Let me know in comments and I'll add a video of the same if required. I hope you liked this blog.
The final output when you have reached code to part 3 will be as follows:-
Sharing a picture of my session below, hope to see you in the next one too.
Happy Trailblazing..!!
This comment has been removed by a blog administrator.
ReplyDeletePlease don't spam. I am going to delete this right now
DeleteThis comment has been removed by a blog administrator.
ReplyDeleteKristen, please don't spam. I am going to delete this right now
DeleteThis comment has been removed by a blog administrator.
ReplyDeleteI am really tired of spam comments now
Delete