Kiểm tra JavaScript và tự động hóa của chúng. Kiểm tra kiến ​​thức về JavaScript - Kiểm tra cơ bản về mã javascript

Kiểm tra mã là một chu trình không thể thiếu trong quá trình phát triển phần mềm. Các nhóm phát triển mới bắt đầu 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 lỗi thời - “nó hoạt động được, được thôi”. Sớm hay muộn, chiến lược này sẽ thất bại và trình theo dõi lỗi bắt đầu bị choáng ngợp bởi vô số nhiệm vụ. Để tránh rơi vào cái bẫy như vậy, tôi khuyên bạn nên hiểu rõ các sắc thái của việc kiểm tra mã JavaScript.

JavaScript không còn giống nhau nữa

Ngày nay, JavaScript không chỉ là một ngôn ngữ để tăng thêm vẻ ngoài cho một ứng dụng. Thời mà JavaScript được sử dụng để đùa hoặc tạo menu đã 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ể, điều đó có nghĩa là khi viết mã, bạn không nên ngại sử dụng các phương pháp đã được chứng minh bằng các ngôn ngữ lập trình khác.

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

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

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

Trong thực tế, mọi thứ xảy 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 thông số kỹ thuật. Các trình tạo mã nâng cao hơn sẽ tự động hóa loại thử nghiệm tích hợp này bằng cách sử dụng những thứ như Selenium.

Do đó, lập trình viên có cơ hội chỉ phát hiện những lỗi nghiêm trọng nhất. Thật không may, những hành động “ngu ngốc” và “ngoài ý muốn” của người dùng, cũng như những động thái xảo quyệt trong logic kinh doanh, vẫn nằm ở hậu trường trong 99% trường hợp.

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 cũng giải quyết được vấn đề một phần và trong một thời gian nhất định. Ngay cả khi chúng ta bỏ qua sự chú ý đến từng chi tiết của đặc công, chất lượng thử nghiệm của anh ta sẽ có xu hướng bằng 0 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 ngày nọ, tôi được giao phát triển một chương trình nhỏ. Về chức năng, dự án giống như một CRM đơn giản mà tôi đã triển khai trong thời gian ngắn nhất. Nhận được số tiền thù lao xứng đáng, tôi bàn giao toàn bộ nguồn hàng cho khách hàng và quên mất dự án trong 8 tháng. Sau đó cuộc vui bắt đầu. Khách hàng quyết định nghiêm túc mở rộng 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. Lúc đầu, nó không khó, nhưng khi nói đến việc tích hợp tổng thể các chức năng, một đàn lỗi vo ve đã lao về phía tôi. Các đoạn mã bắt đầu xung đột và chúng tôi phải mất rất nhiều thời gian để giải quyết xung đột. “Chà, sao bạn không thấy rằng đơn đăng ký của bạn có vấn đề?” - độc giả chăm chú sẽ hỏi. Tôi đã khởi chạy nó, nhưng do ứng dụng đã phát triển nên tôi không có đủ thời gian và thần kinh để kiểm tra hàng loạt chức năng. Tôi hạn chế chỉ thử nghiệm các chức năng riêng lẻ và trả tiền hậu hĩnh cho việc đó. Ý nghĩa của câu chuyện là “Hãy coi thử nghiệm là một phần không thể thiếu trong quá trình phát triển”.

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

Kiểm thử đơ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 về chức năng của từng phần riêng lẻ của ứng dụng. Nếu bạn chưa từng gặp từ khủng khiếp này thì tôi sẽ giải thích ngắn gọn. Kiểm thử đơn vị cho phép bạn tự động hóa quy trình kiểm thử và kiểm thử mọi tính năng của ứng dụng.

Sau khi hoàn thành việc phát triển một chức năng mới (có thể viết bài kiểm tra trước khi bắt đầu phát triển), nhà phát triển sẽ viết mã đặc biệt để kiểm tra mã của mình. Trong mã thử nghiệm của mình, bạn cần 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ớt 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 tuyên bố rằng:

  • khi truyền chuỗi "chuỗi" chúng ta sẽ nhận được "chuỗi" làm đầu ra;
  • khi truyền đi cụm từ “dòng 9” chúng ta sẽ nhận được “dòng 9” ở đầu ra;
  • Chúng ta 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 tab). Nói chung, chúng ta càng bao quát mã tốt hơn bằng các thử nghiệm và cung cấp các tùy chọn tiêu cực có thể có thì khả năng sẽ còn sót lại một ít tóc trên đầu vào thời điểm quan trọng nhất càng lớn.

    Trong thế giới JS, các bài kiểm tra thường được viết bằng các framework chuyên dụng. Họ có mọi thứ bạn cần để mô tả các bài kiểm tra, cũng như ít nhất một số công cụ để hệ thống hóa các báo cáo tiến độ kiểm tra.

    Kiểm tra!= mã bổ sung

    Các nhà phát triển không sử dụng thử nghiệm đơn vị muốn lập luận rằng thử nghiệm đơn vị yêu cầu viết và duy trì mã bổ sung. 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 thể viết thêm mã.

    Tôi đồng ý về thời hạn chặt chẽ, nhưng tôi sẵn sàng tranh luận về mã bổ sung. Một mặt, vâng, các bài kiểm tra yêu cầu mã bổ sung và do đó cần phải viết nó. Mặt khác, mã này đóng vai trò là túi khí trong ô tô và chắc chắn sẽ tự chi trả khi ứng dụng phát triển.

    Khi bạn không có thời gian và bị dày vò bởi mong muốn từ bỏ bài kiểm tra viết, hãy suy nghĩ ba lần. Trong trường hợp này, có thể sẽ phù hợp hơn nếu chỉ đề cập đến những phần phức tạp nhất của mã bằng các bài kiểm tra, thay vì từ bỏ hoàn toàn việc kiểm tra. Hãy luôn nghĩ đến tương lai, như thể trong một tháng nữa 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 mọi mã đều được kiểm tra

    Tại sao tôi lại nói rằng bạn cần suy nghĩ về việc kiểm thử trước khi viết mã chính? Có, bởi vì mã ban đầu được cho là nằm trong 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 mọi mã đều có thể được kiểm tra. Mã kết hợp logic và biểu diễn, đồng thời cũng được nhồi nhét vào những khu vực không thể kiểm tra chính xác. Ở đâ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 sẽ giải quyết một vấn đề chứ không phải 100.500 tình huống có thể xảy ra. Ví dụ, không cần đặt mã gửi dữ liệu đến máy chủ vào chức năng chịu trách nhiệm chuẩn bị dữ liệu;
  • Một hàm bao gồm hơn 10 dòng mã rất có thể là một hàm xấu;
  • Logic và cách trình bày không bao giờ nên đi đôi với nhau;
  • QUnit - một tác phẩm kinh điển của những người tạo ra jQuery

    QUnit đặc biệt phổ biến đối với 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ả của jQuery. Thư viện này phù hợp để kiểm tra cả mã JavaScript gốc và dựa trên jQuery.

    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ó dạng một tệp JS và CSS duy nhất. Giả sử rằng bạn đã tìm ra cách tải các thành phần cần thiết và nếu vậy thì đã đến lúc viết bài kiểm tra dùng thử. Chúng ta đừng đi xa và thử kiểm tra hàm Trim() đã đề cập ở trên.

    Để minh họa các thử nghiệm, tôi đã tạo một dự án đơn giản với hàm tạo 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 – tệp chứa mã để kiểm tra (trong trường hợp của chúng tôi là mô tả về hàm Trim()); - test.js – tệp chứa các bài kiểm tra; - qunit-1.12.0.css – kiểu thiết kế báo cáo với các bài kiểm tra;

    Nội dung của các tệp index.html và test.js được trình bày trong Danh sách 1 và 2. Chúng tôi quan tâm nhất đến danh sách thứ hai, trong đó có phần khai báo hàm đang được kiểm tra (trim()) và mã kiểm tra để kiểm tra nó. chức năng. Xin lưu ý rằng bản thân hàm Trim() có thể được đặt ở bất cứ đâu; tôi đặt nó trong danh sách thứ hai chỉ để tiết kiệm không gian trong tạp chí.

    Bây giờ chúng ta hãy xem xét các bài kiểm tra. Để kiểm tra chức năng 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:

  • test() – trình bao bọc để mô tả bài kiểm tra;
  • ok() – xác nhận cho phép bạn kiểm tra tính đúng đắn của tham số đầu tiên. Trong ví dụ của chúng tôi, tôi chuyển lệnh gọi đến hàm Trim() mà chúng tôi đã xác định và so sánh nó với giá trị mà tôi mong đợi nhận được. Nếu điều kiện đúng, bài kiểm tra được thông qua;
  • bằng() – phương thức cho phép bạn kiểm tra sự bằng nhau của tham số thứ nhất và thứ hai. Hãy lưu ý ngay rằng phương pháp này thực hiện kiểm tra yếu nên chỉ phù hợp với đại lượng vô hướng;
  • notEqual() là đối diện của bằng(). Được thực thi nếu giá trị đầu tiên không bằng giá trị thứ hai;
  • strictEqual() tương tự như bằng() nhưng có một điểm khác biệt - nó sử dụng tính năng kiểm tra nghiêm ngặt (tức là nó cũng kiểm tra kiểu dữ liệu);
  • notStrictEqual() – phương thức này ngược lại với strictEqual();
  • deepEqual() – phương thức xác nhận đệ quy, được sử dụng cho nguyên hàm, mảng, đối tượng;
  • notDeepEqual() – phương thức này ngược lại với deepEqual();
  • raise() – một câu lệnh để 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ỉ rõ cách áp dụng các phương pháp này vào thực tế. Nếu bạn chạy ví dụ kiểm thử ở dạng này thì tất cả các kiểm thử sẽ vượt qua thành công (xem hình tương ứng). Để thấy sự khác biệt giữa những bài kiểm tra đạt và những bài kiểm tra thất bại, tôi đã sửa đổi một chút mã cho một bài kiểm tra. Tôi đã cố tình thêm một kết quả sai vào dòng thử nghiệm bằng cách sử dụng strictEqual() (xem hình tương ứng).

    Liệt kê 1. Nội dung của tệp index.html Kiểm tra với QUnit Liệt kê 2. Kiểm tra các tệp và hàm Trim() Trim(string) ( return (string || "").replace(/^\s+|\s+$/g, ""); ) test("Kiểm tra hàm Trim()", function() ( ok(trim(" test ") == "test", "cắt các khoảng trắng bên ngoài"); ok(trim(" 1 ") == "1", "có nhiều khoảng trắng ở hai bên"); ok(trim(" 24 ") == "24", "khoảng trắng và tab ở hai bên"); , "Dòng trống" "); strictEqual(trim(" ][aker") ));

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

    AsyncTest("myAsyncFunc()", function() ( setTimeout(function() ( ok(myAsyncFunc() == true, "Data được truyề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à ở chỗ thay vì sử dụng trình bao bọc test(), asyncTest() được sử dụng, qua đó nêu rõ rằng tôi quan tâm đến việc thử nghiệm thử nghiệm không đồng bộ cụ thể. Tiếp theo tôi bắt đầu thời gian chờ ở mức 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 việc đều ổn, hãy trả về true. Đây là nơi khoảnh khắc thú vị nhất đến. Khi asyncTest() được gọi, luồng thực thi sẽ dừng và khi quá trình kiểm tra hoàn tất, nó phải được khởi chạy độc lập. Để kiểm soát luồng thực thi, QUnit có các phương thức start() và stop().

    Việc kiểm tra các hàm không đồng bộ bằng thư viện QUnit khá đơn giản. Ví dụ cuối cùng tôi muốn xem xét liên quan đến việc viết một bài kiểm thử thực hiện một số kiểm tra không đồng bộ. Câu hỏi chính nảy sinh trong những nhiệm vụ như vậy là nơi tối ưu để bắt đầu luồng thực thi. Tài liệu chính thức gợi ý sử dụng một cái gì đó như:

    AsyncTest("myAsyncFunc()", function() ( Expect(3); //Ở đây chúng tôi thực hiện ba bước kiểm tra ok(myAsyncFunc(), "Làm cho thế giới trở thành một nơi tốt đẹp hơn 1"); ok(myAsyncFunc(), "Tạo ra thế giới trở thành một nơi tốt đẹp hơn 2") ; ok(myAsyncFunc(), "Làm cho thế giới trở thành một nơi tốt đẹp hơn 3"); setTimeout(function() ( start(); ));

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

    Bạn nên luôn nhớ rằng rất nhiều nội dung giao diện được viết bằng JavaScript. Ví dụ: người dùng nhấp vào ma cô và điều gì đó sẽ xảy ra để phản hồi lạ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 kiểm tra. Hãy xem cách chúng tôi có thể mô phỏng thao tác gõ phím của người dùng 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 chức năng nhất định ghi lại các phím được nhấn. Tôi đã cung cấp mã của nó trong danh sách thứ ba:

    Liệt kê 3. Ghi nhật ký các lần nhấn phím KeyLogger(target) ( if (!(this instanceof KeyLogger)) ( return new KeyLogger(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 nội dung bài kiểm tra, chúng ta cần mô phỏng phím được nhấn. Cách dễ nhất để thực hiện đ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("Keylogging test", function() ( var event, $doc = $(document), Keys = KeyLogger($doc);event = $.Event("keydown"); event .keyCode = 9; $doc.trigger(event); bằng (keys.log.length, 1, "Khóa được ghi"); bằng (keys.log[ 0 ], 9, "Phím được nhấn với mã 9"); );

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

    DOM dưới vỏ bọc thử nghiệm

    Vì Qunit.js cho phép bạn kiểm tra hành động của người dùng nên việc viết bài kiểm tra cho DOM cũng không phải là vấn đề. Điều này thực sự đúng 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 nhìn vào đoạn mã và mọi thứ sẽ trở nên rõ ràng:

    Test("Thêm phần tử div mới", function() ( var $fixture = $("#qunit-fixture"); $fixture.append("Đây là một 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 rất thuận tiện và đơn giản, nhưng sớm hay muộn bạn sẽ bị thu hút 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ụ: với mục đích này, tôi có một máy ảo riêng trong DigitalOcean mà tôi chỉ có thể quản lý bằ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 phải là một khuôn khổ khác để viết bài kiểm tra Đơn vị mà là phiên bản bảng điều khiển chính thức của công cụ WebKit. Nói một cách đơn giản, ứng dụng này mô phỏng một trình duyệt. Với sự trợ giúp của phantom.js, không chỉ có thể tự động hóa việc xác minh thực hiện kiểm thử mà còn có thể giải quyết nhiều vấn đề sớm hay muộn phát sinh trước nhà phát triển: lấy kết quả hiển thị trang thành một tệp (png, jpg), mạng chức năng giám sát (tốc độ tải, hiệu suất tổng thể, v.v.), mô phỏng hành động của người dùng, v.v. Tôi khuyên bạn nên dành thời gian và đọc tài liệu chính thức về dự án này, bạn chắc chắn sẽ tìm thấy điều gì đó thú vị cho 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ứ trên Windows thì không có vấn đề gì - hợp nhất các tệp nhị phân và tiếp tục. Các vấn đề nhỏ khi khởi động có thể xảy ra 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 cách hack được mô tả ở thanh bên.

    Hãy thử làm quen với phantom.js trong thực tế. Để chạy các thử nghiệm đã chuẩn bị ở phần trước thông qua phantom.js và nhận kết quả thực thi vào bảng điều khiển, chúng ta cần một tập lệnh tải đặc biệt - run-qunit.js. Mở console (mình làm trên Windows nên dùng cmd) và gõ lệnh theo dạng:

    Phantom.exe

    Trong trường hợp của tôi, lệnh khởi chạy trông như thế này:

    E:\soft\phantomjs>phantomjs.exe E:\temp\testjsforx\qunit\run-qunit.js file:///E: /temp/testjsforx/qunit/index.html Kết quả thực thi của nó: Các thử nghiệm đã hoàn thành trong 2592 mili giây. 9 xác nhận trong số 9 đã đạt, 0 không thành công.

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

    Điều chắc chắn là cần thiết phải bao gồm mã của bạn bằng các thử nghiệm, bất kể ứng dụng bạn đang tạo ở quy mô nào. Một lần nữa, tôi xin nhắc bạn rằng ngay cả những chương trình nhỏ nhất cũng trở thành những con quái vật vụng về cần được hỗ trợ và bổ sung thêm chức năng. Mã được kiểm tra tốt là chìa khóa thành công và chất lượng. Đúng, không dễ để bắt đầu viết mã phù hợp cho các bài kiểm tra tự động ngay lập tức, nhưng tin tôi đi, tất cả sự dằn vặt này sẽ được đền đáp nhiều hơn 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 để kiểm tra

    Nếu bạn không có thời gian thì việc viết bài kiểm tra cho các hàm đơn giản cũng chẳng ích gì (lấy cùng một hàm Trim() từ các ví dụ trong bài viết); tốt hơn là bạn nên tập trung vào các phần quan trọng nhất của mã. Nên tuân theo quy tắc tương tự khi viết mã thường xuyên thay đổi. Các thông số kỹ thuật của một dự án trực tiếp thay đổi thường xuyên và một số chức 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 không tiêu hóa dữ liệu cũ một cách hữu cơ. Để tránh gặp phải lỗi ở đây, tốt hơn hết là bạn nên bao gồm ngay các chức năng đó bằng các bài kiểm tra. Hãy nhớ một quy tắc đơn giản - không có thời gian để kiểm tra toàn bộ mã, chỉ bao gồm phần quan trọng nhất của nó.

    Quy tắc để có bài kiểm tra tốt
  • Bài kiểm tra nên đơn giản nhất có thể. Bài kiểm tra càng phức tạp thì càng dễ mắc lỗi;
  • Các bài kiểm tra cần được nhóm thành các mô-đun để dễ dàng tìm ra lỗi sau này 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 mỗi khi bạn tìm thấy lỗi;
  • sự cố phantom.js trên Windows

    Điều đó đã xảy ra, nhưng tôi đã thử nghiệm tất cả các ví dụ trong bài viết này không phải trên Linux mà trên Windows 7 cũ. Hóa ra phantom.js gặp 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, còn có NVidia và vì phantom.js nên nó dứt khoát 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 hoàn thành công việc của mình và tiếp tục bị treo trong bộ nhớ. Cửa sổ terminal cũng ngừng phản hồi các lệnh tắt máy (ctrl + c không giúp ích được gì).

    Nếu bạn gặp phải vấn đề tương tự và dự định sử dụng phantom.js trên Windows, thì hãy sẵn sàng thực hiện thủ thuật sau. Mở Bảng điều khiển Nvidia. Tìm mục “Cài đặt 3D” trong cây. Tùy chọn “Bộ điều hợp đồ họa ưa thích” sẽ xuất hiện ở bên phải. Theo mặc định, giá trị của nó được đặt thành “Tự động chọn”. Chúng ta cần đổ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.

  • "Phát triển JavaScript dựa trên thử nghiệm" của Cristian Johansen là một trong số ít cuốn sách xem xét JavaScript từ quan điểm viết bài kiểm tra;
  • John Resing, Beer Bibo “Bí mật của Ninja Ninja” là một cuốn sách hay, chủ yếu hữu ích cho các nhà phát triển JS có trình độ đào tạo trung bình. Cuốn sách thảo luận chi tiết về các vấn đề viết mã trình duyệt chéo hiệu quả, các sắc thái của xử lý sự kiện và nhiều tính năng thú vị khác.
  • Và là công cụ kiểm tra jQuery chính thức. Nhưng QUnit rất tốt để kiểm tra bất kỳ mã JavaScript nào và thậm chí có thể kiểm tra phần phụ trợ JavaScript bằng các công cụ như Rhino hoặc V8.

    Nếu bạn không quen với ý tưởng "thử nghiệm đơn vị", đừng lo lắng - không có gì phức tạp về việc đó:

    "Kiểm tra đơn vị hoặc kiểm tra đơn vị (tiếng Anh) kiểm tra đơn vị) là một quy trình trong lập trình cho phép bạn kiểm tra tính chính xác của từng mô-đun riêng lẻ trong mã nguồn của chương trình. Ý tưởng là viết các bài kiểm tra cho mọi hàm hoặc phương thức không tầm thường. Điều này cho phép bạn nhanh chóng kiểm tra xem lần thay đổi mã tiếp theo có dẫn đến hồi quy, nghĩa là xuất hiện lỗi ở những vị trí đã được kiểm tra của chương trình, đồng thời cũng tạo điều kiện thuận lợi cho việc phát hiện và loại bỏ các lỗi đó."

    Định nghĩa được trích dẫn từ Wikipedia. Chỉ cần thực hiện các thử nghiệm cho từng khối chức năng trong mã của bạn và nếu tất cả các thử nghiệm đều vượt qua thì bạn có thể chắc chắn rằng không có lỗi (chủ yếu phụ thuộc vào mức độ cẩn thận của các thử nghiệm).

    Tại sao bạn nên kiểm tra mã của mình

    Nếu trước đây bạn chưa từng viết bài kiểm thử đơn vị thì có thể bạn vừa lưu trữ mã của mình trực tiếp trên máy chủ web, chạy mã đó, theo dõi lỗi và cố gắng sửa chúng khi chúng được phát hiện. Phương pháp làm việc này gây ra nhiều vấn đề.

    Thứ nhất, đây là một hoạt động rất tẻ nhạt và nhàm chán. Xác thực thực sự là một công việc khá khó khăn vì bạn phải chắc chắn rằng mọi thứ đã được nhấn. Và trong quá trình này khả năng rất cao là có thể bỏ sót một hoặc hai điểm.

    Thứ hai, mọi thứ được thực hiện để thử nghiệm như vậy đều không thể được sử dụng lại. Với phương pháp này rất khó tìm được hồi quy. Hồi quy là gì? Hãy tưởng tượng rằng bạn đã viết một số mã và kiểm tra nó, sửa tất cả các lỗi bạn tìm thấy và đặt mã đó lên trang web. Sau đó, người dùng gửi phản hồi về các lỗi mới và yêu cầu về các tính năng mới. Bạn quay lại mã, sửa lỗi và thêm các tính năng mới. Trong trường hợp này, một tình huống có thể xảy ra là các lỗi cũ lại xuất hiện, tình huống này được gọi là "hồi quy". Bạn phải kiểm tra lại mọi thứ một lần nữa. Và rất có thể bạn sẽ không tìm ra được lỗi lầm cũ của mình. Trong mọi trường hợp, sẽ phải mất thời gian trước khi bạn nhận ra rằng vấn đề là do “hồi quy”. Khi sử dụng thử nghiệm đơn vị, bạn viết một bài kiểm tra. Sau khi mã được sửa đổi, bạn lọc lại mã đó qua quá trình kiểm tra. Nếu xảy ra hồi quy thì một số thử nghiệm sẽ thất bại và bạn có thể dễ dàng xác định phần nào của mã có lỗi. Vì bạn biết mình đã thay đổi những gì nên lỗi sẽ dễ dàng sửa được.

    Một ưu điểm khác của thử nghiệm đơn vị (đặc biệt là phát triển web) là dễ dàng kiểm tra khả năng tương thích giữa nhiều trình duyệt. Bạn chỉ cần chạy thử nghiệm trên các trình duyệt khác nhau. Nếu phát hiện thấy sự cố trong trình duyệt, bạn có thể khắc phục chúng và chạy lại kiểm tra. Do đó, bạn sẽ tự tin rằng tất cả các trình duyệt mục tiêu đều được hỗ trợ vì chúng đều đã được thử nghiệm.

    Cách viết bài kiểm tra đơn vị trong QUnit

    Vậy làm thế nào để bạn trực tiếp viết bài kiểm tra đơn vị trong QUnit? Bước đầu tiên là cài đặt môi trường thử nghiệm:

    Bộ kiểm tra QUnit Bộ kiểm tra QUnit

    Mã sẽ được kiểm tra sẽ nằm trong tệp myProject.js và các kiểm tra sẽ đi vào myTests.js. Để chạy thử nghiệm, bạn chỉ cần mở tệp HTML trong trình duyệt của mình. Bây giờ là lúc để viết một số bài kiểm tra.

    Khối xây dựng của thử nghiệm đơn vị là sự khẳng định.

    "Xác nhận là một biểu thức dự đoán kết quả trả về khi mã của bạn được thực thi. Nếu dự đoán không chính xác thì xác nhận đó có giá trị SAI, cho phép chúng tôi đưa ra kết luận về sự hiện diện của sai sót."

    Để thực hiện các xác nhận, chúng cần được đặt trong khối kiểm tra:

    // kiểm tra hàm này function isEven(val) ( return val % 2 === 0; ) test("isEven()", function() ( ok(isEven(0), "Zero là số chẵn"); ok ( isEven(2), "Hai cũng là"); ok(isEven(-4), "Và âm bốn cũng là số chẵn"); isEven(-7), "Giống như âm 7 là số lẻ");

    Ở đây chúng ta định nghĩa một hàm là chẵn, kiểm tra tính chẵn lẻ của một số và chúng tôi muốn đảm bảo rằng hàm này không trả về các giá trị sai.

    Đầu tiên chúng ta gọi hàm Bài kiểm tra(), xây dựng một khối thử nghiệm. Tham số đầu tiên là chuỗi sẽ được xuất ra. Tham số thứ hai là hàm trả về chứa các xác nhận của chúng tôi. Hàm gọi lại này sẽ được gọi một lần trong quá trình thực thi QUnit.

    Chúng tôi đã viết năm tuyên bố, tất cả đều hợp lý. Câu lệnh logic giả định rằng tham số đầu tiên có giá trị ĐÚNG VẬY. Tham số thứ hai là thông báo được hiển thị trong kết quả.

    Đây là những gì chúng tôi nhận được sau khi chạy thử nghiệm:

    Tất cả các tuyên bố của chúng tôi đã được xác nhận thành công, vì vậy chúng tôi có thể giả sử rằng hàm isEven() hoạt động như mong đợi.

    Hãy xem điều gì xảy ra nếu phát biểu đó là sai.

    // kiểm tra hàm này function isEven(val) ( return val % 2 === 0; ) test("isEven()", function() ( ok(isEven(0), "Zero là số chẵn"); ok ( isEven(2), "Hai cũng là"); ok(isEven(-4), "Và âm bốn cũng là số chẵn"); isEven(-7), "Giống như âm 7 là số lẻ"); // Error ok(isEven(3), "Ba là số chẵn");

    Và đây là kết quả chúng tôi nhận được khi chạy thử nghiệm:


    Tuyên bố có chứa một lỗi mà chúng tôi đã cố ý thực hiện. Nhưng trong dự án của bạn, nếu một số thử nghiệm thất bại và tất cả các câu lệnh khác đều đúng thì sẽ rất dễ tìm ra lỗi.

    Các tuyên bố khác

    ok() không phải là câu lệnh duy nhất mà QUnit hỗ trợ. Có nhiều loại xác nhận khác thuận tiện để sử dụng khi viết bài kiểm tra cho dự án của bạn:

    Tuyên bố so sánh

    Tuyên bố so sánh bằng() giả định rằng tham số đầu tiên (là giá trị thực) tương đương với tham số thứ hai (là giá trị mong đợi). Tuyên bố này rất giống với Được rồi(), nhưng nó xuất ra cả giá trị thực và giá trị mong đợi, giúp việc gỡ lỗi mã dễ dàng hơn nhiều. Cũng như Được rồi(), bằng() có thể chấp nhận một thông báo cho đầu ra dưới dạng tham số thứ ba.

    Vì vậy thay vào đó

    Test("xác nhận", function() ( ok(1 == 1, "một tương đương với một"); ))


    Nên được sử dụng:

    Test("xác nhận", function() ( bằng(1, 1, "một tương đương với một"); ))


    Lưu ý rằng giá trị mong đợi được in ở cuối dòng.

    Và nếu các giá trị không bằng nhau:

    Test("xác nhận", function() ( bằng(2, 1, "một tương đương với một"); ))


    Mục này cung cấp thêm thông tin.

    Xác nhận so sánh sử dụng toán tử “==” để kiểm tra các tham số, do đó nó không thể hoạt động với mảng hoặc đối tượng:

    Test("test", function() ( bằng((), (), "lỗi, đây là những đối tượng khác nhau"); bằng((a: 1), (a: 1) , "error"); bằng(, , "lỗi, đây là các mảng khác nhau"); bằng(, , "lỗi");

    Đối với những trường hợp như vậy, QUnit có xác nhận danh tính.

    Khẳng định danh tính

    Khẳng định danh tính như nhau() sử dụng các tham số tương tự như bằng(), nhưng nó không chỉ hoạt động với các kiểu nguyên thủy mà còn với các mảng và đối tượng. Các câu lệnh từ ví dụ trước sẽ vượt qua bài kiểm tra nếu được thay đổi từ câu lệnh nhận dạng:

    Test("test", function() ( Same((), (), "vượt qua, các đối tượng có cùng nội dung"); giống nhau((a: 1), (a: 1) , "vượt qua"); giống nhau( , , "vượt qua, các mảng có cùng nội dung"); giống nhau(, , "vượt qua");

    Xin lưu ý rằng như nhau() sử dụng toán tử '===' để so sánh, do đó thuận tiện khi sử dụng để so sánh các giá trị đặc biệt:

    Test("test", function() ( bằng(0, false, "true"); tương tự(0, sai, "false"); bằng(null, không xác định, "true"); tương tự(null, không xác định, " SAI"); ))

    Cấu trúc câu lệnh

    Đặt tất cả các xác nhận vào một bài kiểm tra là một ý tưởng rất tồi. Việc kiểm tra như vậy sẽ khó duy trì và bạn có thể bối rối khi đánh giá kết quả thực hiện nó. Do đó, bạn cần cấu trúc bài kiểm tra bằng cách đặt các câu lệnh thành các khối riêng biệt, mỗi khối sẽ nhắm đến một nhóm chức năng cụ thể.

    Bạn có thể tổ chức các mô-đun riêng lẻ bằng cách sử dụng lệnh gọi hàm mô-đun:

    Mô-đun ("Mô-đun A"); test("Kiểm tra", function() ()); test("Một bài kiểm tra khác", function() ()); mô-đun ("Mô-đun B"); test("Kiểm tra", function() ()); test("Một bài kiểm tra khác", function() ());


    Trong ví dụ trước, tất cả các câu lệnh được gọi một cách đồng bộ, nghĩa là chúng được thực thi lần lượt. Có nhiều hàm không đồng bộ trong thế giới thực, chẳng hạn như các yêu cầu hoặc hàm AJAX setTimeout()setInterval(). Làm cách nào để chúng tôi kiểm tra loại chức năng này? QUnit có loại thử nghiệm đặc biệt gọi là "thử nghiệm không đồng bộ" được thiết kế để thử nghiệm không đồng bộ:

    Đầu tiên, chúng ta hãy thử viết một bài kiểm tra theo cách thông thường:

    Test("Kiểm tra không đồng bộ", function() ( setTimeout(function() ( ok(true); ), 100) ))


    Có vẻ như không có khẳng định nào trong bài kiểm tra. Bởi vì câu lệnh được thực thi đồng bộ, nhưng vào thời điểm hàm được gọi thì quá trình kiểm tra đã hoàn thành.

    Cách chính xác để kiểm tra ví dụ của chúng tôi là:

    Test("Asynchronous test", function() ( // Đặt bài kiểm tra vào chế độ tạm dừng stop(); setTimeout(function() ( ok(true); // Sau khi gọi xác nhận // tiếp tục kiểm tra start(); ) , 100) ))


    Chúng tôi đã sử dụng chức năng dừng lại()để dừng kiểm tra và sau khi thực hiện xác nhận, hãy chạy lại kiểm tra bằng hàm bắt đầu().

    Gọi một hàm dừng lại() ngay sau khi gọi hàm Bài kiểm tra() là một thực tế rất phổ biến. Đó là lý do tại sao QUnit có chữ viết tắt đặc biệt: asyncTest(). Ví dụ trước có thể được viết lại thành:

    AsyncTest("Asynchronous test", function() ( // Bài kiểm tra được tự động chuyển sang chế độ "tạm dừng" setTimeout(function() ( ok(true); // Sau khi gọi xác nhận // tiếp tục kiểm tra start(); ) , 100) ) )

    Có một điểm đáng suy nghĩ: hàm setTimeout() luôn gọi hàm gọi lại của nó và nếu kiểm tra một hàm khác (ví dụ: lệnh gọi AJAX). Làm thế nào bạn có thể chắc chắn rằng hàm gọi lại sẽ được gọi? Nếu hàm trả về không được gọi thì hàm bắt đầu() cũng sẽ không được gọi và toàn bộ thử nghiệm sẽ bị đóng băng:


    Bạn có thể tổ chức kiểm tra như sau:

    // Hàm tùy chỉnh function ajax(successCallback) ( $.ajax(( url: "server.php", Success: SuccessCallback )); ) test("Asynchronous test", function() ( // Dừng kiểm tra và // báo cáo lỗi nếu hàm start() không được gọi sau 1 giây stop(1000); ajax(function() ( // ...câu lệnh không đồng bộ start(); )) ))

    Để hoạt động dừng lại() giá trị thời gian chờ được truyền đi. Bây giờ QUnit được thông báo: “if function bắt đầu() sẽ không được gọi sau khi hết thời gian chờ, thử nghiệm này sẽ được coi là thất bại.” Bây giờ toàn bộ quá trình kiểm tra sẽ không bị treo và cảnh báo sẽ được đưa ra nếu có sự cố.

    Bây giờ hãy xem xét trường hợp có nhiều hàm không đồng bộ. Vị trí đặt chức năng bắt đầu()? Bạn cần đặt nó trong một chức năng setTimeout():

    // Hàm tùy chỉnh function ajax(successCallback) ( $.ajax(( url: "server.php", thành công: thành côngCallback )); ) test("Async test", function() ( // Dừng kiểm tra stop(); ajax (function() ( // ...câu lệnh không đồng bộ )) ajax(function() ( // ...câu lệnh không đồng bộ )) setTimeout(function() ( start(); ), 2000 ));

    Giá trị thời gian chờ phải đủ để cho phép cả hai lệnh gọi lại hoàn tất trước khi tiếp tục thử nghiệm. Nếu một trong các hàm không được gọi, làm thế nào chúng ta có thể xác định được hàm nào? Có một chức năng cho việc này trông chờ():

    // Hàm tùy chỉnh function ajax(successCallback) ( $.ajax(( url: "server.php", thành công: thành côngCallback )); ) test("Kiểm tra không đồng bộ", function() ( // Dừng kiểm tra stop(); // Nói với QUnit rằng chúng ta mong đợi ba câu lệnh sẽ được thực thi. Expect(3); ajax(function() ( ok(true); )) ajax(function() ( ok(true); ok(true); )) setTimeout( hàm( ) ( bắt đầu(); ), 2000 ))

    Chúng tôi chuyển đến chức năng trông chờ() số lượng câu lệnh được lên kế hoạch thực hiện. Nếu một trong các câu lệnh không thành công, bạn sẽ nhận được thông báo cho biết có điều gì đó không diễn ra như kế hoạch.

    Có đoạn ghi âm ngắn để bạn sử dụng trông chờ(): bạn cần chuyển số lượng câu lệnh được lên lịch làm tham số thứ hai Bài kiểm tra() hoặc asyncTest():

    // Hàm tùy chỉnh ajax(successCallback) ( $.ajax(( url: "server.php", thành công: thành côngCallback )); ) // Nói với QUnit rằng chúng tôi mong đợi 3 câu lệnh sẽ được thực thi test("asynchronous test", 3 , function() ( // Dừng kiểm tra stop(); ajax(function() ( ok(true); )) ajax(function() ( ok(true); ok(true); )) setTimeout(function() ( bắt đầu(); ), 2000);

    Phần kết luận

    Trong hướng dẫn này, chúng tôi đã cung cấp mọi thứ bạn cần để bắt đầu với QUnit. Kiểm thử đơn vị là một phương pháp tuyệt vời để kiểm tra mã trước khi sử dụng. Nếu bạn chưa từng sử dụng bất kỳ bài kiểm tra nào trước đây thì bây giờ là lúc để bắt đầu.

    Kiểm tra kiến ​​thức về các chủ đề sau hiện có sẵn trên trang web: 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 trình độ hiểu biết của bạn một cách kỹ lưỡng nhất có thể.

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

    Thủ tục kiểm tra:

  • Theo liên kết "Bắt đầu thử nghiệm" cho bài kiểm tra tương ứng.
  • Trả lời các câu hỏi đặt ra bằng cách chọn phương án đúng duy nhất.
  • Sau khi hoàn thành bài kiểm tra, bạn sẽ thấy điểm của mình, số lỗi mắc phải cũng như phần phân tích từng câu hỏi trong bài kiểm tra.
  • Chú ý! Bạn sẽ không thể quay lại câu hỏi trước đó nên hãy suy nghĩ trước khi trả lời.

    Các xét nghiệm hiện có
  • HTML
    • Tổng số bài thi đã thực hiện: 75.424 người
    • Điểm trung bình: 2,83/5 điểm.

    Kiểm tra cơ bản về HTML. Bạn sẽ cần có kiến ​​thức về các thẻ HTML cơ bản cũng như cách sử dụng thành thạo chúng. Cũng cần phải hiểu các tính năng của tiêu chuẩn XHTML 1.1.

  • CSS
    • Tổng số bài đã thực hiện: 32828 người
    • Điểm trung bình: 3,37/5 điểm.

    Bài kiểm tra kiểm tra kiến ​​thức cơ bản về 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 chính (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 biết mục đích của các phần tử giả phổ biến nhất.

  • JavaScript
    • Tổng số bài kiểm tra đã thực hiện: 24845 người
    • Điểm trung bình: 3,31/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 kiểm tra bao gồm các lĩnh vực ứng dụng khác nhau của ngôn ngữ này. Có rất nhiều câu hỏi về việc hiểu các sắc thái “nhỏ”. Mặt khác, bạn được yêu cầu phải biết những điều cơ bản: làm việc với các biến, hàm JavaScript cơ bản, mức độ ưu tiên hoạt động, v.v.

  • PHP
    • Tổng số bài thi đã thực hiện: 33.239 người
    • Điểm trung bình: 3,03/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 được yêu cầu 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.
    Chúng tôi vui lòng yêu cầu: Bài kiểm tra có nhiều câu hỏi như: “Kịch bản sẽ xuất ra cái gì?” Vui lòng không sao chép hoặc kiểm tra nó. Hãy thành thật với chính mình.

  • SQL
    • Tổng số bài thi đã thực hiện: 18.014 người
    • Điểm trung bình: 3,28/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ỉ bao gồm những kiến ​​thức cơ bản nhất của ngôn ngữ này, không có chiều sâu. Bạn sẽ cần kiến ​​thức về các truy vấn SQL cơ bản nhất cũng như cách sử dụng thành thạo chúng.