Zenn にDenoのめちゃくちゃ良さげなテキスト(Effective Deno )が公開されていたので、それを読みながらDenoを触ってみた
いい感じのテーマが思い浮かばなかったのでFizzBuzz問題を実装することにした
「1から100までの数字を画面に表示する。ただし、3の倍数のときは数字の代わりにFizzと表示し、5の倍数のときは数字の代わりにBuzzと表示し、15の倍数のときは数 字の代わりにFizzBuzzと表示する」
Denoの環境 🔗
前に書いた記事(DenoでHello, World!
)同様、Dockerで用意する
.bashrcに記述して、使える状態にした
Denoのバージョンは触った時点で最新の1.9.2を使った
deno () {
docker run \
--interactive \
--tty \
--rm \
--volume $PWD:/app \
--volume $HOME/.deno:/deno-dir \
--workdir /app \
hayd/ubuntu-deno:1.9.2 \
deno "$@"
}
$ deno --version
deno 1.9.2 (release, x86_64-unknown-linux-gnu)
v8 9.1.269.5
typescript 4.2.2
実装 🔗
仮のfizzbuzz関数の実装 🔗
まずはfizzbuzz関数のガワだけを作る
受け取った引数の値を文字列にして返す
export function fizzbuzz(number: number): string {
return String(number);
}
本来、Fizz
,Buzz
,FizzBuzz
はString型で、数値はNumber型で返してあげた方がいい気がするけど、今回はすべてString型で返すことにする
テストの実装 🔗
fizzbuzz関数のガワだけできたので、先にテストを書く
import { assertEquals } from 'https://deno.land/[email protected]/testing/asserts.ts';
import { fizzbuzz } from './fizzbuzz.ts';
Deno.test('fizzbuzz(1)', () => {
assertEquals(fizzbuzz(1), '1');
});
Deno.test('fizzbuzz(3)', () => {
assertEquals(fizzbuzz(3), 'Fizz');
});
Deno.test('fizzbuzz(5)', () => {
assertEquals(fizzbuzz(5), 'Buzz');
});
Deno.test('fizzbuzz(15)', () => {
assertEquals(fizzbuzz(15), 'FizzBuzz');
});
テストの実行 🔗
deno test
で実行できる
もちろんString型にして返すだけなので、1の場合しかテストは通らない
$ deno test
running 4 tests
test fizzbuzz(1) ... ok (4ms)
test fizzbuzz(3) ... FAILED (4ms)
test fizzbuzz(5) ... FAILED (2ms)
test fizzbuzz(15) ... FAILED (1ms)
failures:
fizzbuzz(3)
AssertionError: Values are not equal:
[Diff] Actual / Expected
- "3"
+ "Fizz"
at assertEquals (https://deno.land/[email protected]/testing/asserts.ts:222:9)
at file:///app/fizzbuzz_test.ts:9:3
at asyncOpSanitizer (deno:runtime/js/40_testing.js:37:15)
at resourceSanitizer (deno:runtime/js/40_testing.js:73:13)
at Object.exitSanitizer [as fn] (deno:runtime/js/40_testing.js:100:15)
at TestRunner.[Symbol.asyncIterator] (deno:runtime/js/40_testing.js:272:24)
at AsyncGenerator.next (<anonymous>)
at Object.runTests (deno:runtime/js/40_testing.js:347:22)
at async file:///app/$deno$test.ts:3:1
fizzbuzz(5)
AssertionError: Values are not equal:
[Diff] Actual / Expected
- "5"
+ "Buzz"
at assertEquals (https://deno.land/[email protected]/testing/asserts.ts:222:9)
at file:///app/fizzbuzz_test.ts:13:3
at asyncOpSanitizer (deno:runtime/js/40_testing.js:37:15)
at resourceSanitizer (deno:runtime/js/40_testing.js:73:13)
at Object.exitSanitizer [as fn] (deno:runtime/js/40_testing.js:100:15)
at TestRunner.[Symbol.asyncIterator] (deno:runtime/js/40_testing.js:272:24)
at AsyncGenerator.next (<anonymous>)
at Object.runTests (deno:runtime/js/40_testing.js:347:22)
at async file:///app/$deno$test.ts:3:1
fizzbuzz(15)
AssertionError: Values are not equal:
[Diff] Actual / Expected
- "15"
+ "FizzBuzz"
at assertEquals (https://deno.land/[email protected]/testing/asserts.ts:222:9)
at file:///app/fizzbuzz_test.ts:17:3
at asyncOpSanitizer (deno:runtime/js/40_testing.js:37:15)
at resourceSanitizer (deno:runtime/js/40_testing.js:73:13)
at Object.exitSanitizer [as fn] (deno:runtime/js/40_testing.js:100:15)
at TestRunner.[Symbol.asyncIterator] (deno:runtime/js/40_testing.js:272:24)
at AsyncGenerator.next (<anonymous>)
at Object.runTests (deno:runtime/js/40_testing.js:347:22)
at async file:///app/$deno$test.ts:3:1
failures:
fizzbuzz(3)
fizzbuzz(5)
fizzbuzz(15)
test result: FAILED. 1 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out (11ms)
正しく動くfizzbuzz関数に書き換える 🔗
テストが書けたので、fizzbuzz関数の中身を実装する
export function fizzbuzz(number: number): string {
if (number % 15 == 0)
return 'FizzBuzz';
else if (number % 3 == 0)
return 'Fizz';
else if (number % 5 == 0)
return 'Buzz';
else
return String(number);
}
$ deno test
Check file:///app/$deno$test.ts
running 4 tests
test fizzbuzz(1) ... ok (4ms)
test fizzbuzz(3) ... ok (1ms)
test fizzbuzz(5) ... ok (1ms)
test fizzbuzz(15) ... ok (1ms)
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (8ms)
テストが無事通った
メインのコードを書く 🔗
fizzbuzz関数が無事完成したので、「1から100までの数字を画面に表示する。ただし、3の倍数のときは数字の代わりにFizzと表示し、5の倍数のときは数字の代わりにBuzzと表示し、15の倍数のときは数字の代わりにFizzBuzzと表示する」コードを書く
import { fizzbuzz } from './fizzbuzz.ts';
for (let i = 1; i <= 100; i++) {
console.log(fizzbuzz(i));
}
$ deno run app.ts
Check file:///app/app.ts
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
... 省略 ...
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
無事完成
フォーマッタを掛ける 🔗
特にコーディングルールを読まずに普段のRubyを書くように書いただけなので、フォーマッタを掛ける
deno fmt
でフォーマットしてくれる
$ deno fmt
/app/app.ts
/app/fizzbuzz.ts
/app/fizzbuzz_test.ts
Checked 4 files
そこそこ修正された
# fizzbuzz.ts
export function fizzbuzz(number: number): string {
- if (number % 15 == 0)
- return 'FizzBuzz';
- else if (number % 3 == 0)
- return 'Fizz';
- else if (number % 5 == 0)
- return 'Buzz';
- else
+ if (number % 15 == 0) {
+ return "FizzBuzz";
+ } else if (number % 3 == 0) {
+ return "Fizz";
+ } else if (number % 5 == 0) {
+ return "Buzz";
+ } else {
return String(number);
+ }
}
# fizzbuzz_test.ts
-import { assertEquals } from 'https://deno.land/[email protected]/testing/asserts.ts';
-import { fizzbuzz } from './fizzbuzz.ts';
+import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
+import { fizzbuzz } from "./fizzbuzz.ts";
-Deno.test('fizzbuzz(1)', () => {
- assertEquals(fizzbuzz(1), '1');
+Deno.test("fizzbuzz(1)", () => {
+ assertEquals(fizzbuzz(1), "1");
});
-Deno.test('fizzbuzz(3)', () => {
- assertEquals(fizzbuzz(3), 'Fizz');
+Deno.test("fizzbuzz(3)", () => {
+ assertEquals(fizzbuzz(3), "Fizz");
});
-Deno.test('fizzbuzz(5)', () => {
- assertEquals(fizzbuzz(5), 'Buzz');
+Deno.test("fizzbuzz(5)", () => {
+ assertEquals(fizzbuzz(5), "Buzz");
});
-Deno.test('fizzbuzz(15)', () => {
- assertEquals(fizzbuzz(15), 'FizzBuzz');
+Deno.test("fizzbuzz(15)", () => {
+ assertEquals(fizzbuzz(15), "FizzBuzz");
});
# app.ts
-import { fizzbuzz } from './fizzbuzz.ts';
+import { fizzbuzz } from "./fizzbuzz.ts";
for (let i = 1; i <= 100; i++) {
console.log(fizzbuzz(i));
}
CIを用意する 🔗
GitHub Actionsでテストやリンタが自動で実行されるようにセットアップする
name: ci
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: denoland/setup-deno@main
with:
deno-version: "1.9.2"
- name: Run fmt
run: |
deno fmt --check
- name: Run lint
run: |
deno lint --unstable
- name: Run tests
run: |
deno test -A
ちゃんと動いた良き
first commit · ytkg/deno_fizzbuzz@d2e6104
リポジトリ 🔗
今回やった内容をGitHubにあげた