TestIt

หลังจากเริ่มจัดการ Dev Process จริงจังสิ่งหนึ่งที่เป็นปัญหาต้ังแต่เข้าไปในทีมคือ unit test เพราะไม่มีใครเคยทำมาก่อนในฝั่ง Javascript มีบ้างก็เป็นการทดลองรวมๆ มากกว่า เวลาจะเรียกทีต้อง start server เรียกได้แทบฝันร้าย เรียกแล้วผ่านไม่ผ่าน ไม่มี format ตายตัวรันที Terminal เต็มไปด้วย Text วันแรกๆ เลยทดลองหา Test framework ที่ถูกใจ ใช้ง่าย ใช้ได้ทั้ง client server ก่อนเลย

รอบแลกคิดว่าจะใช้ nodeunit เพราะว่าสามารถใช้ node.js มีผลลัพธ์ให้เห็นสวยงาม แต่พอเอาไปใช้กับ test เก่าที่บางส่วนต้องเรียกบน browser เริ่มเห็นลางร้ายเพราะต้องแยก code test ดีๆ ให้ทำงานบน browser หาอยู่หนึ่งวันยอมแพ้ หาตัวเลือกอื่นก็เปิด wiki หาว่า Javascript มี Test framework อะไรใช้ได้บ้างก่อนเลย ไล่เปิดเว็บทีละอันดูว่าใช้งานยังไง จนมาเจอ TestIt เห็นแล้วถูกใจ ลองเอามาใช้เลย

ติดตั้งเสร็จผ่าน npm แก้ unit test ทั้งหมดทดลองรัน ผลสวยงาม แม้ความสามารถจะไม่เทียบเท่า nodeunit แต่สิ่งที่ได้มาแทนคือเรียกใช้งานบน Browser ได้ก็เริ่มทดลองกับน้อง นั่งเขียนคู่กันไปเรื่อย วันแรกก็เจอปัญหาเลย เริ่มจาก Asynchronous call เพราะปกติมักเขียนแบบนี้ใน nodeunit

var testCase = require('nodeunit').testCase;
var http = require('http');

module.exports = testCase({
  setUp: function (callback) {
    // setup
    callback();
  },
  tearDown: function (callback) {
    // clean up
    callback();
  },
  test1: function (test) {
    var options = {
      host: 'www.llun.in.th',
      port: 80,
      path: '/'
    };

    http.get(options, function(res) {
      test.equals(200, res.statusCode);
      test.done();
    });
  }
});

จาก code ด้านบนเวลา assert ก็จะวางไว้ใน callback function ตรงๆเลย พร้อมบอกว่าจะจบตรงไหน แต่พอเปลี่ยนเป็น TestIt ต้องแก้เป็น

var testCase = require('test_it');
var http = require('http');

testCase('testName', {
  'before each': function(test) {
    // setup
  },
  'after each': function(test) {
    // clean up
  },
  test1: function (test) {
    var options = {
      host: 'www.llun.in.th',
      port: 80,
      path: '/'
    };

    var response;

    http.get(options, function(res) {
      response = res.statusCode;
    });

    test.waitFor(
      function(time) {
        // return true or false to tell testit got result
        return response;
      },
      function() {
        test.assertEqual(200, response);
      });
  }
});

code ยาวขึ้นหน่อยแต่มีสาเหตุที่ต้องทำแบบนี้เนื่องจากเวลา assert แล้วได้ผลลัพธ์เป็น false สิ่งที่ test.assert ทำคือสร้าง Exception ขึ้นมาแล้ว Throw ขึ้นมาหา Runner ที่เป็นคนเรียก test นี้อีกทีแต่ function ที่เป็น callback ของ asynchronous method บางครั้งไม่สามารถ Throw ไปหา Runner ได้(รอผู้เชี่ยวชาญเรื่อง JS scope มาตอบอีกที) บางครั้ง TestIt เลยตอบออกมาเป็น undefined และหยุดทำงานไปดื้อๆ หาสาเหตุมาตั้งนานถึงรู้วิธีใช้

แต่นอกจาก async call ที่เหลือก็ประทับใจดี จะมีติดใจอีกนิดหน่อยก็ตรงที่เวลาที่จะเรียก test unit เป็นชุดมีบางอย่างที่มันใช้ร่วมกันแล้วทำให้ผลลัพธ์ต่างจากการเรียกแยกไป ตอนนี้พยายามหาสาเหตุอยู่ยังหาไม่เจอ ถ้าหาเจอคิดว่าคงได้แก้ TestIt ตรงๆ นอกจากนี้ก็มีปัญหาเรื่องผลลัพธ์ที่เวลามีปัญหาโดยเฉพาะ Error มันจะไม่บอกว่ามี Exception อะไรเกิดขึ้นเหมือนอยู่บรรทัดที่เท่าไหร่ nodeunit ต้องไปไล่หาเอาเอง รวมทั้งเวลา fail ด้วย เป็นแค่สองอย่างที่ยังมีปัญหาอยู่

จริงๆ ตอนนี้ยังมีความคิดอีกอย่างว่าจะใช้ unit test แยกระหว่างฝั่ง client กับ server แต่ถ้ายังแก้ปัญหา TestIt อย่างนี้ได้เรื่อยๆ ก็คงไม่ต้องแล้วใช้ TestIt ตัวเดียวอยู่

About llun

Just a programmer

, ,