Rumah  >  Artikel  >  hujung hadapan web  >  Ingat untuk melindungi pelanggan anda!

Ingat untuk melindungi pelanggan anda!

王林
王林asal
2023-09-07 13:49:051305semak imbas

Dengan memastikan aplikasi anda diuji, anda boleh mengurangkan bilangan pepijat yang ditemui dalam kod anda, meningkatkan kebolehselenggaraan aplikasi anda dan mereka bentuk kod yang tersusun dengan baik.

Ujian unit sisi pelanggan memberikan cabaran yang berbeza daripada ujian sisi pelayan. Apabila bekerja dengan kod pihak pelanggan, anda akan mendapati diri anda bergelut untuk memisahkan logik aplikasi daripada logik DOM, dan selalunya hanya membina kod JavaScript. Nasib baik, terdapat banyak perpustakaan ujian sisi pelanggan yang hebat yang boleh membantu menguji kod anda, mencipta metrik tentang liputan ujian dan menganalisis kerumitannya.


Mengapa menguji?

Pertama sekali, ujian unit selalunya merupakan cara untuk mengurangkan ralat dengan memastikan aplikasi berkelakuan seperti yang diharapkan. Selain itu, terdapat juga konsep Pembangunan Didorong Ujian (TDD) dan Pembangunan Didorong Kelakuan (BDD).

Dua strategi ujian unit ini akan membantu anda mereka bentuk aplikasi anda dengan menulis ujian sebelum menulis logik aplikasi. Dengan menulis ujian sebelum menulis kod, anda akan mempunyai peluang untuk berfikir dengan teliti tentang reka bentuk aplikasi anda.

Ini berlaku kerana apabila anda menulis ujian, anda pada asasnya cuba mereka bentuk API yang berinteraksi dengan kod tersebut, supaya anda boleh memahami reka bentuknya dengan lebih baik. Pengujian terlebih dahulu akan segera mendedahkan sebarang kelemahan dalam reka bentuk kerana kod ujian yang anda tulis pada asasnya menggunakan kod yang anda tulis!

TDD ialah proses penemuan kod

Anda akan mengetahui bahawa TDD membantu anda menemui kod semasa anda menulisnya. TDD boleh diringkaskan dengan cepat sebagai "Merah, Hijau, Refactor." Ini bermakna, anda menulis ujian, tulis kod yang mencukupi untuk membuat ujian gagal di tempat pertama. Kemudian , anda tulis kod yang membuat ujian itu lulus. Selepas itu, anda fikirkan dengan teliti tentang apa yang baru anda tulis dan bina semula. Senang dan mudah.

BDD berbeza sedikit daripada TDD dan lebih berdasarkan keperluan dan spesifikasi perniagaan.


Ujian Pelanggan

Terdapat banyak sebab mengapa anda perlu menguji kod pelanggan anda. Seperti yang dinyatakan sebelum ini, ia akan membantu mengurangkan ralat dan membantu anda mereka bentuk aplikasi anda. Ujian sisi pelanggan juga penting kerana ia memberi anda peluang untuk menguji kod bahagian hadapan secara bebas, jauh daripada pembentangan. Dengan kata lain, salah satu kelebihannya ialah anda boleh menguji kod JavaScript tanpa benar-benar memulakan pelayan aplikasi. Daripada mengklik dan menguji, anda hanya boleh menjalankan ujian dan memastikan kefungsian berfungsi. Dalam kebanyakan kes, anda tidak memerlukan akses internet pun selagi anda menyediakan ujian anda dengan betul.

Dengan JavaScript memainkan peranan penting dalam pembangunan web moden, adalah penting untuk mempelajari cara menguji kod anda dan mengurangkan peluang pepijat memasuki kod pengeluaran. Bos anda tidak suka perkara ini berlaku, dan begitu juga anda! Malah, tempat yang baik untuk bermula dengan ujian pihak pelanggan ialah dengan menulis ujian anda di sekitar pelaporan ralat. Ini akan membolehkan anda berlatih ujian menulis apabila anda tidak mempunyai tempat untuk bermula dari awal.

Sebab lain untuk menguji kod pelanggan anda ialah apabila satu set ujian wujud dan anda mempunyai liputan yang betul bagi kod anda, apabila anda bersedia untuk menambah fungsi baharu pada kod anda, anda akan dapat menambah fungsi baharu, semula -jalankan ujian anda dan pastikan anda tidak merendahkan atau memecahkan sebarang fungsi sedia ada.


Mulakan

Jika anda tidak pernah melakukan ujian pelanggan sebelum ini, bermula dengan ujian pelanggan boleh menjadi menakutkan. Salah satu bahagian paling sukar dalam ujian pihak pelanggan ialah memikirkan cara terbaik untuk mengasingkan DOM daripada logik aplikasi. Ini biasanya bermakna anda memerlukan beberapa jenis abstraksi ke atas DOM. Cara paling mudah untuk mencapai ini adalah melalui rangka kerja pihak pelanggan seperti Knockout.js, Backbone.js atau Angular.js, hanya untuk menamakan beberapa.

Apabila menggunakan perpustakaan seperti ini, anda boleh kurang memikirkan cara halaman anda dipaparkan dalam penyemak imbas dan lebih lanjut tentang fungsi aplikasi anda. Walau bagaimanapun, ujian unit dengan JavaScript mudah tidak mustahil. Dalam kes ini, hidup anda akan menjadi lebih mudah jika anda mereka bentuk kod anda dengan cara yang DOM boleh diabstrakkan dengan mudah.

Pilih perpustakaan ujian

Terdapat banyak perpustakaan ujian yang berbeza untuk dipilih, walaupun ketiga-tiga pemimpin itu cenderung kepada QUnit, Mocha dan Jasmine.

Jasmine dan Mocha kedua-duanya berasal dari sekolah ujian unit BDD, manakala QUnit hanyalah rangka kerja ujian unit sendiri.

Dalam sisa artikel ini, kami akan meneroka menggunakan QUnit kerana ia mempunyai halangan masuk yang sangat rendah untuk ujian pihak pelanggan. Lihat pengenalan terperinci QUnit untuk maklumat lanjut.

Gunakan QUnit TDD kod anda

QUnit Bermula adalah mudah. Apa yang anda perlukan ialah HTML berikut:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>QUnit Example</title>
    <link rel="stylesheet" href="qunit.css">
</head>
<body>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>
    <script src="qunit.js"></script>
    <script src="../app/yourSourceCode.js"></script>
    <script src="tests.js"></script>
</body>
</html>

Untuk beberapa contoh seterusnya, katakan kami sedang membina widget yang anda masukkan kod zip ke dalam kotak teks dan ia mengembalikan nilai bandar, negeri dan daerah yang sepadan menggunakan Geonames. Ia hanya memaparkan kod zip pada mulanya, tetapi setelah kod zip mempunyai lima aksara, ia mendapatkan semula data daripada Geonames. Jika data boleh ditemui, ia akan memaparkan lebih banyak medan yang mengandungi maklumat bandar, negeri dan daerah yang terhasil. Kami juga akan menggunakan Knockout.js. Langkah pertama ialah menulis ujian yang gagal.

Fikirkan sedikit tentang reka bentuk sebelum menulis ujian pertama anda, anda mungkin memerlukan sekurang-kurangnya dua ViewModel, jadi ini akan menjadi titik permulaan yang baik. Mula-mula, kami akan mentakrifkan modul QUnit dan ujian pertama kami:

module("zip code retriever");
test("view models should exist", function() {
    ok(FormViewModel, "A viewModel for our form should exist");
    ok(AddressViewModel, "A viewModel for our address should exist");
});

如果你运行这个测试,它会失败,现在你可以编写代码让它通过:

Ingat untuk melindungi pelanggan anda!

var AddressViewModel = function(options) {

};

var FormViewModel = function() {
    this.address = new AddressViewModel();
};

这次您会看到绿色而不是红色。像这样的测试乍一看有点愚蠢,但它们很有用,因为它们迫使您至少思考设计的一些早期阶段。

Ingat untuk melindungi pelanggan anda!

我们将编写的下一个测试将适用于 AddressViewModel 的功能。从这个小部件的规范中我们知道,其他字段应该首先隐藏,直到找到邮政编码的数据。

module("address view model");
test("should show city state data if a zip code is found", function() {
    var address = new AddressViewModel();

    ok(!address.isLocated());

    address.zip(12345);
    address.city("foo");
    address.state("bar");
    address.county("bam");

    ok(address.isLocated());
});

尚未编写任何代码,但这里的想法是 isLocated 将是一个计算的可观察值,仅当邮政编码、城市、州和县时才返回 true都是实话。所以,这个测试一开始当然会失败,现在让我们编写代码让它通过。

var AddressViewModel = function(options) {
    options = options || {};

    this.zip = ko.observable(options.zip);
    this.city = ko.observable(options.city);
    this.state = ko.observable(options.state);
    this.county = ko.observable(options.county);

    this.isLocated = ko.computed(function() {
        return this.city() && this.state() && this.county() && this.zip();
    }, this);

    this.initialize();
};

现在,如果您再次运行测试,您将看到绿色!

这是最基本的,如何使用 TDD 编写前端测试。理想情况下,在每次失败的测试之后,您应该编写最简单的代码来使测试通过,然后返回并重构代码。不过,您可以了解更多有关 TDD 实践的知识,因此我建议您进一步阅读并研究它,但前面的示例足以让您考虑首先编写测试。

使用Sinon.js模拟依赖关系

Sinon.js 是一个 JavaScript 库,提供监视、存根和模拟 JavaScript 对象的功能。编写单元测试时,您希望确保只能测试给定的代码“单元”。这通常意味着您必须对依赖项进行某种模拟或存根以隔离正在测试的代码。

Sinon 有一个非常简单的 API 可以完成此操作。 Geonames API 支持通过 JSONP 端点检索数据,这意味着我们将能够轻松使用 $.ajax

理想情况下,您不必在测试中依赖 Geonames API。它们可能会暂时关闭,您的互联网可能会中断,并且实际进行 ajax 调用的速度也会变慢。诗乃前来救援。

test("should only try to get data if there's 5 chars", function() {
    var address = new AddressViewModel();

    sinon.stub(jQuery, "ajax").returns({
        done: $.noop
    });

    address.zip(1234);

    ok(!jQuery.ajax.calledOnce);

    address.zip(12345);

    ok(jQuery.ajax.calledOnce);

    jQuery.ajax.restore();
});

在此测试中,我们做了一些事情。首先,sinon.stub 函数实际上将代理 jQuery.ajax 并添加查看其被调用次数以及许多其他断言的功能。正如测试所示,“应该仅在有 5 个字符时尝试获取数据”,我们假设当地址设置为“1234”时,尚未进行 ajax 调用,然后将其设置为“12345”,此时应进行 ajax 调用。

然后我们需要将 jQuery.ajax 恢复到其原始状态,因为我们是单元测试的好公民,并且希望保持我们的测试原子性。保持测试的原子性非常重要,可以确保一个测试不依赖于另一测试,并且测试之间不存在共享状态。然后它们也可以按任何顺序运行。

现在测试已经编写完毕,我们可以运行它,观察它失败,然后编写向 Geonames 执行 ajax 请求的代码。

AddressViewModel.prototype.initialize = function() {
    this.zip.subscribe(this.zipChanged, this);
};

AddressViewModel.prototype.zipChanged = function(value) {
    if (value.toString().length === 5) {
        this.fetch(value);
    }
};

AddressViewModel.prototype.fetch = function(zip) {
    var baseUrl = "http://www.geonames.org/postalCodeLookupJSON"

    $.ajax({
        url: baseUrl,
        data: {
            "postalcode": zip,
            "country": "us"
        },
        type: "GET",
        dataType: "JSONP"
    }).done(this.fetched.bind(this));
};

在这里,我们订阅邮政编码的更改。每当它发生变化时,都会调用 zipChanged 方法。 zipChanged 方法将检查 zip 值的长度是否为 5。当到达 5 时,将调用 fetch 方法。这就是Sinon 存根发挥作用的地方。此时,$.ajax实际上是一个Sinon存根。因此,在测试中 CalledOnce 将是 true

我们将编写的最终测试是数据从 Geonames 服务返回时的情况:

test("should set city info based off search result", function() {
    var address = new AddressViewModel();

    address.fetched({
        postalcodes: [{
            adminCode1: "foo",
            adminName2: "bar",
            placeName: "bam"
        }]
    });

    equal(address.city(), "bam");
    equal(address.state(), "foo");
    equal(address.county(), "bar");
});

此测试将测试如何将来自服务器的数据设置到 AddressViewmodel 上。运行一下,看到一些红色。现在将其设为绿色:

AddressViewModel.prototype.fetched = function(data) {
    var cityInfo;

    if (data.postalcodes && data.postalcodes.length === 1) {
        cityInfo = data.postalcodes[0];

        this.city(cityInfo.placeName);
        this.state(cityInfo.adminCode1);
        this.county(cityInfo.adminName2);
    }
};

fetched方法只是确保从服务器传来的数据中有一个postalcodes数组,然后在viewModel上设置相应的属性。

看看这现在有多容易了吗?一旦你掌握了执行此操作的流程,你就会发现自己几乎不想再进行 TDD。您最终会得到可测试的漂亮小函数。您强迫自己思考代码如何与其依赖项交互。现在,当代码中添加其他新需求时,您可以运行一套测试。即使您错过了某些内容并且代码中存在错误,您现在也可以简单地向套件添加新测试,以证明您已经修复了错误!它实际上最终会让人上瘾。


测试覆盖率

测试覆盖率提供了一种简单的方法来评估单元测试测试了多少代码。达到 100% 的覆盖率通常很困难且不值得,但请尽您所能使其尽可能高。

更新且更简单的覆盖库之一称为 Blanket.js。将它与 QUnit 一起使用非常简单。只需从他们的主页获取代码或使用 Bower 安装即可。然后将毯子添加为 qunit.html 文件底部的库,然后将 data-cover 添加到您想要进行覆盖率测试的所有文件。

    <script src="../app/yourSourceCode.js" data-cover></script>
    <script src="../js/lib/qunit/qunit/qunit.js"></script>
    <script src="../js/lib/blanket/dist/qunit/blanket.js"></script>
    <script src="tests.js"></script>
</body>

完成。超级简单,现在您将在 QUnit 运行程序中获得一个用于显示覆盖范围的选项:

Ingat untuk melindungi pelanggan anda!

在此示例中,您可以看到测试覆盖率并不是 100%,但在这种情况下,由于代码不多,因此很容易提高覆盖率。您实际上可以深入了解尚未涵盖的确切功能:

Ingat untuk melindungi pelanggan anda!

在这种情况下,FormViewModel 从未在测试中实例化,因此缺少测试覆盖率。然后,您可以简单地添加一个新测试来创建 FormViewModel 的实例,并且可能编写一个断言来检查 address 属性是否存在并且是 instanceOf AddressViewModel

然后您将很高兴看到 100% 的测试覆盖率。

Ingat untuk melindungi pelanggan anda!


复杂性测试

随着您的应用程序变得越来越大,能够对 JavaScript 代码运行一些静态分析是件好事。 Plato 是一个在 JavaScript 上运行分析的好工具。

您可以通过 npm 安装来运行 plato

npm install -g plato

然后您可以在 JavaScript 代码目录上运行 plato

plato -r -d js/app reports

这将在位于“js/app”的所有 JavaScript 上运行 Plato,并将结果输出到 reports。 Plato 对您的代码运行各种指标,包括平均代码行数、计算的可维护性分数、JSHint、难度、估计错误等等。

Ingat untuk melindungi pelanggan anda!

在上一张图片中没有太多可看的内容,仅仅是因为对于我们一直在处理的代码来说,只有一个文件,但是当您开始使用具有大量文件的大型应用程序时,几行代码,您会发现它为您提供的信息非常有用。

它甚至会跟踪您运行它的所有时间,以便您可以查看统计数据如何随时间变化。

结论

虽然测试客户端似乎是一个困难的提议,但现在有很多很棒的工具可以使用,使它变得超级简单。本文仅仅触及了当今所有使客户端测试变得容易的事情的表面。这可能是一项乏味的任务,但最终您会发现,拥有测试套件和可测试代码的好处远远超过它。希望通过此处概述的步骤,您将能够快速开始测试客户端代码。

Atas ialah kandungan terperinci Ingat untuk melindungi pelanggan anda!. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn