Your SlideShare is downloading. ×
0
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
How to write easy-to-test JavaScript
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

How to write easy-to-test JavaScript

737

Published on

Common anti patterns that make your JavaScript code hard to test, and how to fix them to make it easy.

Common anti patterns that make your JavaScript code hard to test, and how to fix them to make it easy.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
737
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
7
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Writing Easy-ToTest Code Ynon Perek ynon@ynonperek.com http://ynonperek.com
  • 2. Problem #1 How do you write hard to test code ?
  • 3. Code Flags • Use global state • Use static methods • Mix object construction with business logic • Mixing find-what-i-need logic with business logic • Write LONG functions • Use many conditionals • Dependency hell • Long inheritance hierarchies
  • 4. Isolating Logic ItemWidget jQuery Parser TreeWidget Button Array.sort Data Supplier Data Object
  • 5. Isolating Logic ItemWidget jQuery Parser TreeWidget Button Array.sort Data Supplier Data Object
  • 6. Isolating Logic ItemWidget Test TreeWidget Button Data Supplier
  • 7. Isolating Logic Main ItemWidget TreeWidget Test Button Data Supplier
  • 8. The Code function TreeWidget(ItemWidget, dataSupplier) {
 // ...
 } function TreeWidget() {
 var dataSupplier = new DataSupplier('/music/collection');
 }
  • 9. If you can isolate it, you can test it
  • 10. What Can You Test ? colors = ['red', 'blue', 'green', 'yellow', 'cyan', 'magenta'];
 
 $('#btn').html('Click Me');
 
 
 $('#btn').on('click', function() {
 var idx = $('body').attr('data-color');
 idx = Number(idx) + 1 || 0;
 $('body').attr('data-color', idx);
 if ( Number(idx) >= 0 ) {
 $('body').css("background", colors[idx]);
 } else {
 $('body').css('background', colors[0]);
 }
 });
  • 11. Dependencies • Colors array • DOM structure • jQuery
  • 12. Let’s Try This One function ColorChanger(colors_array, $btn_el, $body_el) {
 var self = this;
 var _current_color = 0;
 
 self.init = function() {
 $btn_el.html('Click Me');
 $btn_el.on('click', self.apply_next_color);
 };
 
 
 }
 self.apply_next_color = function() {
 $body_el.css('backgroundColor', colors_array[_current_color]);
 _current_color += 1;
 };
 var c = new ColorChanger(colors, $('#btn'), $('body'));
 c.init();
  • 13. Now you can easily test: • Code iterates over all colours • Code works well on all possible colours array • Colour iteration is circular
  • 14. Takeaways • Refactoring code can make it easier to test • The goal: • Isolated logic • Clear replaceable dependencies
  • 15. Agenda • Dependency Injection • Data / DOM separation • Component based architecture • Design Patterns
  • 16. Dependency Injection • State all your dependencies at the top • Separate object creation and lookup from business logic
  • 17. DI Framework • A framework that does object creation for you • Some frameworks also manage object lifecycle
  • 18. Famous DI global.myapp.controller(
 'Home', 
 ['$scope', '$routeParams', 'Notebooks', 
 function($scope, $routeParams, Notebooks) {
 // ...
 }]);
  • 19. Famous DI 
 require(["helper/util"], function(util) {
 });
  • 20. Vanilla DI • You don’t really need a framework
  • 21. Q &A
  • 22. Data / DOM Business logic JS write read (event handlers) DOM API HTMLDivElement
  • 23. Event Handlers • Get the data • Call testable handler function $('#username').on('input', function() {
 var newValue = this.value;
 self.checkUsername(newValue);
 });

  • 24. Mixing Lookups $('#btn').on("click", function() {
 if ( $('#page1').is(':hidden') == true ) {
 $('#page1').show();
 $('#page2').hide();
 } else {
 $('#page1').hide();
 $('#page2').show();
 }
 });
 $('#page1').show();
  • 25. Non Mixed Version function Toggle(pages) {
 var active = 0;
 
 function toggle() {
 pages[active].hide();
 active = (active + 1) % pages;
 pages[active].show();
 }
 
 pages[0].show();
 return toggle;
 
 }
 $('#btn').on('click', Toggle([$('#page1'), $('#page2')]));

  • 26. Testing Non-Mixed Version • Setup fake dependencies var FakePage = function() {
 _visible = false;
 return {
 show: function() { _visible = true; },
 hide: function() { _visible = false; },
 visible: function() { return _visible; }
 }
 } ;

  • 27. Testing Non-Mixed Version • Inject and test var toggle = Toggle([p1, p2]);
 
 expect(p1.visible).to.be.true;
 expect(p2.visible).to.be.false; 
 
 toggle();
 expect(p1.visible).to.be.false;
 expect(p2.visible).to.be.true;
  • 28. Mixing Lookups • Separate lookup code from business logic • Test interesting parts -> business logic
  • 29. Components Based Architecture
  • 30. Guidelines • Well defined components with a clear API • Dependencies for each component are injected upon creation • System is a tree of components
  • 31. Components Home Page Sidebar Content
  • 32. Reducing Dependencies • Task: Clicking a menu item in the sidebar should change active item in $content • Is $content a dependency for $sidebar ?
  • 33. Code From Sidebar $('.menu .item').on('click', function() {
 var item_id = $(this).data('id');
 $content.set_active_item(item_id);
 });
  • 34. Direct Connection Problems • It doesn’t scale • Requires tester to mock many components
  • 35. Solution: Observer Pattern • All components share a “hub” • No direct messages between components • Easy on the testing
  • 36. Using Events $('.menu .item').on('click', function() {
 var item_id = $(this).data('id');
 $hub.trigger('active_item_changed', item_id);
 }); Sidebar $hub.on('active_item_changed', set_active_item); Content
  • 37. Testing Events for ( var i=0; i < items.length; i++ ) {
 hub.trigger('active_item_change', i);
 expect($('#content').html()).to.eq(items[i]); } 

  • 38. The Pattern
  • 39. JS Observer • Observer is just a function • Notify by calling it
  • 40. Q &A
  • 41. Code Flags • Use global state • Use static methods • Mix object construction with business logic • Mixing find-what-i-need logic with business logic • Write LONG functions • Use many conditionals • Dependency hell • Long inheritance hierarchies
  • 42. Thanks For Listening • Ynon Perek • http://ynonperek.com • ynon@ynonperek.com

×