readline의 노드를 사용합니다.js 간단한 표준 입력 출력과 모듈 테스트

컨디션

  • node.js 15.14.0
  • npm 7.11.1
  • typescript 4.2.4
  • ts-node 9.1.1
  • jest 26.6.3
  • ts-jest 26.5.5
  • 개시하다


    node.js 표준으로 수신 처리 대상을 입력하고 가공 후 표준 출력을 쓰는 프로그램입니다.
    나는 그때 시험을 쓰는 데 좀 빠져서 여기서 공유한다.

    간단한 표준 입력과 출력을 처리하는 노드입니다.프로그램 설계


    예를 들면 다음과 같은 것을 고려해 보자.
    공백 문자열을 구분 문자로 구분하고 여러 열을 입력합니다.
    문자열이 공백이 되기 전에 키를 만들고,value 모음집을 만듭니다.
    그러나 키가 이미 나타나면value는 무시됩니다.(첫 번째value 결과)
    마지막으로 키-value 모음집을 json 문자열로 표준 출력에 출력합니다.
    test.txt
    hello world
    foo baz
    hoge fuga
    hoge piyo
    
    npx --silent ts-node index.ts < test.txt > result.json
    
    result.json
    {"hello":"world","foo":"baz","hoge":"fuga"}
    
    표준 입력과 출력을 사용하면 이렇게 입력을 간단하게 수신하고 파이프를 사용하여 출력을 jq 등 다른 프로그램으로 전달하는 것이 쉽다.
    Node.js의readline 모듈을 사용하여 간단한 프로그램을 쓰면 이런 느낌인가요?[1]
    index.ts
    import * as readline from "readline";
    
    const r = readline.createInterface({
      input: process.stdin,
      terminal: false,
    });
    
    const result: { [key in string]: string } = {};
    
    r.on("line", (line) => {
      const elements = line.split(" ");
      result[elements[0]] = result[elements[0]] ?? elements[1];
    });
    
    r.on("close", () => {
      console.log(JSON.stringify(result));
    });
    

    테스트


    절차를 쓴 후 시험을 쓰는 것은 세상에서 흔히 있는 일이다.
    이번에는 이렇게 썼어요.
    환경에 설명된 대로 테스트 프레임워크는 Jest입니다.
    index.test.ts
    import { sendLine, sendClose } from "./mock-stdin";
    
    test("input lines has duplicate key", () => {
      // given
      const spyConsoleLog = jest.spyOn(console, "log");
    
      // when
      require("./index");
      sendLine("hello world");
      sendLine("foo baz");
      sendLine("hoge fuga");
      sendLine("hoge piyo");
      sendClose();
    
      // then
      expect(spyConsoleLog).toBeCalledWith(
        '{"hello":"world","foo":"baz","hoge":"fuga"}'
      );
    });
    
    mock-stdin.ts
    let sendLine: (line: string) => void;
    let sendClose: () => void;
    
    jest.mock("readline", () => {
      return {
        createInterface: () => {
          return {
            on: (event: string, callback: (...args: any) => void) => {
              switch (event) {
                case "line":
                  sendLine = callback;
                  break;
                case "close":
                  sendClose = callback;
                  break;
              }
            },
          };
        },
      };
    });
    
    export { sendLine, sendClose };
    
    표준 입력 출력 부분과 논리 부분은 분리되어 논리만 테스트해도 완전히 OK입니다.
    차라리 보통 그렇게 하는 게 낫겠지만 이번에는 이렇게 했어요.

    최후


    jest의 mock이 강하기 때문에 이런 일도 할 수 있다.
    하지만 과도하게 사용하면 결과가 무엇일지 주의하세요.[2]

    창고.


    이번 샘플 프로그램의 창고는 여기.입니다.
    각주
    예상치 못한 입력에서 오류가 발생하기 쉬운 코드입니다. 눈을 감아 주십시오↩︎
    스스로 끊다↩︎

    좋은 웹페이지 즐겨찾기