Testers gonna test)

function(a, b) {
  return a + b >= a && a + b >= b;
}

Какие тесты бы вы написали?

Классы эквивалентности

function genPosNumber() {
  return Math.random() * 10000000000;
}

Генератор

function property(argGenerators, propertyFn) {
  return function() {
    var generatedArgs = argGenerators.map(gen => gen());

    return {
      success: propertyFn(...generatedArgs),
      args: generatedArgs
    };
  }
}

Генератор

function check(property, tries = 100) {
  for (var i = 0; i < tries; i++) {
    var res = property();
    if (!res.success) {
      throw new Error(
        'Property hasnt held on arguments: '
        + JSON.stringify(res.args, null, 2)
      );
    }
  }
}

Проверка

it('forall a, b - a + b >= a && a + b >= b', () => {
  check(property(
    [genPosNumber, genPosNumber],
    function (a, b) {
      return a + b >= a && a + b >= b;
    }
  ))
})

Тест

QuickCheck

var testcheck = require('testcheck');
var gen = testcheck.gen;

it('forall a, b - a + b >= a && a + b >= b', () => {
  testcheck.check(testcheck.property(
    [gen.posInt, gen.posInt],
    function (a, b) {
      return a + b >= a && a + b >= b;
    }
  ))
})

Тест

function convertTo(structForFrontend) {
  ...
  return structFromBackend;
}


function convertFrom(structFromBackend) {
  ...
  return structForFrontend;
}

Тест

function isRevertable(structFromBackend) {
  var structForFrontend = convertFrom(structFromBackend);
  var structForBackend = convertTo(structForFrontend);

  expect(structFromBackend).toEqual(structForBackend);
}

Тест

gen.int // генератор целых чисел
gen.array // генератор массивов
gen.array(gen.int) // генератор массивов целых чисел

Типы

Пользователь

  • type – может быть espoused, single, common_law_marriage, undefined;
  • members – массив объектов с такой структурой:
    • role – может быть sibling, child, parent, spouse;
    • fio – объект с ключами firstname, lastname, middlename;
    • dependant – boolean или undefined.
gen.returnOneOf(['espoused', 'single', 'common_law_marriage', undefined])
gen.returnOneOf(['sibling', 'child', 'parent', 'spouse'])
gen.oneOf([gen.boolean, gen.undefined])
gen.object({
    firstname: gen.oneOf([gen.string, gen.undefined]),
    lastname: gen.oneOf([gen.string, gen.undefined]),
    middlename: gen.oneOf([gen.string, gen.undefined])
})
var familyInfoGen = gen.object({
  type: gen.returnOneOf(['espoused', 'single', 'common_law_marriage', undefined]),
  members: gen.array(
    gen.object({
      role: gen.returnOneOf(['sibling', 'child', 'parent', 'spouse']),
      fio: gen.object({
        firstname: gen.oneOf([gen.string, gen.undefined]),
        lastname: gen.oneOf([gen.string, gen.undefined]),
        middlename: gen.oneOf([gen.string, gen.undefined])
      }),
      dependant: gen.oneOf([gen.boolean, gen.undefined])
    })
  )
});
var sample = require('testcheck').sample;

console.log(JSON.stringify(sample(familyInfoGen, {times: 2}), null, 2))
/*
[
  {
    "type": "espoused",
    "members": []
  },
  {
    "members": []
  }
]
*/
type === 'espoused'

members.length === 0

Женатый без жены

function mapFamily(familyObject) {
  // находим всех супруг
  var spouse = familyObject.members.filter(member => member.role === 'spouse');
  // если женат, а супруги нет
  if (familyObject.type === 'espoused' && spouse.length === 0) {
    return {
      type: familyObject.type,
      members: [
        // то добавляем ее
        { role: 'spouse', fio: {} },
        ...familyObject.members
      ]
    }
  // если не женат, а супруга есть
  } else if (familyObject.type !== 'espoused' && spouse.length !== 0) {
    return {
      type: familyObject.type,
      // убираем ее
      members: familyObject.members.filter(member => member.role !== 'spouse')
    }
  // если супруг больше одной, то оставляем только первую
  } else if (spouse.length > 1) {
    return {
      type: familyObject.type,
      members: familyObject.members.reduce((acc, member) => {
        if (member.role !== 'spouse' && acc.hasSpouse) {
          acc.members.push(member);
        } else if (member.role === 'spouse' && !acc.hasSpouse) {
          acc.members.push(member);
          acc.hasSpouse = true;
        }
        return acc;
      }, { members: [], hasSpouse: false }).members
    }
  }
  // если структура верна, то возвращаем, ничего не меняя
  return familyObject;
}
var familyInfoGenFixed = gen.map(mapFamily, familyInfoGen);
console.log(JSON.stringify(sample(familyInfoGenFixed, {times: 2}), null, 2))
/*
[
  {
    "type": "espoused",
    "members": [
      {
        "role": "spouse",
        "fio": {}
      }
    ]
  },
  {
    "type": "common_law_marriage",
    "members": [
      {
        "role": "child",
        "fio": {
          "firstname": "&",
          "lastname": "",
        }
      }
    ]
  }
]
*/

Testers gonna test)

By Vladimir

Testers gonna test)

  • 83