Add RunningStat class, tests
[lhc/web/wiklou.git] / tests / phpunit / includes / RunningStatTest.php
1 <?php
2 /**
3 * PHP Unit tests for RunningStat class.
4 * @covers RunningStat
5 */
6 class RunningStatTest extends MediaWikiTestCase {
7
8 public $points = array(
9 49.7168, 74.3804, 7.0115, 96.5769, 34.9458,
10 36.9947, 33.8926, 89.0774, 23.7745, 73.5154,
11 86.1322, 53.2124, 16.2046, 73.5130, 10.4209,
12 42.7299, 49.3330, 47.0215, 34.9950, 18.2914,
13 );
14
15 /**
16 * Verify that the statistical moments and extrema computed by RunningStat
17 * match expected values.
18 * @covers RunningStat::push
19 * @covers RunningStat::count
20 * @covers RunningStat::getMean
21 * @covers RunningStat::getVariance
22 * @covers RunningStat::getStdDev
23 */
24 public function testRunningStatAccuracy() {
25 $rstat = new RunningStat();
26 foreach( $this->points as $point ) {
27 $rstat->push( $point );
28 }
29
30 $mean = array_sum( $this->points ) / count( $this->points );
31 $variance = array_sum( array_map( function ( $x ) use ( $mean ) {
32 return pow( $mean - $x, 2 );
33 }, $this->points ) ) / ( count( $rstat ) - 1 );
34 $stddev = sqrt( $variance );
35 $min = min( $this->points );
36 $max = max( $this->points );
37
38 $this->assertEquals( count( $rstat ), count( $this->points ) );
39 $this->assertEquals( $rstat->min, min( $this->points ) );
40 $this->assertEquals( $rstat->max, max( $this->points ) );
41 $this->assertEquals( $rstat->getMean(), $mean );
42 $this->assertEquals( $rstat->getVariance(), $variance );
43 $this->assertEquals( $rstat->getStdDev(), $stddev );
44 }
45
46 /**
47 * When one RunningStat instance is merged into another, the state of the
48 * target RunningInstance should have the state that it would have had if
49 * all the data had been accumulated by it alone.
50 * @covers RunningStat::merge
51 * @covers RunningStat::count
52 */
53 public function testRunningStatMerge() {
54 $expected = new RunningStat();
55
56 foreach( $this->points as $point ) {
57 $expected->push( $point );
58 }
59
60 // Split the data into two sets
61 $sets = array_chunk( $this->points, floor( count( $this->points ) / 2 ) );
62
63 // Accumulate the first half into one RunningStat object
64 $first = new RunningStat();
65 foreach( $sets[0] as $point ) {
66 $first->push( $point );
67 }
68
69 // Accumulate the second half into another RunningStat object
70 $second = new RunningStat();
71 foreach( $sets[1] as $point ) {
72 $second->push( $point );
73 }
74
75 // Merge the second RunningStat object into the first
76 $first->merge( $second );
77
78 $this->assertEquals( count( $first ), count( $this->points ) );
79 $this->assertEquals( $first, $expected );
80 }
81 }