JavaScript基础笔记(十三)测试和调试

错误处理与测试

一、错误处理

一)try-catch语句

function atest() {
        try {
            //可能发生错误的代码
            return 0;
        } catch (error) {
            //错误处理程序
            console.log(error.message);
            return 1;
        } finally {
            //无论如何都会执行的,函数最后返回2
            return 2;
        }
    }

错误类型:

1)Error:错误基类,其他错误类型都由该类继承。

2)EvalError:没有把eval()当函数调用时,会发送该错误。

3)RangeError:数值超出范围

4)ReferenceError:找不到对象时

5)SyntaxError:传入eval()函数的语法错误时

6)TypeError:变量的类型不符合要求

合理使用try-catch:

使用 try-catch 最适合处理那些我们无法控制的错误。假设你在使用一个大型 JavaScript 库中的
函数,该函数可能会有意无意地抛出一些错误。由于我们不能修改这个库的源代码,所以大可将对该函
数的调用放在 try-catch 语句当中,万一有什么错误发生,也好恰当地处理它们。
在明明白白地知道自己的代码会发生错误时,再使用 try-catch 语句就不太合适了。例如,如果
传递给函数的参数是字符串而非数值,就会造成函数出错,那么就应该先检查参数的类型,然后再决定
如何去做。在这种情况下,不应用使用 try-catch 语句。

二)抛出错误

使用throw操作符可以抛出错误,对抛出的值没有要求

//有效
throw 111;
throw ''ss;

在遇到 throw 操作符时,代码会立即停止执行。仅当有 try-catch 语句捕获到被抛出的值时,代
码才会继续执行。

通过使用某种内置错误类型,可以更真实地模拟浏览器错误。每种错误类型的构造函数接收一个参
数,即实际的错误消息。

throw new Error("An error");

何时抛出与捕获:

只应该捕获那些你确切地知道该如何处理的错误。捕获错误的
目的在于避免浏览器以默认方式处理它们;而抛出错误的目的在于提供错误发生具体原因的消息。 

三)错误事件

 任何没有通过 try-catch 处理的错误都会触发 window 对象的 error 事件 ,在任何 Web 浏览器中, onerror 事件处理程序都不会创建 event 对象,
但它可以接收三个参数:错误消息、错误所在的 URL 和行号 。要指定 onerror 事件处理程序,必须使用如下所示的 DOM0 级技术,它没有遵循“DOM2
事件”的标准格式。

window.onerror = function(msg, url, line) {
    log(msg);
//阻止浏览器报告错误的行为
return fales;
}

二、测试

一)日志记录

//一个适用于所有浏览器的log
function log() {
        try {
            console.log.apply(console, arguments);
        }
        catch(e) {
            try {
                opera.postError.apply(opera, arguments);
            }
            catch (e) {
                alert(Array.prototype.join.call(arguments, " "));
            }
        }
    }

二)测试用例

一个好的测试用例的三个特征:

1)可重用性:多次运行应该产生相同的结果

2)简单性:只专注与测试,消除多余代码的影响

3)独立性:避免一个测试结果依赖于另一个结果

三)测试套件

测试套件的主要目的是聚合代码种的所有单个测试,将其组合成一个单位,这样他们可以批量运行,提供一个可以轻松反复运行的单一资源。

1)断言:

自己实现一个断言:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    #results li.pass {
        color: green;
    }
    #results li.fail {
        color: red;
    }
</style>
<body>
<ul id="results"></ul>
</body>
</html>
<script>
    function assert(value, desc) {
        var liElement = document.createElement("li");
        liElement.className = value ? "pass" : "fail";
        liElement.appendChild(document.createTextNode(desc));
        document.getElementById("results").appendChild(liElement);
    }
    window.onload = function () {
        assert(true, "Success");
        assert(false, "Fail");
    }
</script>

2)测试分组的实现:

(function () {
        var results;
        this.assert = function assert(value, desc) {
            var li = document.createElement("li");
            li.className = value ? "pass" : "fail";
            li.appendChild(document.createTextNode(desc));
            results.appendChild(li);
            if (!value) {
                li.parentNode.parentNode.className = "fail";
            }
            return li;
        }

        this.test = function test(name, fn) {
            results = document.getElementById("results");
            results = assert(true, name).
            appendChild(document.createElement("ul"));
            fn();
        }
    })();

    window.onload = function (ev) {
        test("all true", function () {
           assert(true, "111");
           assert(true, "222");
           assert(true, "333");
        });
        test("one false", function () {
           assert(false, "failed");
           assert(true, "success");
           assert(true, "xxx");
        });
    }

3)异步测试

(function () {
        var queue = [], paused = false, results;
        this.assert = function assert(value, desc) {
            var li = document.createElement("li");
            li.className = value ? "pass" : "fail";
            li.appendChild(document.createTextNode(desc));
            results.appendChild(li);
            if (!value) {
                li.parentNode.parentNode.className = "fail";
            }
            return li;
        };

        this.test = function test(name, fn) {
            queue.push(function () {
                results = document.getElementById("results");
                results = assert(true, name).
                appendChild(document.createElement("ul"));
                fn();
            });
            runTest();
        };

        function runTest() {
            if (!paused && queue.length) {
                queue.shift()();
                if (!paused) {
                    resume();
                }
            }
        }

        this.pause = function () {
            paused = true;
        };

        this.resume = function resume() {
            paused = false;
            setTimeout(runTest, 1);
        }
    })();

    window.onload = function (ev) {
        test("First async test", function () {
            pause();
            setTimeout(function () {
                assert(true, "First async completed!");
                resume();
            }, 1000);
        });

        test("Second async test", function () {
            pause();
            setTimeout(function () {
                assert(true, "Second async test completed!");
                resume();
            }, 1000);
        });
    }
Simple is important!
原文地址:https://www.cnblogs.com/Shadowplay/p/8701239.html