| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 | 
							- <html>
 
- 	<head>
 
- 		<title>Jasmine - Unit Testing</title>
 
- 		<link href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" rel="stylesheet" type="text/css" />
 
- 		<link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" rel="stylesheet" type="text/css" />
 
- 		<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript"></script>
 
- 		<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js" type="text/javascript"></script>
 
- 		<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js" type="text/javascript"></script>
 
- 		<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js" type="text/javascript"></script>
 
- 		<style type="text/css">
 
- 			.new-page {page-break-before: always;}
 
- 		</style>
 
- 	</head>
 
- 	<body>
 
- 	<h2>I. Introduction:</h2>
 
- 	<p>In this tutorial we will take an existing Ext application and introduce the Jasmine assertion library for unit
 
- 		testing. Readers must be familiar with JavaScript, ExtJS 4, the MVC architecture as well as the fundamentals of
 
- 		HTML, CSS, and using resources.</p>
 
- 		<p><b>Why Test?</b>
 
- 		There are many reasons to test applications. Tests can verify an application's functionality to eliminate the
 
- 			need to enumerate all the use cases manually. Also, if the application were to be refactored, or updated,
 
- 			the tests could verify that the changes did not introduce new bugs into the system</p>
 
- 	<h2>II. Getting started.</h2>
 
- 	<p>For this tutorial, use the "simple" example of the MVC in the ExtJS bundle — found under
 
- 		<ext>/examples/app/simple. Copy the simple folder to your workspace or desktop.</p>
 
- 	<p>Add these folders:</p>
 
- 	<pre class="brush: bash shell; toolbar: false; gutter: false">
 
- 		<simple dir>/app-test
 
- 		<simple dir>/app-test/specs</pre>
 
- 	<p>Download and extract the Jasmine standalone library into the app-test folder.
 
- 		<a href="http://pivotal.github.com/jasmine/download.html">Link</a></p>
 
- 	<p>Create these files (leave them empty for now, you will fill them in next)</p>
 
- 	<pre class="brush: bash shell; toolbar: false; gutter: false">
 
- 		<simple dir>/app-test.js
 
- 		<simple dir>/run-tests.html</pre>
 
- 	<p>Your project should look like this now:</p>
 
- 	<img src="folder.jpg"/>
 
- 	<p class="new-page">Now that you have the files and folders setup, fill in the test-running environment. Open the run-tests.html
 
- 		and put the following markup into it:</p>
 
- 	<pre class="brush: xml; toolbar: false; gutter: false;">
 
- <html>
 
- <head>
 
- 	<title id="page-title">Tester</title>
 
- 	<link rel="stylesheet" type="text/css" href="app-test/lib/jasmine-1.1.0/jasmine.css">
 
- 	
 
- 	<script type="text/javascript" src="extjs/ext-debug.js"></script>
 
- 	<script type="text/javascript" src="app-test/lib/jasmine-1.1.0/jasmine.js"></script>
 
- 	<script type="text/javascript" src="app-test/lib/jasmine-1.1.0/jasmine-html.js"></script>
 
- 	<!-- include specs here -->
 
- 	<!-- test launcher -->
 
- 	<script type="text/javascript" src="app-test.js"></script>
 
- </head>
 
- <body>
 
- </body>
 
- </html></pre>
 
- 	<p>There are a few key things to remember here: the jasmine resources, the ext framework resource and app-test.js.
 
- 		These will need to be included with your tests (this order is important). You will include the specs
 
- 		(jasmine assertion js files) above the app-test.js and below the rest of the files.</p>
 
- 	<p>Next, open app-test.js and copy this code into it:</p>
 
- 	<pre class="brush: js; toolbar: false; gutter: false;">
 
- Ext.require('Ext.app.Application');
 
- var APPLICATION = null;
 
- Ext.onReady(function() {
 
- 	APPLICATION = Ext.create('Ext.app.Application', {
 
- 		name: 'AM',
 
- 		controllers: [
 
- 			'Users'
 
- 		],
 
- 		launch: function() {
 
- 			//include the tests in the test.html head
 
- 			jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
 
- 			jasmine.getEnv().execute();
 
- 		}
 
- 	});
 
- });</pre>
 
- 	<p>The effect of the above code is a global reference to the <i>Application</i> instance and bootstrap for the 
 
- 		jasmine assertion library. This is accomplished by directly constructing the <i>Application</i> object and 
 
- 		storing the reference when the document is ready, bypassing the Ext.application() method.</p>
 
- 	<p><b>Note:</b> this <i>Application</i> definition is not a copy and paste of your regular <i>Application</i>
 
- 		definition in your app.js. This version will only include the controllers, stores, models, etc and when
 
- 		<i>launch</i> is called it will invoke the Jasmine tests.</p>
 
- 	<p>Now should you have a working test environment.</p>
 
- 	<h2>III. Writing Tests.</h2>
 
- 	<p>Under the specs folder (<simple>/app-test/specs) create two empty text files named:</p>
 
- 	<pre class="brush: bash shell; toolbar: false; gutter: false;">
 
- 		example.spec.js
 
- 		users.spec.js</pre>
 
- 	<p>Then go back to the <i>run-tests.html</i> file and add these two lines under the comment <i>"<!-- include
 
- 		specs here -->"</i></p>
 
- 	<pre class="brush: xml; first-line: 12; toolbar: false; gutter: false"><!-- include specs here -->
 
- <script type="text/javascript" src="app-test/specs/example.spec.js"></script>
 
- <script type="text/javascript" src="app-test/specs/users.spec.js"></script></pre>
 
- 	<p><b>Note:</b> You may have noticed a pattern in the file names. Although, not required, its nice to indicate what
 
- 		the file is for. (in this case the double extension of *.spec.js)</p>
 
- 	<p>Start by filling in example.spec.js.  Jasmine's specification syntax is very descriptive. Each suite of tests is
 
- 		contained in a describe function, and each test is defined by an "it" function.</p>
 
- 	<p>Example:</p>
 
- 	<pre class="brush: js; toolbar: false; gutter: false">
 
- describe("Basic Assumptions", function() {
 
- 	it("has ExtJS4 loaded", function() {
 
- 		expect(Ext).toBeDefined();
 
- 		expect(Ext.getVersion()).toBeTruthy();
 
- 		expect(Ext.getVersion().major).toEqual(4);
 
- 	});
 
- 	it("has loaded AM code",function(){
 
- 		expect(AM).toBeDefined();
 
- 	});
 
- });</pre>
 
- 	<p>To pass a test (each "it" block) simply call <i>expect(someValue).toBe<something>()</i></p>
 
- 	<p class="new-page">Next a more complicated example. Testing a store, which is asynchronous, and retrieved from a Controller. (This
 
- 		is where that global application reference will come in handy)</p>
 
- 	<pre class="brush: js; toolbar: false; gutter: false">
 
- describe("Users", function() {
 
- 	var store = null, ctlr = null;
 
- 	beforeEach(function(){
 
- 		if(!ctlr) ctlr = APPLICATION.getController('Users');
 
- 		if(!store) store = ctlr.getStore('Users');
 
- 		expect(store).toBeTruthy();
 
- 		waitsFor(
 
- 			function(){ return !store.isLoading(); },
 
- 			"load never completed",
 
- 			4000
 
- 		);
 
- 	});
 
- 	it("should have users",function(){
 
- 		expect(store.getCount()).toBeGreaterThan(1);
 
- 	});
 
- 	it("should add and be able to get", function(){
 
- 		store.add(Ext.create('AM.model.User', {
 
- 			name: "John Doe",
 
- 			email: "john.doe@anon.net"
 
- 		}));
 
- 		var user = store.findRecord('name', 'John Doe');
 
- 		expect(user).toBeTruthy();
 
- 		expect(user.get('email')).toBe('john.doe@anon.net');
 
- 	});
 
- 	it("should open the editor window", function(){
 
- 		var grid = Ext.ComponentQuery.query('userlist')[0];
 
- 		ctlr.editUser(grid,store.getAt(0));
 
- 		var edit = Ext.ComponentQuery.query('useredit')[0];
 
- 		expect(edit).toBeTruthy();
 
- 		if(edit)edit.destroy();
 
- 	});
 
- });</pre>
 
- 	<p class="new-page">Notice the "beforeEach" function (this will be called before each "it"). This function sets
 
- 		up the stage for each test, and this example:
 
- 		<ol>
 
- 			<li>gets a <i>Store</i> from a <i>Controller</i></li>
 
- 			<li>asserts that the store was successfully retrieved (not null or undefined)</li>
 
- 			<li>waits for the store to complete loading — see the "waitFor" function — This store
 
- 				auto loads data when its constructed: do not run tests before its ready.</li>
 
- 		</ol>
 
- 	</p>
 
- 	<h2>IV. Automatting.</h2>
 
- 	<p>Combining this with PhantomJS allows us to run these tests from the command line or from a cron job. The provided
 
- 		<i>run-jasmine.js</i> in the PhantomJS distribution is all that is needed. (you can tweak it to make the output suit
 
- 		your needs, <a href="run-jasmine.js">here</a> is an example tweaked version )</p>
 
- 	<p>Example command line:</p>
 
- 	<pre class="brush: bash shell; toolbar: false; gutter: false">phantomjs run-jasmine.js http://localhost/app/run-tests.html</pre>
 
- 	<p>You will need to run the tests from a web server because XHR's cannot be made from the file:// protocol</p>
 
- 	<p><b>About the Author:</b>
 
- 	<a href="http://jonathangrimes.com">Jonathan Grimes</a> (<a href="http://www.facebook.com/jonathan.grimes">FB</a>,<a href="http://twitter.com/jsg2021">Tw</a>,<a href="https://plus.google.com/u/0/102578638400305127370/about">G+</a>) is a software engineer at <a href="http://nextthought.com">NextThought</a>, a technology start-up company that is currently building an integrated platform for online education. </p>
 
- 		
 
- 	<script type="text/javascript"> SyntaxHighlighter.all() </script>
 
- </body>
 
- </html>
 
 
  |