Automatisation des tests des vraies règles

pull/138/head
mama 2017-12-18 20:56:23 +01:00
parent bb418839f6
commit 19c4bb3cfa
4 changed files with 82 additions and 38 deletions

View File

@ -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"
}

View File

@ -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>
)}

View File

@ -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 =>

34
test/real-rules.test.js Normal file
View File

@ -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}
`)
})
)
})
}))