diff --git a/package.json b/package.json index bfcc67984..c3f673500 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "test": "mocha-webpack --webpack-config source/webpack.test.config.js --require source-map-support/register --require test/helpers/browser.js \"test/**/*.test.js\"", "test-watch": "mocha-webpack --webpack-config source/webpack.test.config.js --require source-map-support/register --require test/helpers/browser.js \"test/**/*.test.js\" --watch", "test-meca": "mocha-webpack --webpack-config source/webpack.test.config.js --require source-map-support/register --require test/helpers/browser.js test/mecanisms.test.js --watch", + "test-rules": "mocha-webpack --webpack-config source/webpack.test.config.js --require source-map-support/register --require test/helpers/browser.js test/real-rules.test.js --watch", "heroku-postbuild": "npm install --dev && webpack --config source/webpack.config.js --progress", "test-inversions": "mocha-webpack --webpack-config source/webpack.test.config.js --require source-map-support/register --require test/helpers/browser.js \"test/inversion.test.js\" --watch" } diff --git a/source/components/rule/Examples.js b/source/components/rule/Examples.js index 223a817eb..a248861aa 100644 --- a/source/components/rule/Examples.js +++ b/source/components/rule/Examples.js @@ -1,52 +1,63 @@ import React, { Component } from 'react' -import R, {pick} from 'ramda' +import R, { pick } from 'ramda' import classNames from 'classnames' -import {connect} from 'react-redux' -import { - disambiguateExampleSituation, - collectDefaults -} from 'Engine/rules.js' +import { connect } from 'react-redux' +import { disambiguateExampleSituation, collectDefaults } from 'Engine/rules.js' import { analyse } from 'Engine/traverse' import './Examples.css' -import {assume} from '../../reducers' +import { assume } from '../../reducers' +import { expect } from 'chai' + +// By luck this works as expected for both null and undefined, * but with different branches failing :O * +export let isFloat = n => Number(n) === n && n % 1 !== 0 + +// les variables dans les tests peuvent être exprimées relativement à l'espace de nom de la règle, +// comme dans sa formule +export let runExamples = (examples, rule, parsedRules) => + examples + .map( + R.evolve({ situation: disambiguateExampleSituation(parsedRules, rule) }) + ) + .map(ex => { + let exampleSituationGate = () => name => ex.situation[name] + + let runExample = analyse(parsedRules, rule.name)( + assume(exampleSituationGate, collectDefaults(parsedRules))() + ), + exampleValue = runExample.targets[0].nodeValue, + goal = ex['valeur attendue'], + ok = + exampleValue === goal + ? true + : typeof goal === 'number' + ? Math.abs((exampleValue - goal) / goal) < 0.001 + : goal === null && exampleValue === 0 + + return { + ...ex, + ok, + rule: runExample.targets[0] + } + }) @connect(state => ({ situationGate: state.situationGate, parsedRules: state.parsedRules })) export default class Examples extends Component { - runExamples() { - let { rule, parsedRules } = this.props, - { exemples: examples = []} = rule - - // les variables dans les tests peuvent être exprimées relativement à l'espace de nom de la règle, - // comme dans sa formule - return examples.map(R.evolve({situation: disambiguateExampleSituation(parsedRules, rule)})).map(ex => { - - let exampleSituationGate = () => name => ex.situation[name] - - let runExample = analyse(parsedRules, rule.name)( - assume(exampleSituationGate, collectDefaults(parsedRules))() - ), - exampleValue = runExample.targets[0].nodeValue - - return { - ...ex, - ok: Math.abs(ex['valeur attendue'] - exampleValue) < 0.1, //TODO on peut sûrement faire mieux... - rule: runExample.targets[0] - } - }) - } - render() { - let examples = this.runExamples(), - focusedExample = R.path(['focusedExample', 'nom'])(this.props), - { inject, situationExists, showValues } = this.props + let focusedExample = R.path(['focusedExample', 'nom'])(this.props), + { inject, situationExists, showValues, rule, parsedRules } = this.props, + { exemples = [] } = rule, + examples = runExamples(exemples, rule, parsedRules) if (!examples.length) return null return (
@@ -78,7 +89,7 @@ export default class Examples extends Component { Ce test ne passe pas {showValues && ( - : le résultat attendu était {' '} + : le résultat attendu était{' '} {expected} )} diff --git a/test/mecanisms.test.js b/test/mecanisms.test.js index f718f90c3..7a704c487 100644 --- a/test/mecanisms.test.js +++ b/test/mecanisms.test.js @@ -10,9 +10,7 @@ import { analyse, parseAll } from "../source/engine/traverse" import { collectMissingVariables } from "../source/engine/generateQuestions" import testSuites from "./load-mecanism-tests" import R from "ramda" - -// By luck this works as expected for both null and undefined, * but with different branches failing :O * -let isFloat = n => Number(n) === n && n % 1 !== 0 +import {isFloat} from '../source/components/rule/Examples' describe("Mécanismes", () => testSuites.map(suite => diff --git a/test/real-rules.test.js b/test/real-rules.test.js new file mode 100644 index 000000000..b283e680d --- /dev/null +++ b/test/real-rules.test.js @@ -0,0 +1,34 @@ +/* + Les mécanismes sont testés dans mécanismes/ comme le sont les variables directement dans la base YAML. + On y créée dans chaque fichier une base YAML autonome, dans laquelle intervient le mécanisme à tester, + puis on teste idéalement tous ses comportements sans en faire intervenir d'autres. +*/ + +import { expect, AssertionError } from "chai" +import { enrichRule, rules } from "../source/engine/rules" +import { analyse, parseAll } from "../source/engine/traverse" +import { collectMissingVariables } from "../source/engine/generateQuestions" +import testSuites from "./load-mecanism-tests" +import R from "ramda" +import { runExamples, isFloat } from "../source/components/rule/Examples" + + +let parsedRules = parseAll(rules) + + +describe("Tests des règles de notre base de règles", () => + parsedRules.map(rule => { + if (!rule.exemples) return null + describe(rule.name, () => { + let examples = runExamples(rule.exemples, rule, parsedRules) + examples.map(example => + it(example.nom + "", () => { + if (!example.ok) + throw new AssertionError(` + Valeur attendue : ${example['valeur attendue']} + Valeur obtenue : ${example.rule.nodeValue} + `) + }) + ) + }) + }))