✅ Automatisation des tests des vraies règles
parent
bb418839f6
commit
19c4bb3cfa
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
<div id="examples">
|
||||
<h2>Exemples de calcul <small>Cliquez sur un exemple pour le tester</small></h2>
|
||||
<h2>
|
||||
Exemples de calcul{' '}
|
||||
<small>Cliquez sur un exemple pour le tester</small>
|
||||
</h2>
|
||||
{R.isEmpty(examples) ? (
|
||||
<p>
|
||||
<i className="fa fa-exclamation-triangle" aria-hidden="true" />
|
||||
|
@ -78,7 +89,7 @@ export default class Examples extends Component {
|
|||
Ce test ne passe pas
|
||||
{showValues && (
|
||||
<span>
|
||||
: le résultat attendu était {' '}
|
||||
: le résultat attendu était{' '}
|
||||
<span className="expected">{expected}</span>
|
||||
</span>
|
||||
)}
|
||||
|
|
|
@ -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 =>
|
||||
|
|
|
@ -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}
|
||||
`)
|
||||
})
|
||||
)
|
||||
})
|
||||
}))
|
Loading…
Reference in New Issue