Cory Flanigan

Start using Jasmine. Write better JavaScript. Profit.

Start using Jasmine. Write better JavaScript. Profit.

by Justin Searls and Cory Flanigan

The video "Start using Jasmine. Write better JavaScript. Profit" presented by Justin Searls and Cory Flanigan at Rocky Mountain Ruby 2011 discusses the critical need for testing JavaScript, a practice often overlooked by developers. The speakers emphasize the similarities in craftsmanship between Ruby and JavaScript, advocating for a rigorous approach to JavaScript code development as the complexity of web applications increases.

Key points discussed in the presentation include:
- Importance of Testing JavaScript: The speakers highlight that many developers do not test their JavaScript due to a lack of expectation from their peers and the common excuse that JavaScript is just 'glue code'. They stress that quality user experiences cannot be achieved without testing JavaScript due to its central role in web applications.
- The Shift in Software Development: As more applications demand complex JavaScript functionalities, the need for better testing practices and tools like Jasmine has become critical.
- Craftsmanship in Coding: The presenters argue that the level of care applied to Ruby code should equally apply to JavaScript. They discuss issues with writing untestable anonymous code which often results in a 'big ball of mud.'
- Examples of Refactoring: The presenters share anecdotes about their experiences with messy JavaScript code, and demonstrate how to structure code using Jasmine to improve readability and maintainability.
- Testing Tools: They introduce Jasmine testing framework as a useful tool for creating structured and clear tests for JavaScript code, showing how it resembles RSpec in Ruby, making it more approachable for Ruby developers.
- Commitment to JavaScript: Flanigan and Searls urge developers to start testing their JavaScript to improve overall code quality, while also sharing resources such as the Jasmine Rails gem to help integrate Jasmine testing into Rails projects.

In conclusion, the key takeaway from the presentation is that developers should not shy away from writing tests for JavaScript. By applying testing practices akin to those used in Ruby, they can enhance the quality of user interactions in their applications. The speakers encourage a community effort to overcome barriers in JavaScript testing and offer to assist fellow developers in this endeavor.

00:00:09.519 So I'm Cory.
00:00:12.320 And I'm Justin.
00:00:14.719 I write Ruby and I'm interested in JavaScript, but I want to apply the same sort of processes and level of craftsmanship to my JavaScript code that I do with my Ruby code.
00:00:19.600 However, I had a hard time with that; I found it to not be a very easy process. So, I talked to Justin, and we worked on some stuff together.
00:00:28.800 We started discussing this idea that, in Ruby, we're really focused on craftsmanship, and in JavaScript, the equivalent is something else.
00:00:35.920 I'm fortunate enough not to be deeply embedded in the Rails community as much as I’d like to be; I'm working in many other environments. But a year and a half ago, I had a client who needed some really complex JavaScript, and I was scared because I hated JavaScript. So, I started testing it, learning JavaScript, and eventually, I started liking it and built some really cool complex things.
00:00:53.920 Today, I’m here to share some insights I’ve learned, and hopefully, we’ll be able to help you with some actionable steps that you can take to start testing your JavaScript. But first, we want to talk about why people aren’t testing their JavaScript.
00:01:16.960 Why aren’t you testing your JavaScript? Well, I can tell you why I’m not testing mine. It’s because I’m really good at convincing myself that my excuses are valid reasons, even though they are just weak rationalizations.
00:01:37.280 One reason I hadn’t been doing it until my project demanded it was that no one else expected me to do it. In the craftsmanship community, I think a lot of it is about professionalism and peer pressure that drives us to figure out which practices are really important.
00:02:02.560 If I submit Ruby code without a spec, I can pretty much expect a certain result; I’ll submit a pull request and someone will ask, 'Where’s your spec?' But if I submit a pull request for your JavaScript project and I don’t have any test coverage, I’m so used to that now that I will just look at it, say thank you, write some specs, and re-implement what you did for me, but I won’t expect it. I think that’s terrible.
00:02:25.920 We all know why, right? Craftsmanship is craftsmanship; code is code. We should apply the same level of diligence and care to every part of our system.
00:02:47.599 When we hear things like 'test-driven development for JavaScript isn’t worth it' or 'it’s just glue code', it’s disappointing because I think it has real consequences. One of those consequences is that the browser can do really cool things now, and JavaScript is the only language that runs there.
00:03:09.240 If you really want to build a quality user experience, you just have to be able to grapple with JavaScript; you can’t run from it. I often find myself pushing logic somewhere else, like into a controller or a view, where it’s easier to test with RSpec and the rest of my Ruby app. But what's so bad about that?
00:03:29.280 I think Chris Nelson wrote a blog post recently stating that we are in the late Cambrian age for server-side MVC frameworks, and I think that image is fitting. Rails solved a real problem when it came to dynamic content in 2005, and now we’re at a stage where dynamic interaction isn’t as easy to do.
00:03:41.600 I think applying the same practices that made us successful with our server-side code could really serve us well, offering us a competitive advantage and encouraging us to apply those same practices to our clients.
00:04:01.920 So, Cory, I’ve seen application.js files that look a little like this. Do you think that’s fair?
00:04:10.160 I thought I made this repo private! Yeah, that looks about right—a big ball of mud. Chris Powers would probably call it tangled.
00:04:18.880 We end up writing anonymous code, and if all the code we write is an API, but doesn't even have a name, I don’t know if that’s true. If you’re just using anonymous functions in event handling, it can be problematic.
00:04:35.120 So, naming your methods is usually step one to testing. It’s like the API equivalent of NoSQL. When you don’t have tests, one of the things that I’ve been taught and embraced is that a ton of comments in your code is not the way to go.
00:04:59.760 When I try to apply that reasoning to my code, I often pull out the comments and have a tough time intuiting what the code does immediately. Is anyone else feeling this way? If all the code in the code base looks like this, or if you’re used to fighting with JavaScript, do you want to do it every day? Not really, so I’ll just stick to backend stuff.
00:05:24.240 Maybe ultimately it’s true that JavaScript isn’t right for you, but I think that at least giving it a shot and building enough experience to make an informed decision is a commitment we can all make. Just a week ago, I came across a blog post by Jay Fields that I found very apt.
00:05:41.680 In there, I grabbed the most provocative quote I could find, where he mentioned that he pretty much never pairs. Jay Fields is well regarded, so I could safely assume that his opinion indicates pairing has no value, right?
00:06:01.920 Well, my takeaway may have taken that slightly out of context. He said more about how his experience with pairing might not yield a lot of return on investment for him right now, with some caveats. So saying, 'I don’t do JavaScript', I should probably have that same informed perspective.
00:06:33.280 I don’t mind when I hear someone say they don’t do JavaScript, as long as they’ve given it a shot and found it’s just not for them. A year and a half ago, I used to say the same thing, but I can’t believe how much I’ve learned since then.
00:06:49.440 So, show of hands—who here has context and experience yet still decided not to do JavaScript or not to test JavaScript? Wow, good on you! Alright, cool, I’m with you so far; you’re making some compelling points.
00:07:17.600 At this point, we just want to say that since no one raised their hand, please start testing your JavaScript before you quit testing your JavaScript. Can we make that commitment?
00:07:29.199 Now, let’s get started on how to begin testing our JavaScript. I attempted various Jasmine runners and came across numerous blog posts to set up, but it was fail after fail—it was painful.
00:07:42.400 In the Ruby world, I can simply open my Gemfile, add RSpec, and have a great test stack with no effort. I searched everywhere for something like that in JavaScript, and it was quite challenging.
00:08:11.200 Now, let’s talk about RSpec. Nobody got that? I thought that was going to be the best thing ever! Can I see a show of hands of who knows RSpec? Great! I didn’t ask whether you liked RSpec or preferred it over anything else, just gauging familiarity.
00:08:35.040 What if I told you that this syntax is Jasmine? It looks a lot like our Spec, and actually, this format is quite familiar.
00:08:54.560 Let’s take a stab at the problem with unnamed anonymous functions and see how we can better structure this with Jasmine. For a real-world example—let's take a look at some of your own code and see how it would appear with specs.
00:09:24.639 Can you explain what this trying-to-do is for us, Cory? Yeah! It’s two lines that look pretty simple: we’re clicking and running some code, which can be summarized as 'new task,' then 'step three: profit!'
00:09:42.880 When I see code like this, especially when it comes to jQuery, I often think, what's the concern? Is it that the event binding is off, that the app behavior is happening there, or that it’s all glued together?
00:10:04.080 There are several elements at play here, which gives me an 'uh-oh' feeling. When you don’t separate concerns or structure the flow well, you can run into trouble.
00:10:27.040 Because separation of concerns is crucial, it can lead to messy code. What you’ve provided may not be too bad, but unmanageable neighbors can lead to complications.
00:10:47.680 Let's start with that application behavior. If you didn't see what it does, it just looks at this and generates a jQuery results object. It subsequently adds a new div, labeled as a new task.
00:11:04.800 Now, let’s look at a Jasmine spec for that code. It looks straightforward; we’re adding a task with some setup, behavior, and assertions.
00:11:25.200 A common question people often ask me when discussing testing their JavaScript is, 'How would I test that jQuery or that DOM interaction?' The good news is there are several tools and helpers for Jasmine that can assist in this.
00:11:45.040 The one we utilized here is called Jasmine jQuery, which provides numerous custom matchers that are incredibly powerful. For instance, if a background container is a jQuery result object, you can use the 'toContain' matcher with a jQuery selector, and it will verify if this one exists.
00:12:06.000 We should have taken our Ruby craftsmanship—we’ve developed that idea and applied it with Jasmine and our specs since they perform similar roles of providing matchers.
00:12:28.800 So, it's not that different. Additionally, this spec produced a function that was named and more focused, allowing us to tell what it does just by looking at the name. It's concise, making it easier to understand.
00:12:50.640 Of course, the event binding is the hard part, but does anyone want to revert to the original messy four-line method encumbered with all sorts of craziness? Because there’s the exit!
00:13:12.640 Now that we can see how to improve the readability and maintainability here, let’s examine how to fix this from a visual craft perspective.
00:13:31.440 If you're continually nesting, you may find yourself typing the word 'function' so fast that it loses its meaning, accompanied by numerous semicolons and braces. We can adjust that to enhance clarity.
00:13:55.680 Today, Rails 3.1 with the asset pipeline comes with CoffeeScript support out of the box. Even if you don’t use CoffeeScript for your production code immediately, using it for testing is entirely viable.
00:14:15.760 The result looks cleaner and allows you to present what you're communicating clearly; you can outline your intentions by simply viewing your code.
00:14:28.240 So, that spec led to a new, more reusable function we might call 'clicker'. You give it any jQuery selector, an appropriate callback, and it handles everything else for you while preventing default behavior.
00:14:49.680 We began with a convoluted mishmash of concerns that could lead to duplication. Now, we’ve simplified it into an easy one-liner that’s hopefully more readable and maintainable.
00:15:05.280 This means if we change the way we handle our click event binding, we only need to do it in one place, which is tremendously beneficial.
00:15:19.680 We don’t have much time left, but let’s cover some next steps. It would be remiss if we finished this presentation without pointing you in the direction of new opportunities.
00:15:36.160 One of the last year’s projects I’ve dedicated a lot of time toward involves Jasmine. You can follow my GitHub; about half of my repositories are Jasmine toys and demos. I created a web app that lets you experiment with jasmine directly inside your browser without requiring downloads or setup.
00:15:54.560 It’s designed to be approachable; users can type out specs and source code, hit a button, or use a keyboard shortcut to execute. This interface isn't intimidating.
00:16:12.160 Oh, regarding the editor, I was rather pleased to see that GitHub recently adopted a similar slick editor with syntax highlighting. I feel proud that I was there first!
00:16:33.680 What do I do next? You got me interested—how do I add Jasmine to my Rails project? Cory and I had some challenges coming up with good slides, so we spent a day hacking on a Rails gem called Jasmine Rails.
00:16:50.560 This is a simple gem that wraps up several tools we like. It integrates Jasmine with headless WebKit, allowing tests to be run in a familiar environment while respecting the asset pipeline, so you can use CoffeeScript.
00:17:09.920 You can run it headlessly—or in-browser, which is particularly useful for debugging. Both methods derive from the same Jasmine YAML config file to ensure they stay in sync.
00:17:29.680 It should look something like 'try Jasmine.' Whether in one form or another, Cory prefers it to be formatted this way.
00:17:49.440 One last thing before we finish—we extend our invitation to anyone interested in testing JavaScript or wanting to improve their skills. Let’s get together, discuss hurdles, and work through them together.
00:18:12.480 We can all improve the quality and craftsmanship around our JavaScript code—and in addition to our enthusiasm, we made a gem!
00:18:30.560 We also have a coupon code: it’s in Denver, at Add-on Cubed. See Jake if you don’t know about it.
00:18:45.920 Even if you cannot attend next week, especially if you're flying home, find either of us on Twitter. We’ll gladly answer questions, help you with a gist, or reach out to our friends at Pivotal Labs who created Jasmine.
00:19:00.560 Lastly, a big thank you to Pivotal Labs for sponsoring today and to all of you for writing the kinds of JavaScript that inspired us to give this talk.