Hệ thống kiểm tra Javascript. Mã JavaScript đơn vị kiểm tra: chiến lược, thư viện, công cụ

Kiểm tra mã của bạn- một chu trình phát triển phần mềm tích hợp. Các nhóm phát triển mới làm quen thường đánh giá thấp vai trò của nó và kiểm tra chức năng của ứng dụng theo cách cũ - “nó hoạt động, nhưng không sao cả”. Không sớm thì muộn, chiến lược này cũng thất bại và vô số nhiệm vụ bắt đầu áp đảo trình theo dõi lỗi. Để không rơi vào một cái bẫy tương tự, tôi khuyên bạn nên một lần và mãi mãi đối phó với các sắc thái của thử nghiệm JavaScript mã số.

JavaScript không giống nhau

Hôm nay JavaScript Không chỉ là một ngôn ngữ để mang lại giao diện của một ứng dụng vào cuộc sống. Những ngày mà JavaScript được sử dụng để nói đùa hoặc để tạo thực đơn đã không còn nữa. Bây giờ nó là một ngôn ngữ độc lập hoạt động tốt như nhau trên cả máy khách và máy chủ. Vai trò của JavaScript đã tăng lên đáng kể, có nghĩa là khi viết mã, bạn không nên ngần ngại sử dụng các thực hành đã được chứng minh trong các ngôn ngữ lập trình khác.

Ý tôi là gì về thực hành và mô hình? Tất nhiên là một mẫu kiến ​​trúc MVC (bộ điều khiển chế độ xem mô hình) và các mô hình tổ chức mã. Bằng cách làm theo các thủ thuật đơn giản này, bạn có thể viết mã tốt hơn không chỉ dễ bảo trì mà còn có khả năng kiểm tra tự động.

Lỗi của hầu hết người thử nghiệm

Không có gì bí mật khi cách kiểm tra phổ biến nhất luôn là kiểm tra bằng "mắt" tầm thường. Bản chất của nó rất đơn giản - đã viết vài nghìn dòng mã, giải quyết vấn đề và khởi chạy sáng tạo của bạn. Đã chơi, đã nhấp - mọi thứ dường như hoạt động, bạn có thể tải nó lên máy chủ chiến đấu. Mọi thứ đều cực kỳ đơn giản và với sự quan tâm đúng mức của nhà phát triển (lý tưởng nhất là một cá nhân có biệt danh "người thử nghiệm"), bạn có thể dựa vào hoạt động chính xác của ứng dụng.

Trong thực tế, mọi thứ diễn ra hơi khác một chút. Theo quy định, không có người thử nghiệm riêng biệt. Bản thân nhà phát triển cố gắng kiểm tra chức năng của chương trình bằng cách thực hiện chuỗi hành động được chỉ định trong phân công kỹ thuật. Các giả mạo mã nâng cao hơn tự động hóa loại thử nghiệm tích hợp này với những thứ như Selenium.

Do đó, lập trình viên chỉ có thể phát hiện ra các lỗi thô nhất. Thật không may, các hành động "ngu ngốc" và "ngoài ý muốn" của người dùng, cũng như các động thái khôn lanh trong logic kinh doanh, trong 99% trường hợp đều bị bỏ lại phía sau.

Sự hiện diện của một người riêng biệt trong con người của người thử nghiệm giải quyết vấn đề cũng một phần và cho đến một thời điểm nhất định. Ngay cả khi chúng tôi đặt sự chú ý kỹ thuật của anh ấy sang một bên đến từng chi tiết, chất lượng thử nghiệm của anh ấy sẽ có xu hướng bằng không khi ứng dụng phát triển. Hãy để tôi cho bạn một ví dụ từ thực tế.

Một lần tôi được giao phát triển một chương trình nhỏ. Về mặt chức năng, dự án tương tự như một CRM đơn giản nhất, được tôi triển khai trong thời gian ngắn nhất có thể. Sau khi nhận được thù lao đến hạn, tôi giao hết nguồn hàng cho khách hàng và quên mất dự án trong tám tháng. Sau đó, điều thú vị nhất bắt đầu. Khách hàng đã quyết định mở rộng nghiêm túc chức năng của chương trình và gọi cho tôi để được trợ giúp. Đương nhiên, tôi lấy nó và bắt đầu điêu khắc hết chức năng này đến chức năng khác. Ban đầu nó không có gì khó khăn, nhưng khi nói đến sự tích hợp tổng thể của chức năng, một loạt lỗi ồn ào lao về hướng của tôi. Các đoạn mã bắt đầu xung đột và bạn phải mất nhiều thời gian để giải quyết xung đột. "Chà, làm thế nào mà bạn không thấy rằng có vấn đề với ứng dụng của bạn?" - những độc giả chăm chú sẽ hỏi. Tôi đã bắt đầu nó, nhưng do thực tế là ứng dụng đã phát triển, tôi chỉ đơn giản là không có đủ thời gian và thần kinh để kiểm tra tất cả các chức năng hàng loạt. Tôi chỉ giới hạn bản thân để thử nghiệm các chức năng riêng lẻ và trả tiền rất hậu hĩnh cho việc này. Đạo lý của câu chuyện ngụ ngôn này là "Hãy coi thử nghiệm như một phần không thể thiếu của sự phát triển."

Bài kiểm tra đơn vị giống như một viên đạn bạc

Kiểm tra đơn vị là cách tốt nhất để bạn bớt căng thẳng và tăng cường đảm bảo rằng một số phần nhất định trong ứng dụng của bạn sẽ hoạt động. Nếu bạn chưa bao giờ bắt gặp từ khủng khiếp này, thì tôi sẽ giải thích nó một cách ngắn gọn. Các bài kiểm tra đơn vị cho phép bạn tự động hóa quá trình kiểm tra và kiểm tra mọi tính năng của ứng dụng của bạn.

Sau khi hoàn thành việc phát triển một chức năng mới (có thể viết các bài kiểm tra và trước khi bắt đầu phát triển), nhà phát triển viết mã đặc biệt để kiểm tra mã của mình. Mã thử nghiệm cần phải mô phỏng các tình huống khác nhau và trả về các giá trị. Ví dụ, chúng tôi đã viết một hàm để cắt bỏ khoảng trắng (trim). Để kiểm tra hiệu suất của nó, chúng tôi phải chuẩn bị một số bài kiểm tra cho phép chúng tôi khẳng định rằng:

  • khi truyền chuỗi "string" ở đầu ra, chúng ta sẽ nhận được "string";
  • khi vượt qua mốc thời gian "dòng 9", chúng ta nhận được "dòng 9" ở đầu ra;
  • Chúng tôi cũng có thể thêm thử nghiệm cho các tham số đầu vào khác (ví dụ: thay thế ký tự khoảng trắng bằng một tab). Nói chung, chúng ta càng kiểm tra mã tốt hơn và thấy trước các tùy chọn tiêu cực có thể xảy ra, thì càng có nhiều khả năng vào thời điểm quan trọng nhất, một ít tóc vẫn còn trên đầu.

    Trong thế giới JS, các bài kiểm tra thường được viết bằng các khuôn khổ chuyên dụng. Họ có mọi thứ bạn cần để mô tả các thử nghiệm, cũng như các công cụ ít nghèo nàn nhất để tổ chức các báo cáo về tiến trình thử nghiệm.

    Tests! = Mã bổ sung

    Các nhà phát triển kiểm thử không phải đơn vị thích tranh luận rằng kiểm thử đơn vị yêu cầu mã bổ sung được viết và duy trì. Họ nói rằng thời hạn trong các dự án thực tế thường rất chặt chẽ và đơn giản là không có cách nào để viết mã bổ sung.

    Vì thời hạn quá hạn hẹp, tôi đồng ý, nhưng tôi sẵn sàng tranh luận về mã bổ sung. Một mặt, có, các bài kiểm tra yêu cầu mã bổ sung và do đó thời gian để viết nó. Mặt khác, mã này đóng vai trò của túi khí trong xe và chắc chắn sẽ mang lại hiệu quả khi ứng dụng phát triển.

    Khi không có thời gian và mong muốn từ chối những bài kiểm tra viết dày vò - hãy suy nghĩ ba lần. Có lẽ, trong trường hợp này, thích hợp hơn là chỉ bao gồm các phần phức tạp nhất của mã bằng các bài kiểm tra, chứ không nên từ bỏ hoàn toàn việc kiểm tra. Hãy luôn hướng tới tương lai, như thể trong một tháng, chương trình của bạn có thể phát triển đến mức chưa từng có.

    Không phải tất cả mã đều được kiểm tra

    Tại sao tôi lại tranh luận rằng bạn cần phải suy nghĩ về việc thử nghiệm trước khi viết mã chính? Bởi vì mã ban đầu dự định được bao phủ bởi các bài kiểm tra đơn vị được viết theo một phong cách hơi khác. Không phải tất cả các mã đều có thể được kiểm tra. Mã kết hợp logic và trình bày, và thậm chí được nhồi nhét ở nơi không thể kiểm tra bình thường. Ở đây, tôi luôn khuyên bạn nên tuân theo một số quy tắc đơn giản:

  • Không cần phải viết các hàm lớn. Mỗi chức năng nên giải quyết một vấn đề, không phải 100.500 tình huống có thể xảy ra. Ví dụ, bạn không cần phải treo mã để gửi dữ liệu đến máy chủ trong chức năng chịu trách nhiệm chuẩn bị chúng;
  • Một hàm có hơn 10 dòng mã rất có thể là một hàm không tốt;
  • Logic và biểu diễn không bao giờ được đi cùng nhau;
  • QUnit là một thể loại kinh điển của những người tạo ra jQuery

    QUnitđặc biệt phổ biến trong số các nhà phát triển JavaScript. Thứ nhất, nó được ghi chép đầy đủ và dễ sử dụng, thứ hai, nó được tạo ra bởi các tác giả jQuery. Thư viện thích hợp để kiểm tra cả mã dựa trên jQuery và JavaScript gốc.

    Bạn có thể tải xuống phiên bản QUnit mới nhất từ ​​trang web chính thức - http://qunitjs.com/. Thư viện được phân phối dưới dạng một tệp JS và CSS. Giả sử rằng bạn đã tìm ra tải các thành phần cần thiết, và nếu đúng như vậy, thì đã đến lúc viết một bài kiểm tra thử nghiệm. Chúng ta hãy thử kiểm tra hàm trim () đã đề cập ở trên.

    Để chứng minh các thử nghiệm, tôi đã tạo một dự án đơn giản với cấu trúc sau:

    Index.html - tệp chính sẽ hiển thị kết quả kiểm tra; - qunit-1.12.0.js - tệp thư viện qunit; - example.js - một tệp chứa mã để thử nghiệm (trong trường hợp của chúng tôi là mô tả của hàm trim ()); - test.js - tệp với các bài kiểm tra; - qunit-1.12.0.css - các kiểu thiết kế báo cáo với các thử nghiệm;

    Nội dung của các tệp index.html và test.js được hiển thị trong Liệt kê 1 và 2. Điều khiến chúng tôi quan tâm nhất là danh sách thứ hai, hiển thị khai báo của hàm đang được thử nghiệm (trim ()) và mã cho các thử nghiệm để xác minh rằng nó hoạt động. Hãy chú ý, bản thân hàm trim () có thể được đặt ở bất cứ đâu, tôi đưa nó vào danh sách thứ hai chỉ để tiết kiệm dung lượng trong nhật ký.

    Bây giờ chúng ta hãy xem xét bản thân các bài kiểm tra. Để thực hiện kiểm tra sức khỏe trên mã của chúng tôi, thư viện Qunit.js cung cấp cho chúng tôi một số phương pháp:

  • kiểm tra ()- trình bao bọc để mô tả thử nghiệm;
  • Vâng ()- câu lệnh cho phép bạn kiểm tra tính trung thực của tham số đầu tiên. Trong ví dụ của chúng tôi, tôi chuyển nó một cuộc gọi đến hàm trim () mà chúng tôi đã xác định và so sánh với giá trị mà tôi mong đợi nhận được. Nếu điều kiện là đúng, thử nghiệm được thông qua;
  • bình đẳng ()- phương pháp này cho phép bạn kiểm tra sự bằng nhau của các tham số thứ nhất và thứ hai. Xin lưu ý ngay rằng phương pháp này thực hiện kiểm tra lỏng lẻo, do đó, nó chỉ phù hợp với các giá trị vô hướng;
  • không công bằng () Là đối của bằng (). Được thực thi nếu giá trị đầu tiên không bằng giá trị thứ hai;
  • nghiêm ngặtEqual ()-Tương tự như bằng () với một sự khác biệt - nó sử dụng kiểm tra nghiêm ngặt (nghĩa là nó cũng kiểm tra kiểu dữ liệu);
  • notStrictEqual ()- phương thức đối lập với precisionEqual ();
  • deepEqual ()- phương thức cho các câu lệnh đệ quy, được sử dụng cho các nguyên thủy, mảng, đối tượng;
  • notDeepEqual ()- phương thức đối lập với deepEqual ();
  • tăng ()- một xác nhận để kiểm tra các hàm gọi lại đưa ra một ngoại lệ;
  • Trong danh sách thứ hai, tôi đã chỉ cho bạn cách áp dụng những phương pháp này vào thực tế. Nếu bạn chạy một trường hợp thử nghiệm trong biểu mẫu này, thì tất cả các thử nghiệm sẽ vượt qua thành công (xem hình tương ứng). Để thấy sự khác biệt giữa việc vượt qua các bài kiểm tra và không đạt, tôi đã sửa đổi một chút mã cho một bài kiểm tra. Vào dòng thử nghiệm bằng cách sử dụng nghiêm ngặtEqual () Tôi cố tình thêm một kết quả sai (xem hình tương ứng).

    Liệt kê 1. Nội dung của tệp index.html

    Thử nghiệm với QUnit

    Liệt kê 2. Kiểm tra tệp và hàm trim ()

    function trim (string) (return (string || "") .replace (/ ^ \ s + | \ s + $ / g, "");) test ("Kiểm tra hàm trim ()", function () (ok (trim ("test") == "test", "bớt khoảng trắng ở cuối"); ok (trim ("1") == "1", "nhiều khoảng trắng ở hai bên"); ok (trim ( "24") = "24", "dấu cách và tab ở hai bên"); bằng (trim (""), "", "Chuỗi trống"); nghiêm ngặt (trim ("] [aker")));

    Chúng tôi đã tìm ra cách kiểm tra các chức năng đơn giản. Dù sao, tôi không có gì thêm để thêm. Tiếp theo, bạn cần lấy mã thực và cố gắng tự viết các bài kiểm tra. Hãy xem xét một nhiệm vụ khác, thường phát sinh trước đây JavaScript-developers - kiểm tra các chức năng không đồng bộ. Một ứng dụng được nhồi nhét bằng mã JavaScript, 99% tương tác với phía máy chủ bằng cách sử dụng Ajax. Bạn cũng không thể bỏ chọn mã này, nhưng việc viết các bài kiểm tra sẽ trông hơi khác một chút. Hãy xem xét một ví dụ:

    AsyncTest ("myAsyncFunc ()", function () (setTimeout (function () (ok (myAsyncFunc () == true, "Dữ liệu đã chuyển thành công"); start ();), 500);));

    Sự khác biệt chính giữa ví dụ này và ví dụ trước là thay vì trình bao bọc thử nghiệm (), asyncTest () được sử dụng, do đó trực tiếp nói rằng tôi quan tâm đến việc kiểm tra thử nghiệm không đồng bộ. Sau đó, tôi bắt đầu thời gian chờ ở 500 ml. giây Trong thời gian này, hàm myAsyncFunc () sẽ truyền dữ liệu đến máy chủ thử nghiệm và nếu mọi thứ đều ổn, hãy trả về true. Đây là nơi mà khoảnh khắc thú vị nhất xuất hiện. Khi lệnh gọi tới asyncTest () xảy ra, luồng bị dừng và khi kết thúc quá trình kiểm tra, nó phải được bắt đầu bởi chính nó. Để kiểm soát luồng thực thi trong QUnit có phương thức start () và stop ().

    Kiểm tra các chức năng không đồng bộ với một thư viện QUnit là đủ đơn giản. Ví dụ cuối cùng mà tôi muốn xem qua có liên quan đến việc viết một bài kiểm tra thực hiện nhiều kiểm tra không đồng bộ. Câu hỏi chính đặt ra về vấn đề này trong các nhiệm vụ như vậy là đâu là nơi tối ưu để bắt đầu quy trình thực thi. Tài liệu chính thức đề xuất sử dụng một cái gì đó như:

    AsyncTest ("myAsyncFunc ()", function () (mong đợi (3); // Chúng tôi thực hiện ba lần kiểm tra ở đây ok (myAsyncFunc (), "Make the world better 1"); ok (myAsyncFunc (), "Làm cho thế giới tốt đẹp hơn 2 "); ok (myAsyncFunc ()," Làm cho thế giới tốt đẹp hơn 3 "); setTimeout (function () (start ();), 3000);));

    Kiểm tra các hành động tùy chỉnh

    Bạn nên nhớ rằng rất nhiều giao diện được viết bằng JavaScript. Ví dụ: một người dùng nhấp vào một ma cô và điều gì đó sẽ xảy ra để đáp ứng với nhấp chuột của anh ta. Có một lượng lớn mã "giao diện" như vậy trong các dự án và nó cũng cần được bao phủ bởi các bài kiểm tra. Hãy xem cách bạn có thể mô phỏng một lần nhấn phím tùy chỉnh và viết một bài kiểm tra riêng cho hành động này. Hãy tưởng tượng rằng chúng ta có một số chức năng ghi lại các phím đã nhấn. Tôi đã đưa mã của nó trong danh sách thứ ba:

    Liệt kê 3. Ghi nhật ký tổ hợp phím

    function KeyLogger (target) (if (! (this instanceof KeyLogger)) (trả về KeyLogger mới (target);) this.target = target; this.log =; var self = this; this.target.off ("keydown") .on ("keydown", function (event) (self.log.push (event.keyCode);));)

    Bây giờ chúng ta hãy thử kiểm tra chức năng này. Trước hết, trong phần nội dung của bài kiểm tra, chúng ta cần mô phỏng phím được nhấn. Cách dễ nhất để làm điều này là sử dụng thư viện jQuery, cho phép bạn tạo một sự kiện trong một vài dòng mã (xem Liệt kê 4).

    Liệt kê 4. Mã kiểm tra cho KeyLogger

    test ("KeyLogger test", function () (var event, $ doc = $ (document), key = KeyLogger ($ doc); event = $ .Event ("keydown"); event.keyCode = 9; $ doc. trigger (sự kiện); bằng (các phím.log.length, 1, "Đã ghi lại phím"); bằng (các phím.log [0], 9, "Tổ hợp phím với mã 9 được ghi lại");));

    Vào đầu danh sách với bài kiểm tra, tôi chuẩn bị một sự kiện để mô phỏng cách nhấn phím - "keydown". Chúng ta sẽ quan tâm đến việc nhấn phím Tab (mã số 9). Sau đó, sử dụng phương thức trigger (), tôi gửi sự kiện đã chuẩn bị sẵn, sau đó chúng tôi có thể bắt đầu thử nghiệm. Đầu tiên, chúng tôi kiểm tra bức tranh chung - xem một phím có được nhấn hay không, và sau đó, mã của nó.

    DOM dưới vỏ bọc của các bài kiểm tra

    Một lần Qunit.js cho phép bạn kiểm tra các hành động tùy chỉnh, sau đó việc viết các bài kiểm tra cho DOM cũng không có vấn đề gì. Đây thực sự là trường hợp và ví dụ dưới đây sẽ xác nhận lời nói của tôi. Tôi sẽ không bình luận về nó, chỉ cần xem qua mã và mọi thứ sẽ trở nên rõ ràng:

    Kiểm tra ("Thêm một phần tử div mới", function () (var $ fixture = $ ("# qunit-fixture"); $ fixture.append ("

    Đây là div mới
    "); bằng ($ (" div ", $ fixture) .length, 1," Đã thêm div mới thành công! ");));

    Phantom.JS - chạy thử nghiệm từ bảng điều khiển

    Viết bài kiểm tra bằng thư viện Qunit.js thuận tiện và đơn giản, nhưng sớm hay muộn bạn sẽ được ghé thăm bởi mong muốn bằng cách nào đó tự động hóa việc khởi chạy thử nghiệm và thu thập kết quả. Ví dụ: tôi có một máy ảo riêng cho doanh nghiệp này trong DigitalOcean, tôi chỉ có thể quản lý bằng cách sử dụng bảng điều khiển.

    Dự án phantom.js giải quyết vấn đề này khá dễ dàng. Đây không chỉ là một khuôn khổ khác để viết Bài kiểm tra đơn vị và một phiên bản giao diện điều khiển chính thức của động cơ WebKit... Nói một cách đơn giản, ứng dụng này giả lập một trình duyệt. Với sự trợ giúp của phantom.js, thực sự không chỉ có thể tự động hóa việc kiểm tra việc thực thi thử nghiệm mà còn giải quyết nhiều vấn đề sớm hay muộn nảy sinh trước nhà phát triển: nhận kết quả hiển thị các trang thành một tệp (png, jpg) , các chức năng giám sát mạng (tốc độ tải, hiệu suất tổng thể, v.v.), v.v.), mô phỏng các hành động của người dùng, v.v. Tôi khuyên bạn không nên lười biếng và đọc tài liệu chính thức cho dự án này, bạn chắc chắn sẽ tìm thấy một cái gì đó thú vị cho chính mình.

    Phantom.js có thể được biên dịch cho các nền tảng khác nhau (nix, mac OS X, windows). Nếu bạn phát triển mọi thứ trong Windows, thì không có vấn đề gì - hãy hợp nhất các tệp nhị phân và bắt đầu. Các vấn đề khởi động nhỏ có thể phát sinh nếu bạn đã cài đặt hai bộ điều hợp video, một trong số đó là NVidia. Trong trường hợp này, bạn sẽ phải sử dụng bản hack được mô tả trong thanh bên.

    Chúng ta hãy thử làm quen với phantom.js trong thực tế. Để bỏ qua phantom.js các bài kiểm tra được chuẩn bị trong phần cuối cùng và để có được kết quả thực thi trong bảng điều khiển, chúng ta cần một tập lệnh trình tải đặc biệt - run-qunit.js. Chúng tôi mở bảng điều khiển (tôi làm việc trên Windows, vì vậy tôi sử dụng cmd) và gõ lệnh ở định dạng:

    Phantom.exe<путь к run-qunit.js> <путь к странице с тестами>

    Trong trường hợp của tôi, lệnh khởi chạy xuất hiện như sau:

    E: \ soft \ phantomjs> phantomjs.exe E: \ temp \ testjsforx \ qunit \ run-qunit.js file: /// E: /temp/testjsforx/qunit/index.html Kết quả: Các thử nghiệm hoàn thành trong 2592 mili giây. .. 9 lần khẳng định 9 lần vượt qua, 0 lần thất bại.

    Tất cả các bài kiểm tra đều vượt qua

    Nó chắc chắn là cần thiết để kiểm tra mã và nó không quan trọng quy mô ứng dụng bạn tạo. Một lần nữa, tôi nhắc bạn rằng ngay cả những chương trình nhỏ nhất cũng biến thành những con quái vật vụng về, cần được bảo trì và hoàn thiện chức năng. Mã được kiểm tra kỹ lưỡng là chìa khóa thành công và chất lượng. Đúng vậy, không dễ để bắt đầu viết mã phù hợp cho các thử nghiệm tự động ngay lập tức, nhưng tin tôi đi, tất cả những đau khổ này sẽ được đền đáp bằng lãi suất trong tương lai. Đó là tất cả cho ngày hôm nay, chúc may mắn!

    Khi không có thời gian cho các bài kiểm tra

    Trong trường hợp không có thời gian, sẽ không có ý nghĩa gì khi viết các bài kiểm tra cho các hàm đơn giản (lấy cùng một phần () từ các ví dụ trong bài viết), tốt hơn là nên tập trung vào các phần quan trọng nhất của mã. Quy tắc tương tự cần được tuân theo khi viết mã thường xuyên thay đổi. Các điều khoản tham chiếu cho một dự án trực tiếp thường thay đổi và một số tính năng phải được cập nhật liên tục. Những thay đổi như vậy có thể dẫn đến những khoảnh khắc khó chịu - mã đã thay đổi hoạt động tốt với dữ liệu mới, nhưng mã cũ không tiêu hóa một cách tự nhiên. Để không mắc lỗi ở đây, tốt hơn hết là bạn nên bao gồm các chức năng như vậy bằng các bài kiểm tra ngay lập tức. Hãy nhớ một quy tắc đơn giản - không có thời gian để bao gồm toàn bộ mã bằng các bài kiểm tra, hãy che đi phần quan trọng nhất của nó.

    Các quy tắc kiểm tra tốt

  • Bài kiểm tra phải càng đơn giản càng tốt. Bài thi càng khó, càng dễ mắc lỗi;
  • Các bài kiểm tra nên được nhóm lại thành các mô-đun, để sau này dễ dàng tìm ra lỗi và có thể kiểm tra một số phần nhất định của ứng dụng;
  • Mỗi bài kiểm tra phải độc lập với các bài kiểm tra khác;
  • Luôn viết một bài kiểm tra riêng biệt mỗi khi phát hiện ra lỗi;
  • Sự cố Phantom.js trên Windows

    Nó chỉ xảy ra như vậy, nhưng tôi đã kiểm tra tất cả các ví dụ cho bài viết này không phải trong Linux, mà trong Windows 7. Hóa ra là phantom.js có một số vấn đề nhỏ khi làm việc trên các hệ thống sử dụng một số bộ điều hợp video. Trên máy tính xách tay của tôi, ngoài chip video tích hợp, NVidia vẫn bị treo và do phantom.js nên nó đã từ chối phản hồi lệnh phantom.exit (). Kết quả là, sau khi thực thi tập lệnh, tiến trình phantom.js không kết thúc công việc của nó và tiếp tục treo trong bộ nhớ. Cửa sổ đầu cuối cũng ngừng phản hồi các lệnh thoát (ctrl + c không giúp được gì).

    Nếu bạn gặp phải sự cố tương tự và dự định sử dụng phantom.js trên Windows, hãy sẵn sàng để thử lần hack tiếp theo. Mở Bảng điều khiển Nvidia. Tìm mục "Cài đặt 3D" trong cây. Ở phía bên phải, tùy chọn "Bộ điều hợp đồ họa ưu tiên" sẽ xuất hiện. Theo mặc định, giá trị của nó được đặt thành "Tự động chọn". Chúng tôi cần thay đổi nó thành "Bộ xử lý Nvidia Hiệu suất cao" hoặc "Phần cứng đồ họa tích hợp". Sau thủ thuật đơn giản này phantom.js bắt đầu cư xử ngoan ngoãn.

  • Cristian Johansen "Test-Driven JavaScript Development" là một trong số ít những cuốn sách xem xét JavaScript dưới góc độ của các bài kiểm tra viết;
  • John Rezing, Be'er Beebo "Bí mật của JavaScript Ninja" là một cuốn sách hay sẽ hữu ích chủ yếu cho các nhà phát triển JS có trình độ kinh nghiệm trung cấp. Cuốn sách trình bày chi tiết các vấn đề về cách viết mã trình duyệt chéo hiệu quả, các sắc thái của việc xử lý sự kiện và nhiều tính năng khác.
  • Bây giờ trang web có sẵn để kiểm tra kiến ​​thức về các chủ đề sau: Html, CSS, JavaScript, PHP, SQL.

    Mỗi bài kiểm tra bao gồm 10 câu hỏi về một chủ đề cụ thể. Trong mỗi câu hỏi, tôi cố gắng đề cập đến các lĩnh vực ứng dụng đa dạng nhất của một ngôn ngữ cụ thể để kiểm tra mức độ kiến ​​thức của bạn một cách cẩn thận nhất có thể.

    Tất nhiên, tất cả kiểm tra miễn phí và bất kỳ ai cũng có thể đi qua chúng.

    Quy trình kiểm tra:

    1. Theo liên kết " Bắt đầu thử nghiệm"ở bài kiểm tra tương ứng.
    2. Trả lời các câu hỏi được đặt ra bằng cách chọn thứ duy nhất lựa chọn đúng.
    3. Sau khi hoàn thành thử nghiệm, bạn sẽ thấy điểm số của bạn, số sai lầm, cũng như phân tích từng câu hỏi từ bột.

    Chú ý! Bạn sẽ không thể quay lại câu hỏi trước đó, vì vậy hãy suy nghĩ trước khi trả lời.

    Các bài kiểm tra hiện có sẵn

    1. Html

      • Tổng số bài kiểm tra đã vượt qua: 75424 người
      • Điểm trung bình: 2,83 trên 5điểm.

      Kiểm tra kiến ​​thức cơ bản Html... Bạn sẽ cần biết những điều cơ bản Thẻ HTML, cũng như việc sử dụng chúng có thẩm quyền. Nó cũng cần thiết để hiểu các tính năng của tiêu chuẩn. XHTML 1.1.

    2. CSS

      • Tổng số bài kiểm tra đã vượt qua: 32.828 người
      • Điểm trung bình: 3,37 trên 5điểm.

      Bài kiểm tra kiến ​​thức về những điều cơ bản CSS... Để vượt qua bài kiểm tra thành công, bạn phải biết các loại bộ chọn cơ bản (cú pháp của chúng), biết các thuộc tính cơ bản và các giá trị có thể có của chúng, đồng thời cũng biết mục đích của các phần tử giả phổ biến nhất.

    3. JavaScript

      • Tổng số bài kiểm tra đã vượt qua: 24845 người
      • Điểm trung bình: 3,31 trên 5điểm.

      Bài kiểm tra này kiểm tra kiến ​​thức của bạn về ngôn ngữ JavaScript. Các câu hỏi từ bài kiểm tra bao gồm các lĩnh vực ứng dụng khác nhau của ngôn ngữ đã cho. Có rất nhiều câu hỏi về việc hiểu các sắc thái "nhỏ". Đối với phần còn lại, bạn cần biết những điều cơ bản: làm việc với các biến, các hàm JavaScript cơ bản, mức độ ưu tiên của các hoạt động, v.v.

    4. PHP

      • Tổng số bài kiểm tra đã vượt qua: 33.239 người
      • Điểm trung bình: 3.03 trên 5điểm.

      Bài kiểm tra này kiểm tra kiến ​​thức của bạn về ngôn ngữ PHP. Bạn bắt buộc phải biết các cấu trúc PHP cơ bản, làm việc với các biến, phiên, triển khai chuyển hướng và những thứ tiêu chuẩn khác.
      Yêu cầu nghiêm túc: Bài kiểm tra có nhiều câu hỏi kiểu: "Tập lệnh sẽ xuất ra cái gì?" Yêu cầu lớn, không cần phải sao chép nó và kiểm tra nó. Hãy thành thật với chính mình.

    5. SQL

      • Tổng số bài kiểm tra đã vượt qua: 18014 người
      • Điểm trung bình: 3,28 trên 5điểm.

      Bài kiểm tra này kiểm tra kiến ​​thức của bạn về ngôn ngữ truy vấn SQL. Các câu hỏi chỉ ảnh hưởng đến kiến ​​thức cơ bản nhất của ngôn ngữ này, không có bất kỳ sự đào sâu nào. Bạn sẽ cần biết các truy vấn SQL cơ bản nhất và sử dụng chúng một cách khôn ngoan.

    Việc tạo các trường hợp kiểm thử hiệu quả có thể cực kỳ quan trọng đối với các dự án lớn khi hành vi của các phần của ứng dụng có thể thay đổi vì nhiều lý do khác nhau. Có lẽ vấn đề phổ biến nhất là khi một nhóm lớn các nhà phát triển đang làm việc trên cùng một hoặc các mô-đun có liên quan. Điều này có thể dẫn đến những thay đổi ngoài kế hoạch trong hành vi của các hàm do các lập trình viên khác viết. Hoặc làm việc theo một lịch trình chặt chẽ dẫn đến những thay đổi vô tình đối với các phần quan trọng của ứng dụng.

    Kiểm tra một ứng dụng web thường bao gồm đánh giá trực quan các phần tử của trang và đánh giá thực nghiệm về chức năng của chức năng. Nói cách khác, điều hướng qua các phần và thực hiện các hành động trên các phần tử động.

    Theo thời gian, dự án được lấp đầy với các chức năng mới, kéo dài và làm phức tạp quá trình kiểm tra công việc của nó. Kiểm thử đơn vị được sử dụng để tự động hóa.

    Có 2 cách tiếp cận để xây dựng tập lệnh thử nghiệm:

    • Hộp trắngThử nghiệm- Viết các bài kiểm tra dựa trên việc thực hiện các chức năng. Những thứ kia. vì chúng tôi kiểm tra bằng cùng các thuật toán dựa trên công việc của các mô-đun trong hệ thống của chúng tôi. Cách tiếp cận này không đảm bảo hoạt động chính xác của toàn bộ hệ thống.
    • Hộp đenThử nghiệm- kịch bản dựa trên các thông số kỹ thuật và yêu cầu hệ thống. Bằng cách này, bạn có thể kiểm tra tính đúng đắn của kết quả của toàn bộ ứng dụng, nhưng cách làm này không cho phép bạn mắc phải những lỗi nhỏ và hiếm gặp.

    Kiểm tra những gì

    Có vẻ như nó đáng để thử nghiệm mọi tính năng bạn đã triển khai. Điều này không hoàn toàn đúng. Do đó, để tối ưu hóa quá trình tạo ứng dụng, việc viết các bài kiểm tra tốn nhiều thời gian của nhà phát triển, chỉ nên chuẩn bị các bài kiểm tra cho các chức năng phức tạp, quan trọng hoặc những chức năng phụ thuộc vào kết quả công việc của các mô-đun hệ thống khác. Che đậy bằng các bài kiểm tra logic không rõ ràng có thể gây ra lỗi. Bạn cũng nên tạo các bài kiểm tra cho những phần mã mà bạn định tối ưu hóa trong tương lai, để sau quá trình tối ưu hóa, bạn có thể đảm bảo rằng chúng được thực thi chính xác.

    Nói chung, điều cực kỳ quan trọng là ước tính chi phí thử nghiệm liên quan đến sự chặt chẽ của khung thời gian phát triển. Tất nhiên, nếu bạn không bị giới hạn về thời gian, bạn có thể cho phép các bài kiểm tra bao gồm mọi chức năng. Nhưng theo quy luật, quá trình phát triển được thực hiện trong một thời gian khó khăn, vì vậy nhiệm vụ của một nhà phân tích hoặc một nhà phát triển có kinh nghiệm là phải hiểu nơi nào cần kiểm tra. Ngoài ra, các bài kiểm tra viết làm tăng chi phí của dự án.

    Do đó, chúng ta có thể hình thành 3 trường hợp khi việc sử dụng kiểm thử đơn vị là hợp lý:

    1) Nếu các bài kiểm tra có thể xác định lỗi nhanh hơn so với cách tìm kiếm chúng thông thường.

    2) Giảm thời gian gỡ lỗi

    3) Cho phép bạn kiểm tra mã thường xuyên thay đổi.

    Trong 3 thành phần chính của frontend (HTML, CSS, JavaScript), có lẽ chỉ có đoạn mã JavaScript cần được kiểm tra. CSS được kiểm tra bằng phương pháp trực quan hoàn toàn khi nhà phát triển / người thử nghiệm / khách hàng xem GUI trong các trình duyệt khác nhau. Đánh dấu HTML được xác thực bằng cùng một phương pháp.

    Làm thế nào để kiểm tra

    Khi xây dựng các kịch bản thử nghiệm, bạn nên được hướng dẫn bởi các nguyên tắc sau:

    • Giữ cho các bài kiểm tra của bạn càng đơn giản càng tốt. Sau đó, có nhiều khả năng chính lỗi mà bạn đang cố gắng lặp lại sẽ ảnh hưởng đến kết quả triển khai của nó.
    • Phân rã các bài kiểm tra đơn vị lớn. Tìm vị trí chính xác của lỗi.
    • Làm cho các bài kiểm tra của bạn độc lập. Kết quả của một thử nghiệm không được phụ thuộc vào kết quả của một thử nghiệm khác.
    • Kết quả thử nghiệm phải hoàn toàn có thể lặp lại và được mong đợi. Mỗi lần bạn chạy lại bài kiểm tra, kết quả sẽ giống như lần trước.
    • Đối với bất kỳ lỗi nào trong quá trình thực thi ứng dụng, một tập lệnh kiểm tra phải được tạo. Bằng cách này, bạn có thể chắc chắn rằng lỗi thực sự đã được sửa và không hiển thị với người dùng.

    Kiểm tra những gì

    Có một số thư viện để kiểm tra đơn vị mã js. Có lẽ phổ biến nhất là QUnit. Để tiến hành các bài kiểm tra đơn vị bằng cách sử dụng thư viện này, chúng ta cần tạo một "hộp cát" - một trang html đơn giản sẽ bao gồm thư viện để kiểm tra, mã được kiểm tra và chính các bài kiểm tra.

    Chức năng cho các bài kiểm tra:

    (function () (window.stepen = function (int) (var result = 2; for (var i = 1; i< int; i ++) { result = result * 2; } return result; } window.returnFunc = function() { return "ok"; } })();

    Danh sách các bài kiểm tra:

    Kiểm tra ("stepen ()", function () (bằng (bước (2), 4, "2 ^ 2 - phương pháp bằng"); ok (bước (3) === 8, "2 ^ 3 - phương pháp ok" ); deepEqual (stepen (5), 32, "2 ^ 5 - deepEqual method");)); asyncTest ("returnFunc ()", function () (setTimeout (function () (bằng (returnFunc (), "ok", "Async Func Test"); start ();), 1000);));

    Như bạn có thể thấy, QUnit hỗ trợ 3 chức năng để so sánh kết quả thực thi mã với kết quả mong đợi:

    • Vâng ()- coi thử nghiệm thành công nếu kết quả trả về = true
    • bình đẳng ()- so sánh kết quả với dự kiến
    • deepEqual ()- so sánh kết quả với kết quả mong đợi, kiểm tra loại của nó

    Kết quả thực hiện:

    Như bạn có thể thấy, thư viện QUnit kiểm tra mã cho một số trình duyệt cùng một lúc.

    Có một số thư viện khác cho các bài kiểm tra đơn vị. Tuy nhiên, khái niệm xây dựng các kịch bản thử nghiệm ở chúng đều giống nhau, vì vậy khi đã xử lý xong một kịch bản, bạn sẽ không khó để chuyển sang một kịch bản khác.

    Điều quan trọng cần nhớ

    Một tính năng của mã js hiện đại là thực thi không đồng bộ của nó. Thư viện kiểm thử thường có khả năng thực hiện kiểm tra không đồng bộ. Nhưng ví dụ: nếu bạn đang cố gắng kiểm tra một hàm, chẳng hạn như gửi một yêu cầu nhận đến phần phụ trợ và trả về phản hồi từ nó, thì để chạy các bài kiểm tra, bạn sẽ phải dừng chuỗi bằng hàm stop (), chạy hàm đang được kiểm tra, rồi khởi động lại luồng bằng phương thức start (). Bằng cách "gói nó" trong setTimeout (). Những thứ kia. bạn phải đặt một khoảng thời gian nhất định để hoàn thành việc thực thi chức năng. Cần phải cẩn thận lựa chọn thời lượng của phân đoạn này, .k. mặt khác, công việc lâu dài của phương pháp có thể là một tính năng hoặc thậm chí là nhu cầu triển khai cụ thể của chức năng ứng dụng hoặc hành vi không chính xác.

    Kiểm tra ứng dụng xương sống

    Đối với một ví dụ về thử nghiệm các ứng dụng được viết bằng Backbone.js, chúng tôi sẽ sử dụng dự án được mô tả trong.

    Các bài kiểm tra đơn vị có thể kiểm tra:

    • Tính đúng đắn của việc tạo mô hình và bộ điều khiển
    • Tính đúng đắn của dữ liệu trong các mô hình
    • Thực thi các phương thức bộ điều khiển (đối với điều này, chúng phải trả về một kết quả)
    • Tải thành công lượt xem

    Mã kiểm tra:

    Kiểm tra ("Backbone.js", function () (ok (sample, "Namespace check"); ok (sample.routers.app, "Router check"); ok (sample.core.pageManager.open ("chat") , "Kiểm tra mở trang (Cuộc gọi phương thức bộ điều khiển)") ok (sample.core.state, "Kiểm tra mô hình"); bằng (sample.core.state.get ("content"), "sintel", "Dữ liệu mô hình nhận được kiểm tra "); stop (); ok (function () ($ .ajax ((url:" app / templates / about.tpl ", dataType:" text ")). done (function (data) (self. $ el. html (dữ liệu); trả về dữ liệu;))), "Kiểm tra tải mẫu"); setTimeout (function () (start ();), 1000);));

    Kết quả làm việc với các lỗi thử nghiệm:

    Tự động hóa chạy thử nghiệm

    Thông thường, triển khai một ứng dụng là một nhiệm vụ cần được thực hiện đủ thường xuyên trong quá trình phát triển chuyên sâu. Do đó, hoạt động này thường được tự động hóa. Chúng tôi sử dụng Jenkins, một công cụ tích hợp liên tục, trong công việc của mình. Ý tưởng là kết hợp việc triển khai Jenkins với các bài kiểm tra tự động.

    Kiểm tra QUnit được chạy trong trình duyệt. Phantomjs, một phần mềm giả lập hoạt động của trình duyệt sẽ giúp chúng ta bỏ qua tính năng này. Các nhà phát triển phantomjs đã cung cấp một tập lệnh để thực hiện các bài kiểm tra QUnit, nhưng nó phải được sửa đổi một chút để hoạt động chính xác.

    / ** * Chờ cho đến khi điều kiện kiểm tra là đúng hoặc thời gian chờ xảy ra. * Hữu ích khi chờ đợi * phản hồi của máy chủ hoặc khi xảy ra thay đổi ui (fadeIn, v.v.). * * @param testFx điều kiện javascript đánh giá thành boolean, * nó có thể được chuyển vào dưới dạng một chuỗi (ví dụ: "1 == 1" hoặc * "$ (" # bar "). is (": display ")" hoặc * dưới dạng một hàm gọi lại. * @param on Chuẩn bị sẵn sàng những việc cần làm khi điều kiện testFx được đáp ứng, * nó có thể được chuyển vào dưới dạng một chuỗi (ví dụ: "1 == 1" hoặc * "$ (" # bar "). là (":" = timeOutMillis? timeOutMillis: 3001, //< Default Max Timout is 3s start = new Date().getTime(), condition = false, interval = setInterval(function() { if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { // If not time-out yet and condition not yet fulfilled condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code } else { if(!condition) { // If condition still not fulfilled // (timeout but condition is "false") console.log(""waitFor()" timeout"); phantom.exit(1); } else { // Condition fulfilled (timeout and/or condition is //"true") console.log(""waitFor()" finished in " + (new Date().getTime() - start) + "ms."); typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it"s supposed to do once the // condition is fulfilled clearInterval(interval); //< Stop this interval } } }, 100); // repeat check every 250ms }; }; if (phantom.args.length === 0 || phantom.args.length >2) console.log ("Cách sử dụng: URL run-qunit.js"); phantom.exit (); ) var page = new WebPage (); // Định tuyến các cuộc gọi "console.log ()" từ bên trong Trang // ngữ cảnh đến ngữ cảnh Phantom chính (tức là hiện tại "this") page.onConsoleMessage = function (msg) (console.log (msg);); page.open (phantom.args, function (status) (if (status! == "success") (console.log ("Không thể truy cập mạng"); phantom.exit ();) else (waitFor (function () (return page.evaluate (function () (var el = document.getElementById ("qunit-testresult"); if (el && el.innerText.match ("complete")) (return true;) return false;)); ), function () (var failNum = page.evaluate (function () (var el = document.getElementById ("qunit-testresult"); console.log (el.innerText); try (return document.getElementsByClassName ("fail" ). innerHTML.length;) catch (e) (return 0;) return 10000;)); phantom.exit ((parseInt (failNum, 10)> 0)? 1: 0);));)));

    Để hiển thị thông báo kết quả cho bảng điều khiển, bạn cần thêm chức năng ghi nhật ký vào tập lệnh với các bài kiểm tra.

    Sử dụng ví dụ về một ứng dụng máy tính đơn giản trong Node.js. Chúng tôi sẽ thử nghiệm bằng cách sử dụng Mocha framework.

    Ứng dụng của chúng tôi có thể làm gì:

    • Cộng, trừ, chia và nhân hai số bất kỳ;
    • Hiển thị cảnh báo và thoát ra nếu nhập thứ gì đó không phải là số;
    • Cũng phải có một giao diện dòng lệnh để người dùng cuối sử dụng ứng dụng.

    Điều chúng ta cần:

    • Node.js và npm;
    • Kiến thức về JavaScript: cú pháp và cấu trúc của mã, kiểu dữ liệu, phép toán và biểu thức điều kiện.

    Với các mục tiêu được sắp xếp, bạn có thể bắt đầu thiết lập môi trường để thử nghiệm và phát triển.

    Thiết lập môi trường

    Vì chúng tôi đang sử dụng Node.js, chúng tôi cần tạo môi trường cục bộ cho các tệp và phần phụ thuộc.

    Tạo một thư mục mới calc... Trên dòng lệnh, thay đổi thành thư mục này và tạo một dự án mới bằng lệnh npm init, lệnh này sẽ tạo một tệp mới package.json cho chương trình của chúng tôi.

    Bạn sẽ được nhắc về tên gói, phiên bản, mô tả và thông tin khác về gói. Bạn có thể nhập tên calc.js tiếp tục nhấn đi vàođể gán các giá trị mặc định. Khi bạn nhận được lệnh kiểm tra, hãy nhập mocha - đây là khung kiểm tra mà chúng tôi sẽ sử dụng:

    lệnh kiểm tra: mocha

    Sau khi nhập đầy đủ thông tin, script sẽ tạo một tệp package.json trông giống như sau:

    ("name": "calc.js", "version": "1.0.0", "description": "Một máy tính đơn giản trong Node.js", "main": "index.js", "scripts": ( "test": "mocha"), "author": "", "license": "ISC")

    Bước cuối cùng trong bước này là cài đặt Mocha. Nhập lệnh sau để cài đặt:

    Cài đặt Npm --save-dev mocha

    Sau khi áp dụng lệnh này, một thư mục sẽ xuất hiện node_modules, tập tin package-lock.json và trong tệp package.json các dòng sau sẽ xuất hiện:

    "devDependencies": ("mocha": "^ 4.0.1")

    Tạo một tập tin test.js... Chúng tôi sẽ sử dụng mô-đun Node.js tích hợp sẵn khẳng địnhđể kiểm tra xem true và true có đúng không. Vì nó đúng, bài kiểm tra sẽ vượt qua thành công:

    Const khẳng định = yêu cầu ("khẳng định"); it ("phải trả về true", () => (khẳng định.equal (true, true);));

    Bây giờ hãy chạy thử nghiệm từ dòng lệnh:

    Kiểm tra $ npm> mocha ✓ sẽ trả về true 1 pass (8ms)

    Kiểm tra đã vượt qua như mong đợi, vì vậy chúng tôi đã hoàn tất việc thiết lập môi trường. Loại bỏ từ test.js mọi thứ ngoại trừ dòng const khẳng định = yêu cầu ("khẳng định"); ...

    Chúng tôi sẽ sử dụng tệp test.js trong toàn bộ quá trình tạo ứng dụng. Tạo thêm hai tệp: Operations.js cho các hàm số học và xác thực, và calc.js cho chính ứng dụng. Chúng tôi sử dụng rất nhiều tệp để chúng không quá dài và phức tạp. Đây là danh sách các tệp hiện tại của chúng tôi:

    • calc.js;
    • node_modules;
    • Operations.js;
    • package-lock.json;
    • package.json;
    • test.js;

    Hãy thêm thử nghiệm thực tế đầu tiên cho ứng dụng của chúng tôi.

    Thêm các phép toán

    Trước hết, ứng dụng của chúng ta phải có thể cộng, trừ, chia và nhân hai số bất kỳ. Do đó, đối với mỗi hoạt động này, chúng ta phải tạo một chức năng riêng biệt.

    Hãy bắt đầu với phép cộng. Chúng tôi sẽ viết một bài kiểm tra mà rõ ràng sẽ nhận được tổng dự kiến ​​của hai số. Trong đoạn mã dưới đây, chúng tôi kiểm tra xem tổng của 1 và 3 có bằng 4 hay không bằng cách sử dụng hàm add ():

    Const khẳng định = yêu cầu ("khẳng định"); it ("tìm đúng tổng của 1 và 3", () => (khẳng định.equal (add (1, 3), 4);));

    Sau khi chạy thử nghiệm với lệnh kiểm tra npm, chúng tôi thấy như sau:

    > mocha 0 đạt (9ms) 1 không đạt 1) tìm đúng tổng của 1 và 3: ReferenceError: add không được xác định tại Context.it (test.js: 5: 16) npm ERR! Thử nghiệm thất bại. Xem ở trên để biết thêm chi tiết.

    Kiểm tra không thành công với thông báo ReferenceError: add không được xác định. Chúng tôi đang thử nghiệm hàm add (), hàm này chưa tồn tại, vì vậy kết quả này khá được mong đợi.

    Hãy tạo hàm add () trong tệp Operations.js:

    Const thêm = (x, y) => (+ x) + (+ y);

    Hàm này nhận hai đối số x và y và trả về tổng của chúng. Bạn có thể nhận thấy rằng chúng ta đang viết (+ x) + (+ y), không phải x + y. Chúng tôi sử dụng toán tử một ngôi để truyền đối số thành một số, trong trường hợp đầu vào là một chuỗi.

    Lưu ý Điều này sử dụng hàm mũi tên và trả về ngầm định được thêm vào trong ES6.

    Vì chúng tôi đang sử dụng Node.js và chúng tôi chia mã thành nhiều tệp, chúng tôi cần sử dụng module.exports để xuất mã:

    Const thêm = (x, y) => (+ x) + (+ y); module.exports = (thêm)

    Ở đầu tệp test.js chúng tôi nhập mã từ Operations.js bằng cách sử dụng request (). Vì chúng ta đang sử dụng hàm thông qua biến hoạt động, chúng ta cần thay đổi add () thành Operating.add ():

    Các hoạt động Const = request ("./ Operating.js"); const khẳng định = yêu cầu ("khẳng định"); it ("tìm tổng của 1 và 3 đúng", () => (khẳng định.equal (Operating.add (1, 3), 4);));

    Chúng tôi chạy thử nghiệm:

    Kiểm tra $ npm> mocha ✓ tổng đúng 1 và 3 1 vượt qua (8ms)

    Bây giờ chúng tôi có một chức năng hoạt động và các bài kiểm tra đang vượt qua thành công. Vì các hàm của các phép toán khác hoạt động theo cách tương tự, nên việc thêm các phép thử cho phép trừ (), nhân () và chia () rất dễ dàng:

    It ("tìm đúng tổng của 1 và 3", () => (khẳng định.equal (Operating.add (1, 3), 4);)); it ("các tổng đúng -1 và -1", () => (khẳng định.equal (Operating.add (-1, -1), -2);)); it ("tìm sự khác biệt giữa 33 và 3 một cách chính xác", () => (khẳng định.equal (Operating.subtract (33, 3), 30);)); it ("tìm đúng tích 12 và 12", () => (khẳng định.equal (Operating.multiply (12, 12), 144);)); it ("tìm chính xác thương 10 và 2", () => (khẳng định.equal (Operating.divide (10, 2), 5);));

    Bây giờ, hãy tạo và xuất tất cả các chức năng trong test.js:

    Const thêm = (x, y) => (+ x) + (+ y); const subtract = (x, y) => (+ x) - (+ y); const nhân = (x, y) => (+ x) * (+ y); const chia = (x, y) => (+ x) / (+ y); module.exports = (cộng, trừ, nhân, chia,)

    Và hãy chạy thử nghiệm mới:

    Kiểm tra $ npm> mocha ✓ tìm đúng tổng 1 và 3 ✓ tìm đúng tổng -1 và -1 ✓ tìm đúng hiệu của 33 và 3 ✓ tìm đúng tích của 12 và 12 ✓ tìm đúng là thương của 10 và 2 5 đi qua (8ms)

    Tất cả các bài kiểm tra đều vượt qua thành công, vì vậy bây giờ chúng tôi có thể chắc chắn rằng các chức năng chính của ứng dụng của chúng tôi sẽ hoạt động chính xác. Bây giờ chúng ta có thể thực hiện một số xác nhận bổ sung.

    Thêm xác thực

    Tại thời điểm này, khi người dùng nhập một số và chọn thao tác mong muốn, mọi thứ hoạt động tốt. Tuy nhiên, điều gì sẽ xảy ra khi bạn cố gắng tìm tổng của một số và một chuỗi? Ứng dụng sẽ cố gắng thực hiện thao tác, nhưng vì nó mong đợi một số, nó sẽ trả về NaN.

    Thay vì trả về một số giá trị không thể hiểu được, đã đến lúc thực hiện nhiệm vụ thứ hai - làm cho ứng dụng hiển thị cảnh báo và thoát nếu đối số được cung cấp không phải là một số.

    Đầu tiên, bạn cần viết một hàm sẽ kiểm tra xem đầu vào có phải là số hay không. Ứng dụng chỉ nên hoạt động với các con số, vì vậy chúng tôi sẽ xử lý ba tình huống:

    1. Cả hai đầu vào đều là số.
    2. Một đầu vào là số và đầu vào là chuỗi.
    3. Cả hai đầu vào đều là chuỗi.
    it ("báo lỗi khi sử dụng chuỗi thay vì số", () => (khẳng định.equal (Operating.validateNumbers ("sammy", 5), false);)); it ("báo lỗi khi sử dụng hai chuỗi thay vì số", () => (khẳng định.equal (Operating.validateNumbers ("sammy", "sammy"), false);)); it ("thành công với hai số", () => (khẳng định.equal (Operating.validateNumbers (5, 5), true);));

    Hàm validateNumbers () sẽ xác thực cả hai tham số. Hàm isNaN () kiểm tra xem tham số có phải là số không và nếu không, nó sẽ trả về false. Nếu không, nó trả về true, có nghĩa là xác thực thành công.

    Const validateNumbers = (x, y) => (if (isNaN (x) && isNaN (y)) (return false;) return true;)

    Đừng quên thêm validateNumbers vào module.exports ở cuối tệp. Bây giờ bạn có thể chạy các thử nghiệm mới:

    $ npm test 1) báo lỗi khi sử dụng chuỗi thay vì số ✓ báo lỗi khi sử dụng hai chuỗi thay vì số ✓ thành công khi sử dụng hai số 7 vượt qua (12ms) 1 không đạt 1) báo lỗi khi sử dụng chuỗi thay thế của một số: AssertionError: true == false + mong đợi - thực -true + false

    Hai bài kiểm tra đã vượt qua, nhưng một bài không đạt. Kiểm tra nhập hai số đã thành công, cũng như kiểm tra nhập hai chuỗi. Điều tương tự không thể nói về việc kiểm tra đầu vào chuỗi và số.

    Nếu bạn nhìn lại chức năng của chúng tôi, bạn sẽ nhận thấy rằng cả hai tham số phải là NaN để hàm trả về false. Nếu chúng ta muốn đạt được hiệu quả tương tự khi có ít nhất một trong các tham số là NaN, chúng ta cần thay && bằng || :

    Const validateNumbers = (x, y) => (if (isNaN (x) || isNaN (y)) (return false;) return true;)

    Nếu bạn chạy lại thử nghiệm npm sau những thay đổi này, thì tất cả các thử nghiệm sẽ vượt qua thành công:

    ✓ báo lỗi khi sử dụng chuỗi thay vì số ✓ báo lỗi khi sử dụng hai chuỗi thay vì số ✓ thành công khi sử dụng hai số 8 chuyển (9ms)

    Chúng tôi đã thử nghiệm tất cả các chức năng của ứng dụng của chúng tôi. Các hàm thực hiện thành công các phép toán và xác thực đầu vào. Giai đoạn cuối cùng là tạo giao diện người dùng.

    Tạo giao diện

    Chúng tôi đã có các chức năng cần thiết, nhưng người dùng vẫn không thể sử dụng chúng theo bất kỳ cách nào. Do đó, chúng ta cần một giao diện. Đối với ứng dụng của chúng tôi, chúng tôi sẽ tạo một giao diện dòng lệnh.

    Hiện tại, tập tin calc.js nên để trống. Đây là nơi ứng dụng của chúng tôi sẽ được lưu trữ. Trước tiên, bạn cần nhập các chức năng từ Operations.js:

    Các hoạt động Const = request ("./ Operating.js");

    Bản thân giao diện sẽ sử dụng mô-đun Readline CLI được tích hợp trong Node.js:

    Const readline = request ("readline");

    Sau khi nhập mọi thứ bạn cần, bạn có thể bắt đầu xây dựng ứng dụng của mình. Chúng tôi sẽ sử dụng readline để tạo giao diện, có thể truy cập thông qua biến rl:

    Const rl = readline.createInterface ((đầu vào: process.stdin, đầu ra: process.stdout));

    Điều đầu tiên người dùng sẽ thấy sau khi khởi động chương trình là một thông báo chào mừng và hướng dẫn sử dụng. Chúng tôi sẽ sử dụng console.log () cho việc này:

    Console.log (`Calc.js Bạn đã mở một máy tính trong Node.js! Phiên bản: 1.0.0. Cách sử dụng: người dùng phải nhập hai số rồi chọn làm gì với chúng.`);

    Trước khi chúng ta đi sâu vào các hàm máy tính, hãy kiểm tra xem console.log () có hoạt động như mong đợi hay không. Chúng tôi sẽ làm cho chương trình in một thông báo và thoát. Để thực hiện việc này, hãy thêm một lệnh gọi vào phương thức rl.close () ở cuối.

    Để chạy ứng dụng, hãy nhập nút và tên tệp:

    $ node calc.js Calc.js Bạn đã mở một máy tính trong Node.js! Phiên bản: 1.0.0. Cách sử dụng: Người dùng phải nhập hai số và sau đó chọn thao tác với chúng.

    Chương trình hiển thị thông báo chào mừng và thoát. Bây giờ chúng ta cần thêm đầu vào của người dùng. Người dùng được yêu cầu thực hiện những việc sau: chọn hai số và một thao tác. Mỗi đầu vào sẽ được yêu cầu với phương thức rl.question ():

    Rl.question ("Nhập số đầu tiên:", (x) => (rl.question ("Nhập số thứ hai:", (y) => (rl.question (`Chọn một trong các thao tác sau: Phép cộng ( +) Phép trừ (-) Phép nhân (*) Phép chia (/) Lựa chọn của bạn: `, (lựa chọn) => (// đoạn mã cũng sẽ xuất hiện ở đây rl.close ();));));));

    Biến x được gán là số đầu tiên, y là số thứ hai và lựa chọn là phép toán đã chọn. Bây giờ chương trình của chúng tôi yêu cầu đầu vào, nhưng không làm gì với dữ liệu đã nhận.

    Sau lần nhập thứ ba, bạn cần kiểm tra xem chỉ các số đã được nhập. Để làm điều này, chúng ta sẽ sử dụng hàm validateNumbers (). Sử dụng toán tử NOT, chúng tôi sẽ kiểm tra xem các số đã được nhập chưa, và nếu không phải trường hợp này, chúng tôi sẽ thoát khỏi chương trình:

    If (! Operations.validateNumbers (x, y)) (console.log ("Chỉ có thể nhập số! Vui lòng khởi động lại chương trình.");)

    Nếu mọi thứ được nhập chính xác, thì bây giờ bạn cần chạy phương thức tương ứng với thao tác, đã tạo trước đó. Để xử lý bốn lựa chọn có thể xảy ra, chúng tôi sẽ sử dụng câu lệnh switch và in kết quả của phép toán. Nếu một hoạt động không tồn tại được chọn, khối mặc định sẽ được thực thi, yêu cầu người dùng thử lại:

    If (! Operations.validateNumbers (x, y)) (console.log ("Chỉ có thể nhập số! Vui lòng khởi động lại chương trình.");) Else (switch (choice) (case "1": console.log (` Tổng $ (x) và $ (y) bằng $ (Operating.add (x, y)). `); Break; case" 2 ": console.log (` Sự khác biệt giữa $ (x) và $ (y) bằng $ (Operating.subtract (x, y)). `); break; case" 3 ": console.log (` Tích của $ (x) và $ (y) bằng $ (Operating.multiply (x, y) )). `); break; case" 4 ": console.log (` Riêng $ (x) và $ (y) bằng $ (Operating.divide (x, y)). `); break; default: console.log ("Vui lòng khởi động lại chương trình và chọn một số từ 1 đến 4."); break;))

    Lưu ý Các hàm console.log () ở đây sử dụng các chuỗi mẫu hỗ trợ biểu thức.

    / ** * Một máy tính Node.js đơn giản sử dụng ứng dụng máy tính sử dụng * giao diện dòng lệnh Readline tích hợp sẵn. * / const Operating = request ("./ Operating.js"); const readline = request ("readline"); // Sử dụng readline để tạo giao diện const rl = readline.createInterface ((input: process.stdin, output: process.stdout)); console.log (`Calc.js Bạn có máy tính Node.js! Phiên bản: 1.0.0. Cách sử dụng: người dùng phải nhập hai số rồi chọn làm gì với chúng.`); rl.question ("Nhập số đầu tiên:", (x) => (rl.question ("Nhập số thứ hai:", (y) => (rl.question (`Chọn một trong các thao tác sau: Phép cộng ( +) Phép trừ (-) Phép nhân (*) Phép chia (/) Lựa chọn của bạn: `, (lựa chọn) => (if (! Operations.validateNumbers (x, y)) (console.log (" Chỉ có thể nhập số! Vui lòng khởi động lại chương trình. ");) else (switch (lựa chọn) (trường hợp" 1 ": console.log (` Tổng của $ (x) và $ (y) là $ (Operating.add (x, y)). `); break; case" 2 ": console.log (` Sự khác biệt giữa $ (x) và $ (y) là $ (Operating.subtract (x, y)). `); break; case" 3 ": console.log (`Sản phẩm $ (x) và $ (y) bằng $ (Operating.multiply (x, y)).`); break; case "4": console.log (`Thương số $ (x) và $ (y) bằng $ (các phép toán. chia (x, y)). `); break; default: console.log (" Vui lòng khởi động lại chương trình và chọn một số từ 1 đến 4 "); break;)) rl.close ();));));));

    Ứng dụng của chúng tôi hiện đã sẵn sàng. Cuối cùng hãy kiểm tra công việc của nó. Hãy nhập 999 và 1 và chọn phép tính trừ:

    $ node calc.js Nhập số đầu tiên: 999 Nhập số thứ hai: 1 Lựa chọn của bạn: 2 Hiệu số giữa 999 và 1 là 998.

    Chương trình đã hoàn thành tốt công việc của mình, hiển thị kết quả chính xác. Xin chúc mừng, bạn đã viết một máy tính đơn giản với Node.js và đã học được những kiến ​​thức cơ bản về phát triển TDD.