Näytetään tekstit, joissa on tunniste unit testing. Näytä kaikki tekstit
Näytetään tekstit, joissa on tunniste unit testing. Näytä kaikki tekstit

24 marraskuuta, 2014

Osa 3. Unit testausta JavaScript 'strict mode'

Unit testing

Global on nyt undefined

Kun aloitat koodaamaan 'strict mode'ssa, olet varmaankin aloittamassa projektia aivan alusta, kesken ei kannata yrittää. Strict modessa on täysin uudet säännöt. Ensimmäiseksi esimerkiksi vaikkapa tämä: funktion this muuttuja ei enää sisällä global objektia [window object], vaan se on undefined. Tämä tieto sattumalta mahdollistaa helpon boolean -testin minkä tahansa funktion sisällä, jos this on true, se on global object, ja strict mode ei ole päällä. Jos this on false, eli undefined, strict mode on päällä. 

var varmista = function varmista(testi, msg) { 
     if (!testi) { 
          put("Debug:\n" + msg); 
     };
}; // varmista = itse tehty unit testi

var strictMode = function (){ // palautusarvo Boolean
        return !this;
} // strictMode(); 

varmista (strictMode(), "strict mode: " + strictMode()); 
   // testaa strict mode

Pieni unit test, varmista(), helpottaa testausta, vaikka kesken koodin:

var testi = false; // mikä tahansa boolean -testi
var selkokielinenViesti = "Hei: varmista -testin pitäisi olla true, ei false" 
                        // Kerro tässä mitä olisi pitänyt tapahtua
varmista(testi, selkokielinenViesti);

Kun ajat testin (false) -arvolla, saat ilmoituksen:

Err: 
Error: Debug: Hei: varmista -testin pitäisi olla true, ei false
Url: 
 file:///Users/who/Sites/js/barebones/js/main.js
Line: 21 / 34

Saat tietää paitsi oman viestisi, sen lisäksi: 
1: Virheen tyypin,jos sellainen löytyy. Yleensä vain Error:
2. URL tiedostoon, jossa virhe esiintyy.
3. Millä rivillä ja monennessako kirjaimessa virhe esiintyy.

Jos testi on true, ei tapahdu mitään, kaikki on hyvin ja voit unohtaa koko testin.

On myös mahdollista muutella koodia siten, että erityyppiset virheilmoitukset käsitellään eri tavoin ja vaikkapa kerrotaan laajemmin selkokielellä miten kyseinen virhe voi syntyä, tai annetaan linkkejä materiaaliin, mutta tämän esimerkin tarkoitus on vain päästä alkuun.

Ideaali olisi, että ensin kirjoitat testin ja vasta sitten koodin jota testaat. Jätät testikoodin paikalleen, jotta jos joskus muutat vahingossa jotakin testi heti huomaa muutoksen ja varoittaa ei-toivotuista vaikutuksista. Sillä mitä nopeammin huomaat virheen, sitä nopeammin se on korjattu. Testaa siis kaikki koodi kauttaaltaan koko ajan, korjaat sekunnissa kun saat tiedon heti. Jos törmäät virheeseen joskus myöhemmin, et varmaankaan enää muista miten se on syntynyt ja metsästys voi olla pitkällinen prosessi. Testaa myös jokainen työkalusi, tee huolellinen perusta, jolle voi huoletta rakentaa.

Perusidea: Tutkimusten mukaan vanhaa koodia ei enää kukaan uskalla korjailla. Mutta jos kaikki on testattua, uskallat halutessasi ehkä jopa muokata jotakin vanhaa koodiasi, kun aika koittaa. Ja jonakin päivänä tämäkin projekti on kasvanut liian suureksi.

Kommentoi 'use strict' -ilmoitus pois hetkeksi ja testaa saatko siitä ilmoituksen:
var xyz = function () { 
// 'use strict'; // kääre alkaa ...

Lataa sivu uudelleen. Nyt pitäisi tulle virheilmoituksia. Tarkistele.
Muista palauttaa kommentit sitten takaisin, jotta pääset varsinaiseen työhön.

Näin on testipenkki valmis varsinaiseen koodin vääntöön...

Olisi siis tarkoitus rakentaa minimi -ohjelma ja testailla samalla perus -OOP koodeja.
Ja kyllä, tietysti 'strict mode' päällä.

17 marraskuuta, 2014

Osa 2. JavaScript Testipenkki

JavaScript koodin testipenkki 'strict mode' -testeihin.

Script tagissa on hyvä olla onerror -parametri, joka ilmoittaa jos kooditiedostosi ei lataudu, jos esim: osoite on väärin, tms. Virheitä voi olla vaikea jäljittää, jos tiedosto ei ole edes latautunut. Ulkoinen kooditiedosto on kuitenkin erittäin hyvä tapa, ei siis ollenkaan HTML -koodin sekaan JavaScriptiä, jos suinkin mahdollista ja yleensä on.

<script src="js/main.js" onerror="alert('Load Err: ' + this.src)">

Luo main.js -niminen tekstitiedosto ja siihen koodi:

var xyz = function () { 'use strict'; // this is wrapper start ...
       // Only 'strict mode' -experiments here !
}(); // strict mode wrapper end

Käytä funktiota irroittamaan koodi globaalista.

1. Ensin sulkeet: (); - Irrottaa koodin global -objektista
2. Anonyymi funktio toimii kääreenä

function () {} ();

3. Ensimmäinen asia koodissa on ilmoitus: 'strict mode' -joka kertoo selaimelle, että tähän koodialueeseen on suhtauduttava hiukan tiukemmin, kuin mihin on totuttu. Jos lause tulee vasta funktion sisällä, sen vaikutusalue on vain kyseisen funktion sisäinen, tuolloin globaali objekti koodataan kuten tavallisesti, eli strict mode ei ole silloin voimassa globaalilla alueella.

4. Virheilmoituskoodit on hyvä koodailla nyt saman tien, kun kerran testipenkkiä tehdään:
   - virheilmoitus kertoo miltä riviltä bugi löytyi, joten löydät sen nopeammin.

Lisätään Try - cach() - finally  -alueet:

try {  /*debug area*/
window.onerror=function(msg,Url,Ln,ch){
 alert("Window error:\n" + msg + "\nURL: " + Url + "\nLine: " + Ln+"/"+ch);
};
///// TESTIALUE ALKAA - TÄSTÄ ETEENPÄIN SAA MUOKATA ///////////

// Teretuloa 'strict mode' -kokeilujen kentälle !

var put = function(w) {alert('Viesti: ' + w ); };
put("Heippa Maailma"); // testataan 'put' -funktiota

///// TESTIALUE LOPPUU - ÄLÄ MUOKKAA TÄTÄ ALEMPAA ///////////
 } catch (e) { //Tämä blokki ajetaan jos virhe tapahtuu
        throw e; //window.error() kertoo virheen rivinumeron!
} finally { //Tämä blokki ajetaan joka kerta
//alert("'main.js' sivu on ladattu!"); 
} // try

Siinä. Tämä artikkeli ei vielä mitenkään erityisesti käsitellyt strict modea, mutta siihen tullaan seuraavassa. Tämä oli tärkeää vaihe, niin on jatkossa hiukan helpompaa.

Unit -testaus olisi seuraava vaihe...



25 lokakuuta, 2014

Part 4 Actual app object

How to build minimum JavaScirpt app

First our mini app needs to have private parts encapsulated so that nobody will mess around there.  Second, your app needs to have a public interface for commands so we can use it. We need to do simple model to start, so we can test it first and then we add some functinality piece by piece until it is ready. All this is possible to do with wrapper function. 

Minimum (experimental) app looks like this:

var app = (function () { // app & private area start
var secret,
privateSetter = function (x) {
alert( "validating:" + x);
secret = x;
return true;
}; // private area end
return { // privileged area start
'get': function get () { // getter
return secret;
},
'set': function set (c){ // setter
return privateSetter (c);
}
    }; // privileged area end
} () ) ; // app end

Lets go thru it part by part:

First there is variable app that contains the whole app inside it:
var app = ();

Then there is anonymous wrapper function, with again clauses that will execute it
function (){}()

Inside anonymous app function there is return {}; part which will give us two functions, get and set in an object, only they are visible outside of the object. This leaves everything else in function-object to private variables, so nobody can mess around with their values. Except get and set functions of course, that's why they are called privileged functions. PrivateSetter function will deliver the value to the private variable, so that we have important opportunity to validate it's value first. Now we just say so, actually do validate nothing, but this is the place where it happens someday near future, you know. 

Notice that this function will return true when it is ready and done. We could easily change this so that it would return the old value instead. Or something else, like a length of string or array, or anything else we need, or so that it would not return anything. 

Time to put it into test bench

So build the thing and try in browser if it works. It should.

app.set("This is my App!"); // validating:This is my App!
put(app.get()); // Message: This is my App!

Var secret is safe. If you try to read it straight from variable it will not happen. First write something into secret pocket of app, official way, with set handler.
app.set('ABRAKADABRA'); // validating:ABRAKADABRA

Then try to sneak it out, but without getter -handler.
alert("UGH:" + app.secret); 
// UGH:undefined - Oh, no... can't get it ! It is hidden !

Next  try to overwrite the value without setter -handler:
app.secret = "foo"; // There you have it, try to spell me now you...

And read it back... 
var temp = app.secret = app['secret']; // can try both ways
alert("secret:" + temp); // secret:foo 

/* What, foo?! Did I manage to overwrite it?!  
Ha, who is the man now? Mama, I rule the universe! */

... but then after a while:
/* using official get -handler: */
alert("app.get:"+ app.get()); 
// app.get:ABRAKADABRA   - Oh noooo, you fooled me ! You bastards...

What really happened here was that without the "official" setter handler, you just created (into the app -object) one more public variable with same name (secret) as original private variable, but because they actually are in different scope it is not that harmful at all. Original data was safe all the time in private area of object and if your app will only read it official way, there is no way you can go wrong here. You can store your phone number there and expect nobody to call you for a long time. Bad guys must be more clever to get your precious data now.

This is THE minimum app with JavaScript. Is there something missing?
Could we make some improvements... ? Let me know...

Learn more about strict mode on next lesson.

24 lokakuuta, 2014

Part 3 Testing the WorkBench


Basic testing

Testing if the 'strict mode' is really on:

When in 'strict mode', the value of this inside any function is 'undefined',  not the global (window Object) as it used to be before strict mode. 
This means that we can test if the mode is on easily inside any basic function. 
If this is true (global window object) strict mode is not on. If undefined = false, it is on.
Try following code in your workbench:

var verify = function verify(test, msg) {
    if (!test) { 
       put("Debugger:\n" + msg); 
     }; // if 
}; // verify = self made unit test


var strictMode=function (){ // will return Boolean
        return !this;
} // strictMode(); 


verify(strictMode(), "strict mode: " + strictMode()); 
    // testing strict mode function with unit test


There is small unit test function verify readymade, you can use it like this:

var testCondition = false; // any boolean test here
var messageToUnitTest = "Hello: Unit Test -test" 
  // any message here, just to tell you what is wrong:
verify(testCondition, messageToUnitTest);

You will get alert:

Err: 
Error: Debug: Hello: Unit Test -test
Url: 
 file:///Users/who/Sites/js/barebones/main.js
Line: 21 / 34

Alert will tell you your message, (after the word "Debug:") plus: 
1: Type of the error, if there is one. Usually just Error:
2. URL of the file where the code is hidden.
3. Where, on which line / character the error happens

If test is ok, unit test will not say or do anything, it will be happy and you can forget it. Usually this is what to expect. No windows popping all the time, only if something is wrong.

Leave many lines of
verify(testCondition, messageToUnitTest);
into your code, and if something unexpected happens, you know that one of them will warn you. For example if strict mode is not on anymore, that line will save you immediately and you don't have to wonder hours when something just isn't the way it should be... but what...

This is the way to go. First make a test, then make actual code and you will have tested code all over the place. If you then go and change the old code, your tests will run and hopefully notice if something nasty is about to happen. You shall notice it right away on the spot, and so you can fix it in seconds, not next week or someday.

You should also test that your testbench -functions work properly. Spend time in basics and make them the foundation of everything else.

Try. Let's comment the 'strict' - text out for a moment, like this:

var xyz = function () { 
// 'use strict'; // this is wrapper start ...

Now you should see some warnings concerning about 

  Err: 'strict mode': false... 

Go ahead and check it out, just remember to remove the comments back after testing...
Now we have testbench to code, we can start.

Next page is about building the minimum app and some 
basics of OOP JavaScript in strict mode. Nervous? Now the real thing starts!

22 lokakuuta, 2014

Part 2 JS Workbench

Workbench for JavaScript coding in 'strict mode'

How to start coding in strict mode JavaScript. In 'strict mode' there is very much different rules than "normal" JavaScript. But it is worth of effort to learn new skills right now, especially if you just started to learn JavaScript. Always good to have external script file, do not code in HTML document at all, if you can. Make sure you have this kind of script tag in your HTML5 document:

<script src="js/main.js" onerror="alert('Load Err: ' + this.src)">

There is special onerror -handler that shall reveal if problem is already in the file load, or url of the file. You can't find the error from the file if it is not even loaded. Next, make a "main.js" -file into folder named "js" and start writing some JavaScript in it, like this example. First line is always this, and last line is always that (3rd line).

var xyz = function () { 'use strict'; // this is wrapper start ...
       // Only 'strict mode' -experiments here !
}(); // strict mode wrapper end

This is a recommendation: Use "function format" of 'use strict' -sentence.

1. First there is there clauses: (); - So everything is isolated from global window object. 

2. Anonymous function is next and with extra clauses it is runned into memory. 
This is a wrapper for our app.

function () {} ();

3. Next big thing, and first thing in actual code block is the 'strict mode' -message that tells the browser to be strict with everything. If you put 'strict mode' -message only inside of functions, all global area will not be in 'strict mode'. 
This is the best practise nowadays, as far as I know.

4. Next put some error codes to help with finding where the errors are hiding: 
Those alert -messages can be changed to use anything to get the messages into your debugger, if you use one.

Adding Try - cach() - finally - blocks to catch some error messages.

try {  /*debug area*/
window.onerror=function(msg,Url,Ln,ch){
alert("Window error:\n" + msg + "\nURL: " + Url + "\nLine: " + Ln+"/"+ch);
};
///////////// TEST AREA START - DO NOT EDIT BEFORE THIS ///////////

// Only 'strict mode' -experiments here !

var put = function(w) {alert('Message: ' + w ); };
put("Hello World"); // Testing 'put' -function

///////////// TEST AREA END - DO NOT EDIT AFTER THIS ///////////
 } catch (e) { //This is runned only if some error has been thrown
        throw e; //Sending error to window.onerror -handler for line number.
} finally { //This block is runned every time.
//alert("'main.js' loaded in memory."); 
 } // try

There you are. Nothing to do with actual 'strict mode' -code yet, but we are coming to it...
Next thing is to try some interesting experiments with this workbench. 
Maybe we add a little self made unit testing method and...
That will be explained on next page.