Translate

Monday, 24 August 2020

How to Use Deno’s Built-in Tools

How to Use Deno’s Built-in Tools

One surprising difference between Deno and Node.js is the number of tools built into the runtime. Other than a Read-Eval-Print Loop (REPL) console, Node.js requires third-party modules to handle most indirect coding activities such as testing and linting. Deno provides almost everything you need out of the box.

Before we begin, a note. Deno is new! Use these tools with caution. Some may be unstable. Few have configuration options. Others may have undesirable side effects such as recursively processing every file in every subdirectory. It’s best to test tools from a dedicated project directory.

Install Deno

Install Deno on macOS or Linux using the following terminal command:

curl -fsSL https://deno.land/x/install/install.sh | sh

Or from Windows Powershell:

iwr https://deno.land/x/install/install.ps1 -useb | iex

Further installation options are provided in the Deno manual.

Enter deno --version to check installation has been successful. The version numbers for the V8 JavaScript engine, TypeScript compiler, and Deno itself are displayed.

Upgrade Deno

Upgrade Deno to the latest version with:

deno upgrade

Or upgrade to specific release such as v1.3.0:

deno upgrade --version 1.30.0

Most of the tools below are available in all versions, but later editions may have more features and bug fixes.

Deno Help

A list of tools and options can be viewed by entering:

deno help

Read-Eval-Print Loop (REPL)

Like Node.js, a REPL expression evaluation console can be accessed by entering deno in your terminal. Each expression you enter returns a result or undefined:

$ deno

Deno 1.3.0
exit using ctrl+d or close()
> const w = 'World';
undefined
> w
World
> console.log(`Hello ${w}!`);
Hello World!
undefined
> close()

$

Previously entered expressions can be re-entered by using the cursor keys to navigate through the expression history.

Dependency Inspector

A tree of all module dependencies can be viewed by entering deno info <module> where <module> is the path/URL to an entry script.

Consider the following lib.js library code with exported hello and sum functions:

// general library: lib.js

/**
 * return "Hello <name>!" string
 * @module lib
 * @param {string} name
 * @returns {string} Hello <name>!
 */
export function hello(name = 'Anonymous') {

  return `Hello ${ name.trim() }!`;

};

/**
 * Returns total of all arguments
 * @module lib
 * @param {...*} args
 * @returns {*} total
 */
export function sum(...args) {

  return [...args].reduce((a, b) => a + b);

}

These can be used from a main entry script, index.js, in the same directory:

// main entry script: index.js

// import lib.js modules
import { hello, sum } from './lib.js';

const
  spr = sum('Site', 'Point', '.com', ' ', 'reader'),
  add = sum(1, 2, 3);

// output
console.log( hello(spr) );
console.log( 'total:', add );

The result of running deno run ./index.js:

$ deno run ./index.js

Hello SitePoint.com reader!
total: 6

The dependencies used by index.js can be examined with deno info ./index.js:

$ deno info ./index.js

local: /home/deno/testing/index.js
type: JavaScript
deps:
file:///home/deno/testing/index.js
  └── file:///home/deno/testing/lib.js

Similarly, the dependencies required by any module URL can be examined, although be aware the module will be downloaded and cached locally on first use. For example:

$ deno info https://deno.land/std/hash/mod.ts

Download https://deno.land/std/hash/mod.ts
Download https://deno.land/std@0.65.0/hash/mod.ts
Download https://deno.land/std@0.65.0/hash/_wasm/hash.ts
Download https://deno.land/std@0.65.0/hash/hasher.ts
Download https://deno.land/std@0.65.0/hash/_wasm/wasm.js
Download https://deno.land/std@0.65.0/encoding/hex.ts
Download https://deno.land/std@0.65.0/encoding/base64.ts
deps:
https://deno.land/std/hash/mod.ts
  └─┬ https://deno.land/std@0.65.0/hash/_wasm/hash.ts
    ├─┬ https://deno.land/std@0.65.0/hash/_wasm/wasm.js
    │ └── https://deno.land/std@0.65.0/encoding/base64.ts
    ├── https://deno.land/std@0.65.0/encoding/hex.ts
    └── https://deno.land/std@0.65.0/encoding/base64.ts

For further information, see the Deno Manual: Dependency Inspector.

Linter (Syntax Checker)

Deno provides a linter to validate JavaScript and TypeScript code. This is an unstable feature which requires the --unstable flag, but no files will be altered when it’s used.

Linting is useful to spot less obvious syntax errors and ensure code adheres with your team’s standards. You may already be using a linter such as ESLint in your editor or from the command line, but Deno provides another option in any environment where it’s installed.

To recursively lint all .js and .ts files in the current and child directories, enter deno lint --unstable:

$ deno lint --unstable

(no-extra-semi) Unnecessary semicolon.
};
 ^
    at /home/deno/testing/lib.js:13:1

Found 1 problem

Alternatively, you can specify one or more files to limit linting. For example:

$ deno lint --unstable ./index.js
$

For further information, see the Deno Manual: Linter. It includes a list of rules you can add to code comments to ignore or enforce specific syntaxes.

Test Runner

Deno has a built-in test runner for unit-testing JavaScript or TypeScript functions.

Tests are defined in any file named <something>test with a .js, .mjs, .ts, .jsx, or .tsx extension. It must make one or more calls to Deno.test and pass a test name string and a testing function. The function can be synchronous or asynchronous and use a variety of assertion utilities to evaluate results.

Create a new test subdirectory with a file named lib.test.js:

// test lib.js library

// assertions
import { assertEquals } from 'https://deno.land/std/testing/asserts.ts';

// lib.js modules
import { hello, sum } from '../lib.js';

// hello function
Deno.test('lib/hello tests', () => {

  assertEquals( hello('Someone'), 'Hello Someone!');
  assertEquals( hello(), 'Hello Anonymous!' );

});

// sum integers
Deno.test('lib/sum integer tests', () => {

  assertEquals( sum(1, 2, 3), 6 );
  assertEquals( sum(1, 2, 3, 4, 5, 6), 21 );

});

// sum strings
Deno.test('lib/sum string tests', () => {

  assertEquals( sum('a', 'b', 'c'), 'abc' );
  assertEquals( sum('A', 'b', 'C'), 'AbC' );

});

// sum mixed values
Deno.test('lib/sum mixed tests', () => {

  assertEquals( sum('a', 1, 2), 'a12' );
  assertEquals( sum(1, 2, 'a'), '3a' );
  assertEquals( sum('an', null, [], 'ed'), 'annulled' );

});

To run all tests from all directories, enter deno test. Or run tests stored in a specific directory with deno test <dir>. For example:

$ deno test ./test

running 4 tests
test lib/hello tests ... ok (4ms)
test lib/sum integer tests ... ok (2ms)
test lib/sum string tests ... ok (2ms)
test lib/sum mixed tests ... ok (2ms)

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (11ms)

$

A --filter string or regular expression can also be specified to limit tests by name. For example:

$ deno test --filter "hello" ./test

running 1 tests
test lib/hello tests ... ok (4ms)

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 3 filtered out (5ms)

Longer-running tests can be stopped on the first failure by passing a --failfast option.

For further information, see the Deno Manual: Testing. A few third-party test modules are also available, including Merlin and Ruhm, but these still use Deno.test beneath the surface.

Continue reading How to Use Deno’s Built-in Tools on SitePoint.



No comments:

Post a Comment