<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mikbe.com</title>
    <description>This is where I publish stuff I think others can find useful.
</description>
    <link>http://mikbe.com/</link>
    <atom:link href="http://mikbe.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 13 Mar 2016 15:01:10 +0000</pubDate>
    <lastBuildDate>Sun, 13 Mar 2016 15:01:10 +0000</lastBuildDate>
    <generator>Jekyll v3.0.1</generator>
    
      <item>
        <title>Why and How Testing Can Make You Happier</title>
        <description>&lt;p&gt;I was once a non-tester, because I didn’t see the value. Then I tried it for a while, and was convinced. I’ve gathered some experience, but not enough. This article is an attempt to collect what I know and what I think I know, and hope I can finally learn some of the stuff I know but don’t necessarily practice.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/simpsons-testing.gif&quot; alt=&quot;hello&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The main inspiration source for this article is &lt;a href=&quot;http://javascriptair.com/episodes/2016-01-06/&quot;&gt;JavaScript Air episode 004&lt;/a&gt;, but there’s also some original content in here. And some from &lt;a href=&quot;https://vimeo.com/68375232&quot;&gt;TDD: Where did it all go wrong?&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I don’t always test my code, but when I do, it feels better.&lt;/p&gt;

  &lt;p&gt;– &lt;cite&gt;me&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;what-is-it-all-about&quot;&gt;What is it all about?&lt;/h2&gt;

&lt;p&gt;This, only for code:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/testing-bicycle-integration-test.gif&quot; alt=&quot;Integration testing a bike&quot; /&gt; &lt;em&gt;The concept isn’t that hard.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article is mostly about unit testing, as opposed to integration testing or end-to-end testing, but some aspects are true for all kinds. And know that there’s a spectrum. In practice, tests are seldom one or the other, and that isn’t the goal either.&lt;/p&gt;

&lt;p&gt;Unit tests are cheap and should make up the largest part of your testing efforts. They’re cheap to write and run. They look at only specific parts of the code. Integration tests are the opposite, they encompass larger parts of the code. Some mimic users.&lt;/p&gt;

&lt;h2 id=&quot;why-is-it-important&quot;&gt;Why is it Important?&lt;/h2&gt;

&lt;p&gt;Testing helps you achieve peace of mind about your code. Writing a solution to a half-complex problem, then manually testing it only takes you so far. With some experience, you’ll surely recognize the situation of shipping some code with confidence, only to find it break apart at its first opportunity.&lt;/p&gt;

&lt;p&gt;Testing gives experience with the mindset of putting your code under the most extreme conditions it can get into. What if the number passed in was negative when we always assumed it would be positive? What if it wasn’t a number at all?&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Everybody writes bugs, we all write bugs. So, it’s not a matter of “can you write code correctly or not the first time?”, we all write incorrect code. &lt;strong&gt;That’s all that we do, we only write incorrect code&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;– &lt;cite&gt;Joe Eames, JavaScript Air 004&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Coding is hard&lt;/strong&gt;, and we should all acknowledge that. Among the primary reasons to test your code is to gain confidence that it will behave as &lt;em&gt;expected&lt;/em&gt;, whatever that is.&lt;/p&gt;

&lt;p&gt;Not convinced? Here are some additional arguments:&lt;/p&gt;

&lt;h3 id=&quot;tested-code-is-better-code&quot;&gt;Tested Code is Better Code&lt;/h3&gt;

&lt;p&gt;Many people&lt;sup&gt;[who?]&lt;/sup&gt; will tell you that code testing leads to better code quality. This is especially true when using unit tests and at least some variation on test driven development, even if it’s a sloppy one. Here’s why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If your code is hard to test, then it’s probably not very well written.&lt;/strong&gt; What identifies good code is a large question, but the emphasized sentence here is a good rule of thumb. A quality of good code that most will agree on is that it separates concerns. Experienced programmers limit function bodies to only do one logical thing for this reason.&lt;/p&gt;

&lt;h4 id=&quot;aligning-your-goals&quot;&gt;Aligning Your Goals&lt;/h4&gt;

&lt;p&gt;Code that is hard to test probably has either too many things going on, or too many dependencies (or both). Think of this as a problem of aligning interests: When writing untested code, there is a conflict of interest between speed (or laziness) and separation of concerns, and it doesn’t matter as much for the short term how your code is structured. &lt;strong&gt;When your code has to be tested, your goals are more aligned,&lt;/strong&gt; because tests are easier to write for well written code!&lt;/p&gt;

&lt;h4 id=&quot;think-as-a-consumer&quot;&gt;Think as a Consumer&lt;/h4&gt;

&lt;p&gt;When you’re writing tests first, you’re &lt;strong&gt;designing your code’s API first.&lt;/strong&gt; Testing puts you into code consumer mode, where you’ll write code against what’s going to be the interface to other stuff. Designing your API without so much concern for inner workings leads to a better API design, which leads to easier consumption of your module, which leads to cleaner code in the project as a whole.&lt;/p&gt;

&lt;h4 id=&quot;eureka-moments&quot;&gt;Eureka moments&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Testing leads to a-ha moments.&lt;/strong&gt; Often because it forces you to think about edge cases – the value zero, &lt;code class=&quot;highlighter-rouge&quot;&gt;10^12&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;null&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;undefined&lt;/code&gt;. You’ll have the opportunity to think about, reflect on and acknowledge what should happen under strange circumstances. Merely the process of thinking about them, or other situations your code can face, often leads to realizations of how the code can be &lt;em&gt;simplified&lt;/em&gt; (as well as how it has to guard itself).&lt;/p&gt;

&lt;p&gt;These eureka moments can also come from one of the most frustrating situations: when your code and tests don’t agree. You’re put in the situation of having to decide which is right. If you’re in this situation, something has probably gone wrong with the design, or your assumptions have changed. Think of this as a good sign! Your code will be happier.&lt;/p&gt;

&lt;!-- As a side note, I like to think about this situation like an NP-complete problem, *[The travelling salesman problem][travellingsalesman]*. These problem instances basically cannot be calculated without checking all possible solutions, so it&#39;s very hard. However, if you have God-given correct answer to the instance, testing the outcome of the algorithm is easy as `t.equal(outcome, godGiven)`. Doesn&#39;t it make sense that testing is easier than writing actual code?--&gt;

&lt;h3 id=&quot;tests-document-what-the-code-does&quot;&gt;Tests Document What the Code Does&lt;/h3&gt;

&lt;p&gt;No-one loves to write documentation, but it sure as hell is nice when the module your inheriting (from your one year younger self, or someone else) or interfacing is well documented. Tests can be this documentation, and with an added bonus: tests put their money where their mouths are and &lt;em&gt;demonstrate&lt;/em&gt; what they mean. Like the best science teachers, they don’t just tell you that hydrogen is flammable. They fill a balloon with hydrogen, let it rise to the ceiling and put a lighted match on a stick to it (One of my most memorable 5th grade classes).&lt;/p&gt;

&lt;p&gt;Do you know what is common to all bugs? &lt;em&gt;They passed all the tests.&lt;/em&gt; So when you find one, you know where not to look.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/testing-just-as-i-expected.gif&quot; alt=&quot;hello&quot; /&gt; &lt;em&gt;At least you know what doesn’t work.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing makes it easier to join a project&lt;/strong&gt;, because they reveal what the code is actually supposed to do. They tell a story about the design decisions, what went through the mind of the original developer.&lt;/p&gt;

&lt;h3 id=&quot;refactor-without-worry&quot;&gt;Refactor Without Worry&lt;/h3&gt;

&lt;p&gt;Ever looked at a horrible mess of code, but been to afraid to clean it up? The first thing I do in situations like that is to create tests to discover what the code is supposed to be doing. The tests lock down the functionality, in a good way, allowing us to focus on the spring cleaning, rather than worrying about breaking stuff.&lt;/p&gt;

&lt;p&gt;I’ve seen pieces of code so bad they cause real concerns of whether they actually do what they’re supposed to. Still, no-one dared touch it, afraid of not only breaking intended functionality, but also breaking &lt;em&gt;bugs&lt;/em&gt;. I suspect a large test set based on past I/O would be well worth its investment.&lt;/p&gt;

&lt;p&gt;Fun fact, &lt;strong&gt;the feelings of worry and happiness are inversely proportional&lt;/strong&gt;. Or something like that.&lt;/p&gt;

&lt;h3 id=&quot;create-value-with-confidence-and-correct-products&quot;&gt;Create Value with Confidence and Correct Products&lt;/h3&gt;

&lt;p&gt;Correct code is more valuable than incorrect code&lt;sup&gt;[citation needed]&lt;/sup&gt;. Everything helping your code to be correcter tahn what was there before is worth taking a look at, it’s as simple as that. Delivering correct code builds up trust over time, trust is a valuable asset.&lt;/p&gt;

&lt;h2 id=&quot;a-tool-to-use-less-brain-ram&quot;&gt;A Tool to Use Less Brain RAM&lt;/h2&gt;

&lt;p&gt;Here’s a tip: &lt;strong&gt;Don’t try to solve a problem and engineer a nice solution at the same time.&lt;/strong&gt; Testing gives us that opportunity, using this recipe from &lt;a href=&quot;https://vimeo.com/68375232&quot;&gt;Ian Cooper’s talk on TDD&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Write a red test.&lt;/li&gt;
  &lt;li&gt;Solve the problem, make it green &lt;em&gt;as fast as possible.&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;Engineer a nice solution, refactor it to something you’re proud of.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important thing to take away here is the temporal separation of concerns in your head. Do not try to do steps 2 and 3 at the same time. One of the main limitations of programming is how much you can keep in your head at once, and you’ll write better code the less you have to keep there when you’re typing.&lt;/p&gt;

&lt;p&gt;When solving the problem, do not think about how the code really should be. Copy-paste code, write inefficient loops, duplicate stuff, do whatever you have to do to get the test green as fast as possible. &lt;em&gt;Then&lt;/em&gt; think about how to change it into something you could show your mother.&lt;/p&gt;

&lt;p&gt;Separating your own concerns is one of the reasons to test in the first place, and this method helps doing it in practice. When you quickly and dirtily race to a solution, you don’t have to think about how it looks or how fast it runs. When you carve out your nicely engineered and cool solution, you don’t have to worry about screwing something up.&lt;/p&gt;

&lt;h2 id=&quot;knowing-what-to-test-is-key&quot;&gt;Knowing What to Test is Key&lt;/h2&gt;

&lt;p&gt;Knowing what to test isn’t as easy as it sounds, and is definitively something that comes with experience. Many test too much. Knowing what to test is related to understanding what is important, and what isn’t, and knowing that is not trivial. Here’s a tip, though:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Test at the highest level possible to get coverage and flexibility on implementation.&lt;/em&gt;&lt;/p&gt;

  &lt;p&gt;– Brian Lonsdorf, JavaScript Air 004&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, basically:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Do not test internal stuff&lt;/strong&gt;, it will only get in your way. If you honestly feel like you should test the internal stuff, then you might be better off separating some of the internals out to a new module, where they are external.&lt;/li&gt;
  &lt;li&gt;Do not allow tests to be &lt;strong&gt;over specified&lt;/strong&gt; and deal with stuff they don’t have to or shouldn’t know about.&lt;/li&gt;
  &lt;li&gt;Do not write tests just to get 100 % coverage. If someone tells you to always have 100 % coverage, no matter what, then &lt;strong&gt;punch them in the face&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember that tests should be written &lt;em&gt;outside-in&lt;/em&gt;, from a perspective outside the module. Note that full test coverage should still be possible, i.e. all branches of your code should still be reachable. If they’re not, they’re basically dead code, right? &lt;strong&gt;Test the internals only if you need to understand better how they work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think about what happens when the code is refactored, some time in the future. The implementation should be allowed to change without tests failing. Why? Well, because &lt;strong&gt;if the future coder has to change the tests, then it’s basically a rewrite, not a refactor. And rewrites aren’t safe.&lt;/strong&gt; There should be no new tests for refactoring internals.&lt;/p&gt;

&lt;p&gt;Be pragmatic about what to test. Testing is part of the project, part of the value creation, and it doesn’t make sense to test just anything, just like it doesn’t make sense to implement every button. Remember the documentation aspect. If tests are mostly involved with implementation details, we loose the focus on what’s &lt;em&gt;important in the module&lt;/em&gt;. We loose the documentation value.&lt;/p&gt;

&lt;p&gt;About documentation, &lt;strong&gt;test your domain assumptions.&lt;/strong&gt; These are the code interpretations of the problem domain you’re working in, often something where the programmer is not the expert. Documenting these assumptions in code form solves two problems: documenting the assumptions themselves, and proving that they work as interpreted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write a test when you find a bug.&lt;/strong&gt; Don’t just fix it, but prove for yourself and others that you’ve actually done so. Write a test, and make sure it’s both red and aligned what the expectation would be not aware of the bug. Fix the bug, make it green. Save the day.&lt;/p&gt;

&lt;p&gt;Code coverage is overrated as a concrete number, but useful as a tool. Do not strive to cover for coverage’s sake. &lt;strong&gt;Remember that coverage only tells you what lines your tests run, but not in what combination they will run.&lt;/strong&gt; However, it can be a good indication of whether things are moving in the right direction. If a refactor leads to poorer code coverage, then some bells should be ringing, especially if it’s a refactor. Do not allow yourself to write tests just to increase the number. Well tested and written code will have a higher number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The trigger for writing a test is when you’ve got a new piece of behavior.&lt;/strong&gt; The tests should capture that behavior, but no more.&lt;/p&gt;

&lt;p&gt;Testing libraries might be both easier and more important than testing end applications. After all, libraries will be used by multiple applications.&lt;/p&gt;

&lt;h2 id=&quot;how-to-write-awesome-tests&quot;&gt;How To Write Awesome Tests&lt;/h2&gt;

&lt;p&gt;Knowing how to write good tests is key, because it’s very easy to write them badly. The truth is, as with everything, that it takes practice. Still, here are some tips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good test is a simple test.&lt;/strong&gt; It doesn’t try to cover everything in one go. It’s name should reflect what it does, and the name should fit comfortably in one line. The name shouldn’t be &lt;em&gt;“it works”&lt;/em&gt;, but rather, &lt;em&gt;“it returns 0 for negative values”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/rocket-test.gif&quot; alt=&quot;hello&quot; /&gt; &lt;em&gt;A good test is a simple test.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure not to overspecify your test.&lt;/strong&gt; Overspecified tests know too much about internals for their own good, and don’t allow refactoring.&lt;/p&gt;

&lt;p&gt;A unit test runs the code in isolation from other tests, not necessarily other code. It takes the code out of it’s context, and creates an artificial context from which an aspect of it can be investigated. However, that does not mean a unit test has to run in isolation from all other &lt;em&gt;code&lt;/em&gt;, even though this is often cited as “pure unit tests”. &lt;strong&gt;Everything does not have to be mocked, stubbed or spied on,&lt;/strong&gt; leading to more complex setups, lower coverage and more fragile tests.&lt;/p&gt;

&lt;p&gt;Use &lt;a href=&quot;http://sinonjs.org/docs/#mocks&quot;&gt;mocks&lt;/a&gt; or &lt;a href=&quot;http://sinonjs.org/docs/#stubs&quot;&gt;stubs&lt;/a&gt; where that makes sense. You don’t want to test against a real HTTP API, but stub them out. Use a mock or a stub if what you’re testing is your own call to that object, or if you want to lead your own code down a certain path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A test should read like a small story, following the AAA system: Arrange, Act, Assert.&lt;/strong&gt; You set things up, you make some statement, and you assert that the statement did what the statement should. The “small story” aspect has emphasis on &lt;em&gt;small&lt;/em&gt;. None of the “A”-s should be more than about 3 lines. Making some space between the phases can be nice. It should contain no branching or looping, and you should assert only one logical thing. (It’s nice if that can be expressed as one assert statement, but sometimes you’ll need more, and that’s OK.) Never assert in two different places in the test, as this causes confusion as to what you’re actually testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The test should be readable with only some domain knowledge.&lt;/strong&gt; If it does things that are hard to explain without going into the inner workings of the module, then it’s probably better to either spend some more time on the test, or just leave it out completely.&lt;/p&gt;

&lt;p&gt;Generally, don’t test your dependencies. For certain projects, it may make sense to do some simple testing of the assumptions your own code is making, but do so sparingly and with caution. Testing a library is the job of the library author. Instead, rely on changelogs for upgrades, and on testing your integration against the library (this is a reason not to mock everything).&lt;/p&gt;

&lt;p&gt;Write cheap tests that don’t take forever to run, because &lt;strong&gt;run them as often as possible&lt;/strong&gt;. If you can pass a &lt;code class=&quot;highlighter-rouge&quot;&gt;--watch&lt;/code&gt; argument to your test runner and have it run every time a file is changed, then that’s a good thing.&lt;/p&gt;

&lt;p&gt;Last but not least, &lt;strong&gt;use a test framework you like working with.&lt;/strong&gt; If JavaScript is your thing, I’d like to recommend &lt;a href=&quot;https://github.com/sindresorhus/ava&quot;&gt;AVA 🚀&lt;/a&gt; because of it’s clarity, simplicity and lack of complex configuration. Whatever you choose, make sure it’s something that works with you and helps you write efficiently and fast. As with everything code, if it’s not fun, something is probably wrong.&lt;/p&gt;

</description>
        <pubDate>Fri, 11 Mar 2016 17:32:00 +0000</pubDate>
        <link>http://mikbe.com/code/testing/dx/2016/03/11/why-and-how-testing-can-make-you-happier.html</link>
        <guid isPermaLink="true">http://mikbe.com/code/testing/dx/2016/03/11/why-and-how-testing-can-make-you-happier.html</guid>
        
        
        <category>code</category>
        
        <category>testing</category>
        
        <category>dx</category>
        
      </item>
    
      <item>
        <title>Give Your Releases Awesome Names with Codenamer</title>
        <description>&lt;p&gt;&lt;strong&gt;TL;DR: I’ve released &lt;a href=&quot;https://github.com/mikberg/codenamer&quot;&gt;Codenamer&lt;/a&gt;, a simple CLI to generate codenames. Such as it’s own release codename, &lt;code class=&quot;highlighter-rouge&quot;&gt;0.3.0 canonical-catastrophe&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;curl -s https://en.wikipedia.org/wiki/Gravitational_Waves | codenamer --format pa,cJ,n15-cN,a,n20
astronomical-amplification
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Using codenames for releases has been one of my hobbies, ever since I started using Angular, inspired by their &lt;a href=&quot;https://github.com/angular/angular.js/blob/master/CHANGELOG.md&quot;&gt;cool-sounding and mysterious codenames&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using names for releases in large-ish projects can make them easier to remember and to talk about. Even if the name is totally unrelated to the contents of a release, it can be easier to relate a feature set to a name than to an arbitrary number.&lt;/p&gt;

&lt;p&gt;In order to be extra cool, codenames should:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Sound awesome&lt;/li&gt;
  &lt;li&gt;Keep to a theme&lt;/li&gt;
  &lt;li&gt;Fulfill a set of rules, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;adjective&amp;gt;-&amp;lt;noun&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Optionally relate to the release number, e.g. start with &lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt; for &lt;code class=&quot;highlighter-rouge&quot;&gt;0.1.x&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Alliteration&quot;&gt;Alliterations&lt;/a&gt; are welcome.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;using-codenamer&quot;&gt;Using Codenamer&lt;/h2&gt;

&lt;p&gt;Codenamer lets you generate these memorable codenames without need for imagination. You just pipe it a (fairly large) body of text as input, and some rules for the codenames.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;curl -s https://en.wikipedia.org/wiki/Alliteration | codenamer --count 10 --format cJ,n15-cN,a,n20
persuasive-parallelism
specific-syllables
symmetrical-syllable
consonant-consonants
alliterative-argument
pickled-proposition
special-speaker
rhetorical-release
memorable-meter
potential-pairs
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;format&lt;/code&gt; option lets you specify the number of words per codename, the length of each word (or the combined length), the word class for each of the words and alliteration.&lt;/p&gt;

&lt;p&gt;The module also has a Node API, so you can generate codenames as part of a release script or something.&lt;/p&gt;

&lt;p&gt;Install it with &lt;code class=&quot;highlighter-rouge&quot;&gt;npm install --global codenamer&lt;/code&gt;, and you’re ready.&lt;/p&gt;

&lt;p&gt;Check the repo at &lt;a href=&quot;https://github.com/mikberg/codenamer&quot;&gt;mikberg/codenamer&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Sun, 14 Feb 2016 12:36:01 +0000</pubDate>
        <link>http://mikbe.com/awesome/projects/2016/02/14/generate-awesome-codenames-with-codenamer.html</link>
        <guid isPermaLink="true">http://mikbe.com/awesome/projects/2016/02/14/generate-awesome-codenames-with-codenamer.html</guid>
        
        
        <category>awesome</category>
        
        <category>projects</category>
        
      </item>
    
      <item>
        <title>Zero to Hero with End-to-End testing using Nightwatch, SauceLabs and Travis</title>
        <description>&lt;p&gt;Developing super cool web apps has always been a walk on a thin line: You want to use the latest possible language features and APIs, but at the same time, it needs to work in loads of, for developers, obscure browsers like IE10 and Android Browser.&lt;/p&gt;

&lt;p&gt;Deploying quickly grinds to a holt when you find out in final tests that your app doesn’t work in all of the required browsers and environments, and last minute hacks are sometimes needed. Using a continuous integration testing tool with real-life browsers was a real timesaver and stress-reliever for me.&lt;/p&gt;

&lt;p&gt;This is a summary of the feature branch that took me there.&lt;/p&gt;

&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h2&gt;

&lt;p&gt;In order to get something tested at all, we need two ingredients: A &lt;em&gt;browser automation tool&lt;/em&gt; and a &lt;em&gt;test runner&lt;/em&gt;. For browser automation, &lt;a href=&quot;http://www.seleniumhq.org/&quot;&gt;Selenium&lt;/a&gt; is the obvious option, and the one cloud testing providers like BrowserStack and SauceLabs use.&lt;/p&gt;

&lt;p&gt;If you’re on OSX, run &lt;code class=&quot;highlighter-rouge&quot;&gt;brew install selenium-server-standalone&lt;/code&gt;, along with a webdriver for your favourite browser: &lt;code class=&quot;highlighter-rouge&quot;&gt;brew install chromedriver&lt;/code&gt;. Run it with &lt;code class=&quot;highlighter-rouge&quot;&gt;selenium-server -p 4444&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There are many test runners which integrate with Selenium. You can choose any test runner you want, so choose one that makes sense for you, based on programming language and needs. This article is based on &lt;a href=&quot;http://nightwatchjs.org/&quot;&gt;Nightwatch&lt;/a&gt;, but should be easily translatable for other test runners.&lt;/p&gt;

&lt;p&gt;Go ahead and install Nightwatch with &lt;code class=&quot;highlighter-rouge&quot;&gt;npm install -g nightwatch&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;configuring-nightwatch&quot;&gt;Configuring Nightwatch&lt;/h2&gt;

&lt;p&gt;Nightwatch needs some config, so create a new file called &lt;code class=&quot;highlighter-rouge&quot;&gt;nightwatch.js&lt;/code&gt;. Nightwatch uses a &lt;code class=&quot;highlighter-rouge&quot;&gt;.json&lt;/code&gt; config file as default, but using a JS one allows us to do some smart stuff later, like generating parts of the config based on environment variables.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// nightwatch.js&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;src_folders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;test/e2e/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Find the rest of the configuration you need in Nightwatch’ developer guide. In the &lt;code class=&quot;highlighter-rouge&quot;&gt;default&lt;/code&gt; configuration, just use the &lt;code class=&quot;highlighter-rouge&quot;&gt;browserName&lt;/code&gt; corresponding to the Selenium webdriver you installed, e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;chrome&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;creating-your-first-test&quot;&gt;Creating your first test&lt;/h2&gt;

&lt;p&gt;Time to write some code! Create a file &lt;code class=&quot;highlighter-rouge&quot;&gt;test/e2e/simple/simpleTest.js&lt;/code&gt;and paste in something like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// test/e2e/simple/simpleTest.js&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;beforeEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;http://localhost:8000&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;waitForElementVisible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;waitForElementVisible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘#&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Smoke&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;visible&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘#&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Check&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rendered&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;with&lt;/span&gt;   &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;MyTitle&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Thanks to the Nightwatch API, the code is pretty self explanatory. Replace the assertions with something that makes sense for you.&lt;/p&gt;

&lt;p&gt;Assuming you already have your app running, go ahead and run your test, with &lt;code class=&quot;highlighter-rouge&quot;&gt;nightwatch --config nightwatch.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/nightwatch.gif&quot; alt=&quot;Running Nightwatch&quot; /&gt; &lt;em&gt;Awesome, the title matches the HTML.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;running-tests-in-the-cloud&quot;&gt;Running Tests in the Cloud&lt;/h2&gt;

&lt;p&gt;Useful as it is to test whether Chrome can parse HTML, we’re now ready to 10x the awesomeness, using SauceLabs. Feel free to create an account at this point.&lt;/p&gt;

&lt;p&gt;First, make some changes to the Nightwatch config:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;launch_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://ondemand.saucelabs.com:80&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;selenium_port&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;selenium_host&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;ondemand.saucelabs.com&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;silent&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;username&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SAUCE_USERNAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;access_key&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SAUCE_ACCESS_KEY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;screenshots&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;waitForConditionTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;(You can move your previous default config to one called e.g. “local”.)&lt;/p&gt;

&lt;p&gt;Nightwatch needs your username and access key to connect to SauceLabs. We also use the opportunity to add a global default time for Nightwatch’ timeouts.&lt;/p&gt;

&lt;p&gt;At the same level as the default configuration, add one or two browsers you want to test against:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;chrome&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;desiredCapabilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;browserName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;chrome&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;OS X 10.11&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;47&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;ie11&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;desiredCapabilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;browserName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;internet explorer&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;platform&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;Windows 10&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;11.0&#39;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Set your SauceLabs username and access key environment variables with &lt;code class=&quot;highlighter-rouge&quot;&gt;export SAUCE_USERNAME &amp;lt;username&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For SauceLabs to be able to contact your server, install SauceConnect with &lt;code class=&quot;highlighter-rouge&quot;&gt;brew install sauce-connect&lt;/code&gt;, then run it with &lt;code class=&quot;highlighter-rouge&quot;&gt;sc -u &amp;lt;USERNAME&amp;gt; -k &amp;lt;ACCESS_KEY&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This should be all it takes to run tests on a machine far, far away, somewhere in a cloud, and have it do stuff the server running right under your fingertips. Run &lt;code class=&quot;highlighter-rouge&quot;&gt;nightwatch --config nightwatch.js --env chrome&lt;/code&gt;, then sit back and relax.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/nightwatch-saucelabs.png&quot; alt=&quot;Nightwatch on Saucelabs&quot; /&gt; &lt;em&gt;Not bad, Chrome and IE agree on the title.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;run-your-tests-from-travis&quot;&gt;Run Your Tests from Travis&lt;/h2&gt;

&lt;p&gt;This step requires us to make Travis spawn both a server to host our app, and a tunnel to SauceLabs with SauceConnect. Worry not, because it’s not that hard.&lt;/p&gt;

&lt;p&gt;For more documentation, read &lt;a href=&quot;For more documentation, read Travis’ article.&quot;&gt;Travis’ article&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;addons&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;sauce_connect&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nvm install 4.0 // if you&#39;re not using Node as language&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;npm install -g nightwatch&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;before_script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;// This is our server&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;- npm run serve:dist &amp;amp;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;nightwatch --config nightwatch.js --env chrome,ie11&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;// This one feels hacky, but does the job of killing the server&lt;/span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;pkill node&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If your server takes a very long time to load, it can be a good idea to add a “sleep 30” command after you start the server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Also note:&lt;/strong&gt; You probably have some other stuff you want travis to do. Do them before Nightwatch, as the tests involving SauceLabs are probably the most expensive. You’ll also give your server some time to build JavaScript.&lt;/p&gt;

&lt;p&gt;For SauceLabs to connect to Travis, we need to send them a tunnel identifier. We’d also like SauceLabs to take a note of the Travis build number it is testing, so we also pass that one. Luckily, they’re both based on the same value.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// nightwatch.js&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TRAVIS_JOB_NUMBER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TRAVIS_JOB_NUMBER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// in test_settings.default:&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;launc_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;http://ondemand.saucelabs.com:80&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;desiredCapabilities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TRAVIS_JOB_NUMBER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&#39;tunnel-identifier&#39;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TRAVIS_JOB_NUMBER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Congratulations, the next time you push your code, servers around the world will collaborate to make sure everything works as intended.&lt;/p&gt;

&lt;p&gt;Gather some friends to watch in awe as results tick into the SauceLabs dashboard, with live videos and things flashing all over the screen.&lt;/p&gt;

&lt;h2 id=&quot;make-saucelabs-know-whether-or-not-it-worked&quot;&gt;Make SauceLabs know whether or not it worked&lt;/h2&gt;

&lt;p&gt;You might have noticed the nice question mark next to each of your tests in SauceLabs. It appears because while it provided Nightwatch with a nice API for it to run commands an queries, it’s completely oblivious to whether or not it was expected. In order to get some nice check marks (or red exclamation marks), we need to report SauceLabs about the outcomes.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/mikberg/ce463e09d6adf46f987c&quot;&gt;Here’s an example implementation&lt;/a&gt; in the form of a Gist, inspired by &lt;a href=&quot;https://github.com/18F/college-choice/blob/8029b46f1283ed94c7f13662689374c399ff6740/test/sauce.js&quot;&gt;this code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Edit your test to run the sauce function when it tears down:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sauce&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;../sauce&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;//...&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;tearDown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sauce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/saucelabs-results.png&quot; alt=&quot;Saucelabs results&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Awesome. Add some better tests, add more obscure browsers, like Android 4.0. Now, only be a little bit nervous about browsers on each commit, rather than terrified when releasing.&lt;/p&gt;
</description>
        <pubDate>Sat, 23 Jan 2016 13:59:43 +0000</pubDate>
        <link>http://mikbe.com/javascript/ci/testing/2016/01/23/zero-to-hero-with-end-to-end-testing.html</link>
        <guid isPermaLink="true">http://mikbe.com/javascript/ci/testing/2016/01/23/zero-to-hero-with-end-to-end-testing.html</guid>
        
        
        <category>javascript</category>
        
        <category>ci</category>
        
        <category>testing</category>
        
      </item>
    
      <item>
        <title>Writing Simple Unit Tests with Relay</title>
        <description>&lt;p&gt;Ever since I started using &lt;a href=&quot;http://facebook.github.io/relay/&quot;&gt;Relay&lt;/a&gt; in my React projects, code coverage has dropped significantly in their code bases. Testing Relay containers is not trivial, and the project definitively &lt;a href=&quot;https://github.com/facebook/relay/issues/161&quot;&gt;lacks a test tool&lt;/a&gt;. There I decided to make an effort and a write-up of my findings.&lt;/p&gt;

&lt;p&gt;Mock Relay gist: &lt;a href=&quot;https://gist.github.com/mikberg/07b4006e22aacf31ffe6&quot;&gt;https://gist.github.com/mikberg/07b4006e22aacf31ffe6&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;getting-started-mocking-relay&quot;&gt;Getting Started: Mocking Relay&lt;/h2&gt;

&lt;p&gt;To get any testing done, Relay must be mocked to prevent invariant violations such as this one:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Invariant Violation: RelayContainer: `Relay(Main)` was rendered without a valid route.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you’re using &lt;a href=&quot;https://facebook.github.io/jest/docs/manual-mocks.html#content&quot;&gt;Jest&lt;/a&gt;, then it’s both automatic and a piece of cake.&lt;/p&gt;

&lt;p&gt;If not, then mocking a dependency might be trickier, but if you’re using &lt;a href=&quot;http://webpack.github.io/&quot;&gt;Webpack&lt;/a&gt;, then I’ve got this trick up my sleeve:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// webpack.test.config.js (webpack config used in tests)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;alias&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&#39;react-relay&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* path to mock relay */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&#39;real-react-relay&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;/../node_modules/react-relay/&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In other words: During tests, importing &lt;code class=&quot;highlighter-rouge&quot;&gt;react-relay&lt;/code&gt; resolves to our mock Relay module, while the real Relay module is available as &lt;code class=&quot;highlighter-rouge&quot;&gt;real-react-relay&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using this, we can write our mock module like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Our mock Relay module&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Relay&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;real-react-relay&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;QL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Relay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;QL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/mikberg/07b4006e22aacf31ffe6&quot;&gt;I’ve published my mock Relay module as a gist&lt;/a&gt;, if you’re interested, heavily inspired by &lt;a href=&quot;https://github.com/facebook/relay/issues/161#issuecomment-134324986&quot;&gt;this comment to facebook/relay#161&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;testing-containers&quot;&gt;Testing Containers&lt;/h2&gt;

&lt;p&gt;Alrighty, we have successfully mocked Relay and are ready to write some actual tests. In the mock Relay module, that &lt;code class=&quot;highlighter-rouge&quot;&gt;createContainer&lt;/code&gt; simply returns the container class itself.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;createContainer&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;That makes rendering the component with fixtures super simple, we can just give it to the component as props:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fixtures&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;myid&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;hasNewNotifications&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;TestUtils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;renderIntoDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;MyContainer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fixtures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;We can now test that the component renders correctly with every possible data combination from Relay. We can also test static methods. Yay!&lt;br /&gt;
In order to test our Relay specs, the second argument sent to &lt;code class=&quot;highlighter-rouge&quot;&gt;Relay.createContainer&lt;/code&gt;, we modify the mock’s method to sneakily attach its own method to the container class:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;createContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;specs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/* eslint no-param-reassign:0 */&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getRelaySpecs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;specs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;component&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Testing becomes a breeze:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Test our prepareVariables method&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;variables&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;MyContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getRelaySpecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prepareVariables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;variables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Testing the execution of mutations is mentioned in the bottom of the article.&lt;/p&gt;

&lt;h2 id=&quot;testing-queries&quot;&gt;Testing Queries&lt;/h2&gt;

&lt;p&gt;Whether or not it is strictly necessary to test the Relay queries, the Relay.QL&lt;code class=&quot;highlighter-rouge&quot;&gt;…&lt;/code&gt; parts, is up for debate. You’ll probably be pretty safe leaving it out, as they are automatically validated against Relay’s schema.&lt;/p&gt;

&lt;p&gt;The real problem here is that the Babel Relay plugin &lt;a href=&quot;https://github.com/facebook/relay/blob/master/scripts/babel-relay-plugin/lib/getBabelRelayPlugin.js#L147&quot;&gt;transforms&lt;/a&gt; our queries &lt;em&gt;before&lt;/em&gt; they are evaluated by the Relay.QL function; thus it can’t easily be mocked or proxied. If we try to mock it, our mock won’t even be evaluated, because the whole expression is replaced before it’s evaluated.&lt;/p&gt;

&lt;p&gt;As far as I know, there’s not really any efficient way of testing the queries other than running tests on the objects they are transformed into.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// isMatch from lodash -- I&#39;m sure there&#39;s a library&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// implementing this method too, leave a note if you know one.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;findDeep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&#39;object&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({}.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;findDeep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// This is a pretty stupid test&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;queries&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;an&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;query&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MyContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getRelaySpecs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fragments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;needle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;fieldName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;findDeep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;viewerQuery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;isMatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;needle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It does increase the code coverage, though not in a very useful way.&lt;/p&gt;

&lt;h2 id=&quot;testing-mutations&quot;&gt;Testing Mutations&lt;/h2&gt;

&lt;p&gt;Most of the mutation objects is straight forward to test. &lt;code class=&quot;highlighter-rouge&quot;&gt;getVariables&lt;/code&gt;, for instance, should be a breeze under most circumstances.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mutation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CreateEventMutation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inFixtures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mutation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getVariables&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inFixtures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;deep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;inFixtures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In most cases however, we’ll get a warning that parts of the fixtures we use to create the mutation really should have come from Relay. With components, we mocked &lt;code class=&quot;highlighter-rouge&quot;&gt;createContainer&lt;/code&gt; to return the component itself (with some extras), so that we could pass in fixtures as props. We’ll do a similar trick for mutations:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// In our mock Relay module&lt;/span&gt;
&lt;span class=&quot;kr&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Mutation&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Relay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Mutation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;_resolveProps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Configs from &lt;code class=&quot;highlighter-rouge&quot;&gt;getConfigs()&lt;/code&gt; can be a bit trickier to test. Since they are mostly about defining stuff, I guess that’s not the end of the world.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;correlates&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;viewer&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;returned&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;viewer&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fieldsChange&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mutation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getConfigs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;FIELDS_CHANGE&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fieldsChange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fieldIDs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inFixtures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;viewer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;be&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetched&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;requiredChildren&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;mutation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getConfigs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;REQUIRED_CHILDREN&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;findDeep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;requiredChildren&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;isMatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;findDeep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;isMatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;fieldName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}))).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;test-mutation-usage&quot;&gt;Test Mutation Usage&lt;/h2&gt;

&lt;p&gt;The last point is the touch point between our components and mutations. To get this tested, we can simply use Sinon to stub them into the behaviour that we want: calling either the &lt;code class=&quot;highlighter-rouge&quot;&gt;onSuccess&lt;/code&gt; or the &lt;code class=&quot;highlighter-rouge&quot;&gt;onFailure&lt;/code&gt; callback.&lt;/p&gt;

&lt;p&gt;But this would require us to stub the methods every time, which can become cumbersome. I opted to create a special class:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MockStore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;successResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;succeedWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;successResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;See the rest of the class &lt;a href=&quot;https://gist.github.com/mikberg/07b4006e22aacf31ffe6&quot;&gt;in the Github Gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That allows us to use Sinon to create stubs directing our code the way we want:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;redirects&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;success&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;sinon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;spy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Relay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;succeedWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;createEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_handleSubmit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;calledWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;events&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;logs&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;failure&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;sinon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;stub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;Relay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;failWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;getError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_handleSubmit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;calledWith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;restore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Combining all of the techniques above, we at least have a starting point for testing Relay applications. I must admit I still find testability a pain point with Relay apps, and simply because the unit tests work, I wouldn’t be completely confident about the app’s health before actually running it.&lt;/p&gt;

&lt;p&gt;I think it could be healthy to use some simple integration tests to verify that the application works.&lt;/p&gt;

</description>
        <pubDate>Tue, 19 Jan 2016 13:59:43 +0000</pubDate>
        <link>http://mikbe.com/javascript/react/relay/testing/2016/01/19/writing-simple-unit-tests-with-relay.html</link>
        <guid isPermaLink="true">http://mikbe.com/javascript/react/relay/testing/2016/01/19/writing-simple-unit-tests-with-relay.html</guid>
        
        
        <category>javascript</category>
        
        <category>react</category>
        
        <category>relay</category>
        
        <category>testing</category>
        
      </item>
    
  </channel>
</rss>
