I wanted to ask if someone here does tests.
Do you use a Test framework like gtest, or just write a function that is called which calls all the functions to be tested?
Unit tests for engine code?
Moderator: Ras
-
- Posts: 1062
- Joined: Tue Apr 28, 2020 10:03 pm
- Full name: Daniel Infuehr
Unit tests for engine code?
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer
Daniel Inführ - Software Developer
-
- Posts: 28353
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Unit tests for engine code?
If I implement complex incremental updates, e.g. of an attack map, I start with writing a function that calculates it from scratch, and one to compare that with the incrementally updated one. Otherwise, in something as simple as an engine, I just test it by having it play games, and look for blunders in those. Sometimes I add some code to copy all variables that contain or depend on the game state, and to test those after each UnMake to make sure these are still the same.
-
- Posts: 3
- Joined: Tue Aug 30, 2022 9:35 pm
- Full name: Erik Fast
Re: Unit tests for engine code?
I do something like this:
Each test function can run one or more tests and return the number of failures. These will also use macros to output the line number when a test condition fails, for example:
I also like the idea of randomized testing or fuzzing because I think it covers a lot more cases than a couple of hand-picked tests can. I find it useful to write a function that plays several thousand games of random legal moves and feeds those positions into other tests.
Code: Select all
bool run_tests() {
int num_failures = 0;
num_failures += test_a();
num_failures += test_b();
num_failures += test_c();
// ...
if (num_failures)
printf("%d tests failed.\n", num_failures);
else
printf("All tests succeeded.\n");
return num_failures == 0;
}
int main(int argc, char **argv) {
if (!run_tests())
return 1;
// Main program.
// ...
return 0;
}
Code: Select all
#define TestAssert(x) if (!(x)) { printf("Test assertion failed (%s:%d):\n\n\t%s\n". __FILE__, __LINE__, #x); num_failures++; }
-
- Posts: 263
- Joined: Wed Jun 16, 2021 2:08 am
- Location: Berlin
- Full name: Jost Triller
Re: Unit tests for engine code?
I simply code everything correctly first try, this way I don't need to write any tests.
-
- Posts: 219
- Joined: Fri Apr 11, 2014 10:45 am
- Full name: Fabio Gobbato
Re: Unit tests for engine code?
I don't use a test framework but I have single functions for testing perft, hash move validation, see, tb probing code and polyglot book probe.
-
- Posts: 3233
- Joined: Wed Mar 10, 2010 10:18 pm
- Location: Hamburg, Germany
- Full name: Srdja Matovic
Re: Unit tests for engine code?
+1Fabio Gobbato wrote: ↑Sat Sep 17, 2022 10:41 am I don't use a test framework but I have single functions for testing perft, hash move validation, see, tb probing code and polyglot book probe.
I have a selftest function for perft and hashes, and write specific ones on demand.
--
Srdja
-
- Posts: 1062
- Joined: Tue Apr 28, 2020 10:03 pm
- Full name: Daniel Infuehr
Re: Unit tests for engine code?
All good ideas.
I also will add regression tests.
Just a big number of stored chess trees (multiple gb) and comparing the number of nodes until the correct PV is found.
Haven't solved the issue of generating trees (domain free) yet.
I would like to have trees of high testing quality like poisoned chess positions. Where moves look very good in the short term but turn out to be bad.
I also will add regression tests.
Just a big number of stored chess trees (multiple gb) and comparing the number of nodes until the correct PV is found.
Haven't solved the issue of generating trees (domain free) yet.
I would like to have trees of high testing quality like poisoned chess positions. Where moves look very good in the short term but turn out to be bad.
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer
Daniel Inführ - Software Developer
-
- Posts: 29
- Joined: Thu Jun 09, 2022 5:09 am
- Full name: Clayton Ramsey
Re: Unit tests for engine code?
I do both unit testing and run games while observing. In general, I usually write a unit test every time I catch a bug to ensure that I don't create one again.
-
- Posts: 28353
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Unit tests for engine code?
You did not like the method I gave you?dangi12012 wrote: ↑Sun Sep 18, 2022 5:15 pm Haven't solved the issue of generating trees (domain free) yet.
I would like to have trees of high testing quality like poisoned chess positions. Where moves look very good in the short term but turn out to be bad.
-
- Posts: 1062
- Joined: Tue Apr 28, 2020 10:03 pm
- Full name: Daniel Infuehr
Re: Unit tests for engine code?
Description:
In my words (Is this an apt description?)
Known PV with a score in the end. (single line with score 8)
Then add a cut move leading to leaves which are all better than the PV. (all leaves score 9 or above)
Then fill other nodes with random leaf evals.
Code:
I think for tests I would need to expand your code to store the actual tree in a typical Node* children, Node* parent structure. I think its a good scaffolding - except I dont understand how this can be used to generate a poisoned tree and also how adding random leaf nodes will keep the eval in tact.
Also the non leaf nodes dont have a score here so how could Alphabeta(depth -1) even return some value?
What would be needed is that Alphabeta(5) suggest strongly a move but Alphabeta(8) will prove that this was a big mistake.
Is this a poisoned position?
Code: Select all
For a given depth you can start with a PV, and assign it the score you want in the end leaf.
You can then built a refutation tree (of alternating cut-nodes and all nodes) by generating only a single move in the cut-nodes
(the cut-move), and assign all the leaves a score better
(for the side playing the cut-moves) than the PV score.
You can then go back to the cut-nodes, and generate trees from them
through their other moves with totally random leaf evaluation.
Known PV with a score in the end. (single line with score 8)
Then add a cut move leading to leaves which are all better than the PV. (all leaves score 9 or above)
Then fill other nodes with random leaf evals.
Code:
Code: Select all
Tree(depth, score, bound)
{
if(depth == 0) {
switch(bound) {
case EXACT: return score;
case UPPER: return score - 1;
case LOWER: return score + 1;
case ANY: return randomScore();
}
} else {
n = N; // desired number of children
switch(bound) {
case EXACT: // PV node
Tree(depth-1, -score, EXACT); n--; // one PV child
children = LOWER; // other moves are refuted, i.e. lead to cut-nodes
break;
case LOWER: // cut-node
Tree(dept-1, -score, UPPER); n--; // one cut-move
children = ANY; // the other children are irrelevant
break;
case UPPER: // all-node
children = LOWER; // all children are cut-nodes
break;
case ANY: // unspecified node type
children = ANY;
}
while(n-- > 0) {
Tree(depth-1, -score, children);
}
}
}
Also the non leaf nodes dont have a score here so how could Alphabeta(depth -1) even return some value?
What would be needed is that Alphabeta(5) suggest strongly a move but Alphabeta(8) will prove that this was a big mistake.
Is this a poisoned position?
Code: Select all
Tree(9, 8, EXACT)
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer
Daniel Inführ - Software Developer