Testing Your Sproutcore Presentation
Upcoming SlideShare
Loading in...5
×
 

Testing Your Sproutcore Presentation

on

  • 1,715 views

How to test your Sproutcore application using BDD.

How to test your Sproutcore application using BDD.

Statistics

Views

Total Views
1,715
Views on SlideShare
1,713
Embed Views
2

Actions

Likes
1
Downloads
28
Comments
0

1 Embed 2

http://twitter.com 2

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Testing Your Sproutcore Presentation Testing Your Sproutcore Presentation Presentation Transcript

  • How do I test my Sproutcore Application? Greg Moeck
  • @gregmoeck
  • Quick Poll
  • Question 1
  • Full TimeSproutcore?
  • Full TimeJavaScript?
  • Other?
  • Question 2
  • PracticeTDD/BDD?
  • PracticeTest Last UnitTesting?
  • NoAutomated Tests?
  • Question 3
  • Practice TDD/BDDIn JS / SC?
  • What We Want InOur Tests
  • EnsureApplication Behavior
  • All Objects Work Together
  • All Objects WorkIndividually
  • All Objects Work Together Acceptance/Integration Tests
  • All Objects Work Individually Unit Tests
  • “ Unit Tests Tell You That You Built The System Right. Acceptance / Integration Tests Tell You That You’ve Built The Right System Gojko Adzic, Specification by Example
  • Integration Tests
  • EnsuresValue ForThe User
  • Use TheSystem As The User Would
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • Scenario(Searching For An Item, function() { Given(an auction item that is available for sale, function() { var itemTitle = item; beforeEach(function() { Fictum.addResource(Item, {title: itemTitle}); }); When(I search for that auction item, function() { beforeEach(function() { Simulo.fillIn(#mainSearchWidget input[type="text"], itemTitle); Simulo.clickOn(#mainSearchWidget .submit-search); }); Then(I should see the auction item within the search results, function(page) { page.within(.search-results, function(page) { expect(page).toHaveContent(itemTitle); }); }); }); }); });});
  • UnitTests
  • EnsuresValue Of TheArchitecture
  • Use Object Like ACollaborator Would
  • Isolate TheObject
  • Example:Testing A View
  • TestThroughView API
  • TotalFlow
  • Example
  • sc-init todos --template
  • install jasmine-sproutcorehttps://github.com/gmoeck/jasmine- sproutcore
  • install simulohttps://github.com/gmoeck/simulo
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • describe(Scenario: Adding a todo, function() { Given(I have loaded the todo application, function() { afterEach(function() { Todos.mainPane.remove(); }); When(I add a new todo item, function() { var description; beforeEach(function() { description = Do Something; Simulo.fillIn(#new-todo, description).pressEnter(); }); Then(I should see the item in the list of available items, function(page) { page.within(#incomplete-todos, function(page) { expect(page).toHaveContent(description); }); }); }); });});
  • resources/templates/todos.handlebars<h1>Todos</h1>{{#view Todos.CreateTodoView}} <input id="new-todo" type="text" placeholder="What needs to be done?" >{{/view}}
  • Error
  • Error
  • views/create_todo_view.jsTodos.CreateTodoView = SC.TemplateView.extend({});
  • resources/templates/todos.handlebars<h1>Todos</h1>{{#view Todos.CreateTodoView}} <input id="new-todo" type="text" placeholder="What needs to be done?" >{{/view}}{{#collection Todos.TodoListView id="incomplete-todos"}} {{content.title}}{{/collection}}
  • views/todo_list_view.jsTodos.TodoListView = SC.TemplateCollectionView.extend({});
  • tests/unit/views/create_todo_view_spec.js describe(Todos.CreateTodoView, function() { describe(#insertNewline, function() { var createTodoSpy, value; beforeEach(function() { value = Do Something; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, createTodo); view.insertNewline(); }); it(delegates to create a new todo with its current value, function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • tests/unit/views/create_todo_view_spec.js describe(Todos.CreateTodoView, function() { describe(#insertNewline, function() { var createTodoSpy, value; beforeEach(function() { value = Do Something; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, createTodo); view.insertNewline(); }); it(delegates to create a new todo with its current value, function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • tests/unit/views/create_todo_view_spec.js describe(Todos.CreateTodoView, function() { describe(#insertNewline, function() { var createTodoSpy, value; beforeEach(function() { value = Do Something; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, createTodo); view.insertNewline(); }); it(delegates to create a new todo with its current value, function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • tests/unit/views/create_todo_view_spec.js describe(Todos.CreateTodoView, function() { describe(#insertNewline, function() { var createTodoSpy, value; beforeEach(function() { value = Do Something; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, createTodo); view.insertNewline(); }); it(delegates to create a new todo with its current value, function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • tests/unit/views/create_todo_view_spec.js describe(Todos.CreateTodoView, function() { describe(#insertNewline, function() { var createTodoSpy, value; beforeEach(function() { value = Do Something; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, createTodo); view.insertNewline(); }); it(delegates to create a new todo with its current value, function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • tests/unit/views/create_todo_view_spec.js describe(Todos.CreateTodoView, function() { describe(#insertNewline, function() { var createTodoSpy, value; beforeEach(function() { value = Do Something; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, createTodo); view.insertNewline(); }); it(delegates to create a new todo with its current value, function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • tests/unit/views/create_todo_view_spec.js describe(Todos.CreateTodoView, function() { describe(#insertNewline, function() { var createTodoSpy, value; beforeEach(function() { value = Do Something; view = Todos.CreateTodoView.create({value: value}); createTodoSpy = spyOn(Todos.todoListController, createTodo); view.insertNewline(); }); it(delegates to create a new todo with its current value, function() { expect(createTodoSpy).toHaveBeenCalledWith(value); }); });
  • Todos.todoListController.createTodo
  • controllers/todo_list_controller.jsTodos.todoListController = SC.ArrayController.create({ createTodo: function(title) { }});
  • views/create_todo_view.jsTodos.CreateTodoView = SC.TemplateView.extend(SC.TextFieldSupport, { insertNewline: function() { }});
  • views/create_todo_view.jsTodos.CreateTodoView = SC.TemplateView.extend(SC.TextFieldSupport, { insertNewline: function() { Todos.todoListController.createTodo(this.get(value)); }});
  • Should be different, but we already definedTodos.todoListController.
  • tests/unit/controllers/todo_list_controller_spec.jsdescribe(Todos.todoListController, function() { describe(#createTodo, function() { var createTodoSpy, title; beforeEach(function() { title = title; createTodoSpy = spyOn(Todos.Todo, create); Todos.todoListController.createTodo(title); }); it(creates a todo with the passed in title, function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); });});
  • tests/unit/controllers/todo_list_controller_spec.jsdescribe(Todos.todoListController, function() { describe(#createTodo, function() { var createTodoSpy, title; beforeEach(function() { title = title; createTodoSpy = spyOn(Todos.Todo, create); Todos.todoListController.createTodo(title); }); it(creates a todo with the passed in title, function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); });});
  • tests/unit/controllers/todo_list_controller_spec.jsdescribe(Todos.todoListController, function() { describe(#createTodo, function() { var createTodoSpy, title; beforeEach(function() { title = title; createTodoSpy = spyOn(Todos.Todo, create); Todos.todoListController.createTodo(title); }); it(creates a todo with the passed in title, function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); });});
  • tests/unit/controllers/todo_list_controller_spec.jsdescribe(Todos.todoListController, function() { describe(#createTodo, function() { var createTodoSpy, title; beforeEach(function() { title = title; createTodoSpy = spyOn(Todos.Todo, create); Todos.todoListController.createTodo(title); }); it(creates a todo with the passed in title, function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); });});
  • tests/unit/controllers/todo_list_controller_spec.jsdescribe(Todos.todoListController, function() { describe(#createTodo, function() { var createTodoSpy, title; beforeEach(function() { title = title; createTodoSpy = spyOn(Todos.Todo, create); Todos.todoListController.createTodo(title); }); it(creates a todo with the passed in title, function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); });});
  • tests/unit/controllers/todo_list_controller_spec.jsdescribe(Todos.todoListController, function() { describe(#createTodo, function() { var createTodoSpy, title; beforeEach(function() { title = title; createTodoSpy = spyOn(Todos.Todo, create); Todos.todoListController.createTodo(title); }); it(creates a todo with the passed in title, function() { expect(createTodoSpy).toHaveBeenCalledWith({title: title}); }); });});
  • Todos.Todo.create
  • models/todo.jsTodos.Todo = SC.Object.extend({});
  • controllers/todo_list_controller.jsTodos.todoListController = SC.ArrayController.create({ createTodo: function(title) { Todos.Todo.create({title: title}); }});
  • tests/unit/controllers/todo_list_controller_spec.jsdescribe(Todos.todoListController, function() { describe(#createTodo, function() { var createTodoSpy, title, todo; beforeEach(function() { title = title; todo = {title: title}; createTodoSpy = spyOn(Todos.Todo, create).andReturn(todo); Todos.todoListController.createTodo(title); }); ... it(adds that todo to its content, function() { expect(Todos.todoListController.get(content)).toContain(todo); }); });});
  • controllers/todo_list_controller.jsTodos.todoListController = SC.ArrayController.create({ content: [], createTodo: function(title) { Todos.Todo.create({title: title}); }});
  • controllers/todo_list_controller.jsTodos.todoListController = SC.ArrayController.create({ content: [], createTodo: function(title) { var todo = Todos.Todo.create({title: title}); this.pushObject(todo); }});
  • Questions?gmoeck@gmail.com @gregmoeck