2013-02-15 16 views
14

हम Ember.js सीखने की प्रक्रिया में हैं। हम अपने सभी विकास टीडीडी करते हैं, और एम्बर.जेएस को अपवाद नहीं चाहते हैं। हमारे पास बैकबोन.जेएस ऐप्स टेस्ट-संचालित बिल्डिंग का अनुभव है, इसलिए हम जैस्मीन या मोचा/चाई का उपयोग करके फ्रंट-एंड कोड परीक्षण से परिचित हैं।ember.js में यूनिट परीक्षण दृश्य कैसे करें?

विचारों का परीक्षण करने के तरीके को समझते समय, हम एक समस्या में भाग गए जब दृश्य उपयोग के लिए टेम्पलेट में #linkTo कथन है। दुर्भाग्य से हम अच्छे परीक्षण उदाहरण और प्रथाओं को खोजने में असमर्थ हैं। यह गलती जवाब पाने के लिए हमारी खोज है कि कैसे यूनिट-टेस्ट एम्बर अनुप्रयोगों को सही तरीके से करें।

test for linkTo in Ember.js source code पर ध्यान देते समय, हमने देखा कि इसमें #linkTo का समर्थन करने के लिए एम्बर ऐप की पूर्ण तार है। क्या इसका मतलब यह है कि हम टेम्पलेट का परीक्षण करते समय इस व्यवहार को रोक नहीं सकते?

टेम्पलेट प्रस्तुतकर्ताओं का उपयोग करके एम्बर दृश्यों के लिए परीक्षण कैसे बनाते हैं?

हमारे परीक्षण और टेम्पलेट के साथ a gist है जो परीक्षण पास करेगा, और एक टेम्पलेट जो इसे विफल कर देगा।

view_spec.js.coffee

# This test is made with Mocha/Chai, 
# With the chai-jquery and chai-changes extensions 

describe 'TodoItemsView', -> 

    beforeEach -> 
    testSerializer = DS.JSONSerializer.create 
     primaryKey: -> 'id' 

    TestAdapter = DS.Adapter.extend 
     serializer: testSerializer 
    TestStore = DS.Store.extend 
     revision: 11 
     adapter: TestAdapter.create() 

    TodoItem = DS.Model.extend 
     title: DS.attr('string') 

    store = TestStore.create() 
    @todoItem = store.createRecord TodoItem 
     title: 'Do something' 

    @controller = Em.ArrayController.create 
     content: [] 

    @view = Em.View.create 
     templateName: 'working_template' 
     controller: @controller 

    @controller.pushObject @todoItem 

    afterEach -> 
    @view.destroy() 
    @controller.destroy() 
    @todoItem.destroy() 

    describe 'amount of todos', -> 

    beforeEach -> 
     # $('#konacha') is a div that gets cleaned between each test 
     Em.run => @view.appendTo '#konacha' 

    it 'is shown', -> 
     $('#konacha .todos-count').should.have.text '1 things to do' 

    it 'is livebound', -> 
     expect(=> $('#konacha .todos-count').text()).to.change.from('1 things to do').to('2 things to do').when => 
     Em.run => 
      extraTodoItem = store.createRecord TodoItem, 
      title: 'Moar todo' 
      @controller.pushObject extraTodoItem 

broken_template.handlebars

<div class="todos-count"><span class="todos">{{length}}</span> things to do</div> 

{{#linkTo "index"}}Home{{/linkTo}} 

working_template.handlebars

<div class="todos-count"><span class="todos">{{length}}</span> things to do</div> 
+1

मूल रूप से आप मुसीबत अलगाव में सामान instantiating होगा। एम्बर चाहता है कि आपका पूरा ऐप चल रहा हो। यह कोई जवाब नहीं है, लेकिन आम तौर पर मैं एकीकरण परीक्षण पसंद करता हूं (देखें [यह वीडियो] (http://www.youtube.com/watch?v=heK78M6Ql9Q)) यूनिट परीक्षणों पर। मैंने लोगों को अलगाव में विचारों का परीक्षण करने की कोशिश की है, और यहां तक ​​कि जब यह काम करता है यह एक अच्छी रणनीति की तरह प्रतीत नहीं होता है। इसके पीछे कुछ तर्कसंगतताओं के लिए http://www.slideshare.net/jo_liss/testing-ember-apps/27 देखें। –

उत्तर

9

हमारा समाधान अनिवार्य रूप से पूरे आवेदन को लोड करना है, लेकिन जितना संभव हो सके हमारे परीक्षण विषयों को अलग करें। उदाहरण के लिए,

describe('FooView', function() { 
    beforeEach(function() { 
    this.foo = Ember.Object.create(); 
    this.subject = App.FooView.create({ foo: this.foo }); 
    this.subject.append(); 
    }); 

    afterEach(function() { 
    this.subject && this.subject.remove(); 
    }); 

    it("renders the foo's favoriteFood", function() { 
    this.foo.set('favoriteFood', 'ramen'); 
    Em.run.sync(); 
    expect(this.subject.$().text()).toMatch(/ramen/); 
    }); 
}); 

है, रूटर और अन्य वैश्विक उपलब्ध हैं, तो यह पूरा अलगाव नहीं है, लेकिन हम आसानी से चीजों को परीक्षण के अंतर्गत वस्तु के करीब के लिए डबल्स में भेज सकते हैं।

तुम सच में रूटर अलग करने के लिए चाहते हैं, linkTo सहायक यह controller.router के रूप में लग रहा है, तो आप

this.router = { 
    generate: jasmine.createSpy(...) 
}; 

this.subject = App.FooView.create({ 
    controller: { router: this.router }, 
    foo: this.foo 
}); 
1

एक तरह से आप इस संभाल कर सकते हैं कर सकता है linkTo सहायक और उसके बाद के लिए एक ठूंठ बनाने के लिए है पहले ब्लॉक में इसका इस्तेमाल करें। इससे वास्तविक लिंक की सभी अतिरिक्त आवश्यकताओं को बाधित किया जाएगा (उदा। रूटिंग) और आपको दृश्य की सामग्री पर ध्यान केंद्रित करने दें। यहाँ कैसे मैं इसे कर रहा हूँ है:

// Test helpers 
TEST.stubLinkToHelper = function() { 
    if (!TEST.originalLinkToHelper) { 
     TEST.originalLinkToHelper = Ember.Handlebars.helpers['link-to']; 
    } 
    Ember.Handlebars.helpers['link-to'] = function(route) { 
     var options = [].slice.call(arguments, -1)[0]; 
     return Ember.Handlebars.helpers.view.call(this, Em.View.extend({ 
      tagName: 'a', 
      attributeBindings: ['href'], 
      href: route 
     }), options); 
    }; 
}; 

TEST.restoreLinkToHelper = function() { 
    Ember.Handlebars.helpers['link-to'] = TEST.originalLinkToHelper; 
    TEST.originalLinkToHelper = null; 
}; 

// Foo test 
describe('FooView', function() { 
    before(function() { 
     TEST.stubLinkToHelper(); 
    }); 

    after(function() { 
     TEST.restoreLinkToHelper(); 
    }); 

    it('renders the favoriteFood', function() { 
     var view = App.FooView.create({ 
      context: { 
       foo: { 
        favoriteFood: 'ramen' 
       } 
      } 
     }); 

     Em.run(function() { 
      view.createElement(); 
     }); 

     expect(view.$().text()).to.contain('ramen'); 
    }); 
}); 
संबंधित मुद्दे