gremlins.js是一个用 Java 编写的Monkey测试库,用于 Node.js 和浏览器。通过释放大量不规律的 gremlins 来检测 Web 应用的鲁棒性、健壮性。

Gremlins.js模拟用户随机操作如:单击窗口中的任意位置,在表格中输入随机数据,或者将鼠标移动到不指望它的元素。它的目标:触发JavaScript错误,或使应用程序报错。如果Gremlins.js不能破坏一个应用程序,恭喜!该应用程序是强大的,就能够释放给真正的用户。

Monkey测试,可以运行在模拟器里或实际设备中,向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等),实现对正在开发的应用程序进行压力测试。Monkey测试是一种为了测试软件的稳定性、健壮性的快速有效的方法。

简便使用方法:

1、打开浏览器,访问相应站点-测试页面;

2、F12,切换到Console页面;

3、在console中输入以下代码;

javascript: (function () {
    function callback() {
        gremlins.createHorde({
            species: [gremlins.species.clicker(), gremlins.species.toucher(), gremlins.species.formFiller(), gremlins.species.scroller(), gremlins.species.typer()],
            mogwais: [gremlins.mogwais.alert(), gremlins.mogwais.fps(), gremlins.mogwais.gizmo()],
            strategies: [gremlins.strategies.distribution()]
        }).unleash();
    }
    var s = document.createElement("script");
    s.src = "https://unpkg.com/gremlins.js";;
    if (s.addEventListener) {
        s.addEventListener("load", callback, false);
    } else if (s.readyState) {
        s.onreadystatechange = callback;
    }
    document.body.appendChild(s);
})()

4、点击回车,页面就会开始Monkey测试;

Purpose

在开发HTML5应用程序时,您是否预料到不常见的用户交互?你成功地检测到并修补了所有内存泄漏吗?否则,应用程序迟早会中断。如果n个随机操作可以使应用程序失败,那么最好在测试期间确认它,而不是让用户发现它。

Gremlins.js模拟随机用户操作:小精灵单击窗口中的任意位置,以表单形式输入随机数据,或者将鼠标移到不需要的元素上。他们的目标是:触发JavaScript错误,或者使应用程序失败。恭喜你,小精灵不能破坏应用程序!这个应用程序足够健壮,可以发布给真正的用户。

这种做法,也称为Monkey测试或Fuzz测试,在移动应用程序开发中非常常见(例如,请参见Android Monkey程序)。既然前端(MV*,d3.js,Backbone.js,Angular.js,等等)和后端(Node.js)开发使用了持久的JavaScript应用程序,那么这种技术对于web应用程序就变得很有价值了。

Installation

此模块通过npm分发,npm与node捆绑在一起,应该作为项目的 dependencies之一进行安装:

npm i gremlins.js

这个库有 dependencieschance列表。

gremlins.js也可以作为bookmarklet提供。进入这个页面,抓住它,在任何一个网页上释放出一大群人。

Basic Usage

一个小精灵部落是一支由一群专门的小精灵组成的军队,随时准备搞乱你的应用程序。释放小精灵开始压力测试:

const horde = gremlins.createHorde();
horde.unleash();
// gremlins will act randomly, at 10 ms interval, 1000 times

gremlins.js提供了几种小精灵:一些在页面上的任何地方单击,其他人在表单输入中输入数据,其他人在每个可能的方向滚动窗口,等等。

您将在屏幕和控制台日志中看到gremlins操作的痕迹(它们留下红色痕迹):

gremlin formFiller input 5 in <input type="number" name="age">
gremlin formFiller input pzdoyzshh0k9@o8cpskdb73nmi.r7r in <input type="email" name="email">
gremlin clicker    click at 1219 301
gremlin scroller   scroll to 100 25
...

一个部落也有莫格威人,他们是无害的小精灵(或者,你可以说,小精灵是有害的莫格威人)。Mogwais只监视应用程序的活动并将其记录在记录器上。例如,“fps”mogwai每隔500毫秒监控每秒的帧数:

mogwai  fps  33.21
mogwai  fps  59.45
mogwai  fps  12.67
...

莫格威人还报告了当小精灵破坏了应用程序。例如,如果每秒帧数降至10以下,fps mogwai将记录一个错误:

mogwai  fps  12.67
mogwai  fps  23.56
err > mogwai  fps  7.54 < err
mogwai  fps  15.76
...

在10个错误之后,一个特殊的mogwai停止了测试。他被称为Gizmo,他防止小精灵破坏应用程序。毕竟,一旦gremlins发现了前10个错误,您就已经知道如何使应用程序更加健壮。

如果Gizmo没有停止,默认的部落在大约1分钟后停止。您可以增加gremlins动作的数量,使攻击持续更长时间:

horde.createHorde({
    strategies: [gremlins.strategies.allTogether({ nb: 10000 })],
});
horde.unleash();
// gremlins will attack at 10 ms interval, 10,000 times

与mogwais一样,Gremlins是简单的JavaScript函数。如果 gremlins.js没有提供可以破坏应用程序的gremlin,那么开发它非常容易:

// Create a new custom gremlin to blur an input randomly selected
function customGremlin({ logger, randomizer, window }) {
    // Code executed once at initialization
    logger.log('Input blur gremlin initialized');
    // Return a function that will be executed at each attack
    return function attack() {
        var inputs = document.querySelectorAll('input');
        var element = randomizer.pick(element);
        element.blur();
        window.alert('attack done');
    };
}

// Add it to your horde
horde.createHorde({
    species: [customGremlin],
});

gremlins.js中的所有内容都是可配置的;您将发现扩展和适应您的用例非常容易。

Advanced Usage

设置要在测试中使用的小精灵和大灰狼

默认情况下,所有的小妖精和莫格威人都会加入部落。

也可以使用自定义配置对象选择仅添加所需的小精灵物种:

gremlins
    .createHorde({
        species: [
            gremlins.species.formFiller(),
            gremlins.species.clicker({
                clickTypes: ['click'],
            }),
            gremlins.species.toucher(),
        ],
    })
    .unleash();

如果您只想在默认的gremlin之外添加自己的gremlin,请使用 allSpecies常量:

gremlins
    .createHorde({
        species: [...gremlins.allSpecies, customGremlin],
    })
    .unleash();

要添加所需的mogwai,请以相同的方式使用 mogwai配置和 allMogwais()常量。

gremlins.js目前提供了一些小精灵和怪物:

  • 单击Remerglin可在任何可见区域单击文档
  • toucherGremlin可触及文档可见区域的任何位置
  • formFillerGremlin通过输入数据、选择选项、单击复选框等方式填写表单
  • scrollerGremlin滚动视口以显示文档的另一部分
  • typerGremlin在键盘上键入键
  • alertMogwai阻止对alert()的调用阻止测试
  • fpsMogwai记录浏览器每秒的帧数(FPS)
  • 当小鬼们走得太远时,gizmoMogwai可以阻止他们

Configuring Gremlins

gremlins.js提供的所有gremlin和mogwai都是可配置的,也就是说,您可以通过注入自定义配置来改变它们的工作方式。

例如,clicker gremlin是一个将对象作为自定义配置的函数:

const customClicker = gremlins.species.clicker({
    // which mouse event types will be triggered
    clickTypes: ['click'],
    // Click only if parent is has class test-class
    canClick: (element) => element.parentElement.className === 'test-class',
    // by default, the clicker gremlin shows its action by a red circle
    // overriding showAction() with an empty function makes the gremlin action invisible
    showAction: (x, y) => {},
});
gremlins.createHorde({
    species: [customClicker],
});

每个特定的gremlin或mogwai都有自己的定制方法,请查看源代码以获取详细信息。

Seeding The Randomizer

如果希望攻击可重复,则需要为随机数生成器设定种子:

// seed the randomizer
horde.createHorde({
    randomizer: new gremlins.Chance(1234);
});

在攻击之前或之后执行代码

在开始攻击之前,您可能需要执行自定义代码。这对于:

  • 启动探查器
  • 禁用某些功能以更好地针对测试
  • Bootstrap应用程序

幸运的是,unleashHorde是一个承诺。因此,如果你想在释放前后执行代码,只需:

const horde = gremlins.createHorde();

console.profile('gremlins');
horde.unleash().then(() => {
    console.profileEnd();
});

制定战略

默认情况下,gremlins将以随机顺序、均匀分布、间隔10ms的延迟进行攻击,这种攻击策略称为分布策略。您可以使用strategies自定义对象对其进行自定义:

const distributionStrategy = gremlins.strategies.distribution({
    distribution: [0.3, 0.3, 0.3, 0.1], // the first three gremlins have more chances to be executed than the last
    delay: 50, // wait 50 ms between each action
});

注意,如果使用默认的gremlin,有五种类型的gremlin。上一个示例将给最后一个gremlin specie一个0值。

你也可以使用另一种策略。策略只是一个需要一个参数的函数:一个gremlin数组。另外两种策略捆绑在一起(allTogether和bySpecies),对于更复杂的攻击场景,实现定制策略应该相当容易。

Stopping The Attack

部落可以在紧急情况下使用 horde.stop()方法停止攻击Gizmo使用此方法来防止10个错误后对应用程序造成进一步损害,如果不想继续攻击,也可以使用它。

Customizing The Logger

默认情况下,gremlins.js将所有gremlin操作和mogwai观察记录在控制台中。如果您喜欢使用另一种日志记录方法(例如,将gremlins活动存储在LocalStorage中,并每10秒用Ajax发送一次),只需向 logger()方法提供一个包含4个方法(log、info、warn和error)的logger对象:

const customLogger = {
    log: function (msg) {
        /* .. */
    },
    info: function (msg) {
        /* .. */
    },
    warn: function (msg) {
        /* .. */
    },
    error: function (msg) {
        /* .. */
    },
};
horde.createHorde({ logger: customLogger });

Cypress

要在cypress测试中运行gremlins.js,您需要提供tested窗口:

import { createHorde } from 'gremlins.js';

describe('Run gremlins.js inside a cypress test', () => {
    let horde;
    beforeEach(() =>
        cy.window().then((testedWindow) => {
            horde = createHorde({ window: testedWindow });
        })
    );
    it('should run gremlins.js', () => {
        return cy.wrap(horde.unleash()).then(() => {
            /* ... */
        });
    });
});

License

gremlins.js是根据麻省理工学院的许可证授权的,由marmelab提供。

Github