Debugging During Testing With NodeJS¶
In the previous step we used testing as a way to develop our component without switching to a browser.
Sometimes our code has problems that require investigation with a debugger. For React, that usually means a trip to the browser to set a breakpoint and use the Chrome developer tools. Let’s show how the IDE’s debugger, combined with TDD, can make this investigation far more productive.
Cleanup¶
First, let’s remove some unused code from our first test,
renders without crashing
. Delete the last 3 lines and leave it as:
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App/>, div);
ReactDOM.unmountComponentAtNode(div);
});
Also, TSLint is complaining about sorting of our imports. Put your cursor
on the import of shallow
, hit Alt-Enter
, and tell the IDE to fix the
error.
Hello Parameter¶
We will start by using TDD to make our component’s greeting a bit more
dynamic. Start in the side-by-side mode described in the previous section,
with both App.tsx
and App.test.tsx
open.
First, add a method to the App
class:
public label() {
return 'Hello React';
}
Then, change the <h1>
to use the output of this method, using
autocompletion for the method name:
<h1>{this.label()}</h1>
We didn’t write a test first. That’s sort of ok: we didn’t change the
rendering itself. But we also didn’t test the method. Let’s do that now by
adding a test in App.test.tsx
:
it('generates a label', () => {
const a = new App({});
expect(a.label()).toBe('Hello React');
});
In this test we don’t need a component with TSX and a fake DOM etc. Its a
TypeScript method that returns a string. To conform to the React.Component
constructor signature, we pass in an empty object as props. Note how the IDE
gave us a placeholder reminder.
Let’s make the method slightly dynamic by passing in a name for the label,
then converting that name to uppercase. First, change our tests to the
behavior we expect. The generates a label
test needs its last line
changed to:
expect(a.label('React'))
.toBe('Hello REACT');
Our tests now break so we need to implement this feature. The <h1>
, like
the test, needs to pass in a value:
<h1>{this.label('React')}</h1>
Now it’s just a matter of changing the method to accept an argument, then uppercasing the return value:
public label(name) {
return `Hello ${name.toUpperCase()}`;
}
Note that the IDE has a quick fix, via Alt-Enter
, to convert the string
to an ES6 template string (the backticks.)
With that, our tests pass, but the TypeScript compiler is angry: the name
argument doesn’t have a supplied type. Let’s fix that:
public label(name: string) {
return `Hello ${name.toUpperCase()}`;
}
Stop at Breakpoint¶
Let’s see debugging in action. Imagine we pass in a number and we can’t figure out why our method is failing.
Let’s do so. In the last generates a label
test, change the argument to
a.label(42)
.
First, note that TypeScript told our test that the supplied value was not assignable to a string. This is the beauty of TypeScript. Especially in test-writing, it helps you “fail faster”. Meaning, when paired with a smart IDE, it moves the failure directly under your eyeballs, in the most immediate location…the place where you typed it. Moreover, it provides very specific error messages.
Let’s go ahead and debug this. Click in the gutter beside that line to set a breakpoint. Then right-click on the test in the tool window and run it under the debugger. Execution stops on that line. We can then step into our method call.
Execution stops in our method. We can inspect the local values and see that
name
is 42
.
We can now poke and prod our code interactively, in the execution context
where it fails. This is a very productive development cycle: write tests,
when stuck, use the debugger. No flailing around with console.log
in a
browser’s dev tools window.
Let’s clean up:
- Click the red square to stop the debugger
- Close the Debugger tool tab window
- Click the red circle to clear the breakpoint
- Change the test’s label argument from
42
back toReact
- Re-open the Run Tool window