From 496852b9885640b44b46bb63c7b09c3fb4df13b3 Mon Sep 17 00:00:00 2001
From: Tomas Pecka <peckato1@fit.cvut.cz>
Date: Sun, 24 Feb 2019 13:10:13 +0100
Subject: [PATCH] Unit tests: CPPUNIT -> Catch2: algo

---
 .../automaton/convert/FTAtoPDATest.cpp        | 130 +++---
 .../test-src/automaton/convert/FTAtoPDATest.h |  21 -
 .../automaton/determinize/determinizeTest.cpp | 192 ++++-----
 .../automaton/determinize/determinizeTest.h   |  25 --
 .../properties/EpsilonClosureTest.cpp         |  69 ++-
 .../automaton/properties/EpsilonClosureTest.h |  19 -
 .../simplify/FSMSingleInitialStateTest.cpp    |  83 ++--
 .../simplify/FSMSingleInitialStateTest.h      |  19 -
 .../automaton/simplify/FSMTotalTest.cpp       |  57 ++-
 .../automaton/simplify/FSMTotalTest.h         |  19 -
 .../simplify/minimizeBrzozowskiTest.cpp       |  46 +-
 .../simplify/minimizeBrzozowskiTest.h         |  19 -
 .../automaton/simplify/minimizeTest.cpp       | 302 +++++++------
 .../automaton/simplify/minimizeTest.h         |  20 -
 .../automaton/simplify/normalizeTest.cpp      |  61 ++-
 .../automaton/simplify/normalizeTest.h        |  19 -
 .../test-src/automaton/simplify/trimTest.cpp  | 167 +++-----
 .../test-src/automaton/simplify/trimTest.h    |  22 -
 .../transform/AutomataCompactionTest.cpp      | 223 +++++-----
 .../transform/AutomataCompactionTest.h        |  23 -
 .../transform/AutomataConcatenationTest.cpp   | 129 +++---
 .../transform/AutomataConcatenationTest.h     |  19 -
 .../automaton/transform/AutomataUnionTest.cpp |  25 +-
 .../automaton/transform/AutomataUnionTest.h   |  19 -
 .../transform/AutomatonIterationTest.cpp      |  95 ++---
 .../transform/AutomatonIterationTest.h        |  19 -
 .../grammar/convert/GrammarCFGtoPDATest.cpp   |  25 +-
 .../grammar/convert/GrammarCFGtoPDATest.h     |  21 -
 .../test-src/grammar/convert/rg2rgTest.cpp    |  69 +++
 .../generate/GrammarGenerateUpToLength.cpp    | 354 ++++++++--------
 .../generate/GrammarGenerateUpToLength.h      |  23 -
 .../properties/GrammarPropertiesTest.cpp      | 258 ++++++------
 .../properties/GrammarPropertiesTest.h        |  23 -
 .../simplify/GrammarEpsilonRemoverTest.cpp    | 247 ++++++-----
 .../simplify/GrammarEpsilonRemoverTest.h      |  23 -
 .../GrammarLeftRecursionRemoverTest.cpp       | 383 ++++++++---------
 .../GrammarLeftRecursionRemoverTest.h         |  27 --
 .../GrammarSimpleRulesRemoverTest.cpp         | 239 +++++------
 .../simplify/GrammarSimpleRulesRemoverTest.h  |  23 -
 .../grammar/simplify/GrammarToCNFTest.cpp     | 172 ++++----
 .../grammar/simplify/GrammarToCNFTest.h       |  21 -
 .../grammar/simplify/GrammarToGNFTest.cpp     | 307 +++++++-------
 .../grammar/simplify/GrammarToGNFTest.h       |  25 --
 .../test-src/grammar/simplify/TrimTest.cpp    |  34 ++
 .../test-src/grammar/toGrammar/rg2rgTest.cpp  |  78 ----
 .../test-src/grammar/toGrammar/rg2rgTest.h    |  21 -
 alib2algo/test-src/main.cpp                   | 168 +-------
 alib2algo/test-src/playTest.cpp               |  89 ----
 alib2algo/test-src/playTest.h                 |  30 --
 alib2algo/test-src/regexp/RegExpTest.cpp      | 124 ------
 alib2algo/test-src/regexp/RegExpTest.h        |  23 -
 .../regexp/convert/ToAutomatonTest.cpp        |  81 ++++
 .../test-src/regexp/glushkov/GlushkovTest.cpp | 117 ++++++
 .../regexp/properties/RegExpEmptyTest.cpp     |  32 --
 .../regexp/properties/RegExpEmptyTest.h       |  21 -
 .../regexp/properties/RegExpEpsilonTest.cpp   |  60 ---
 .../regexp/properties/RegExpEpsilonTest.h     |  21 -
 .../properties/RegExpPropertiesTest.cpp       |  69 +++
 .../regexp/simplify/RegExpOptimizeTest.cpp    | 397 ++++++------------
 .../regexp/simplify/RegExpOptimizeTest.h      |  21 -
 .../test-src/regexp/toAutomaton/re2faTest.cpp |  93 ----
 .../test-src/regexp/toAutomaton/re2faTest.h   |  23 -
 .../transform/RegExpConcatenateTest.cpp       |  66 +--
 .../regexp/transform/RegExpConcatenateTest.h  |  21 -
 .../regexp/transform/RegExpDerivationTest.cpp |  56 ++-
 .../regexp/transform/RegExpDerivationTest.h   |  23 -
 .../regexp/transform/RegExpIntegralTest.cpp   |  34 +-
 .../regexp/transform/RegExpIntegralTest.h     |  23 -
 .../test-src/string/compare/compareTest.cpp   |  92 ++--
 .../test-src/string/compare/compareTest.h     |  23 -
 .../string/properties/borderArrayTest.cpp     |  23 +-
 .../string/properties/borderArrayTest.h       |  19 -
 .../compression/ArithmeticCompressionTest.cpp |  31 +-
 .../compression/ArithmeticCompressionTest.h   |  19 -
 .../stringology/compression/LZ77Test.cpp      | 118 ++----
 .../stringology/compression/LZ77Test.h        |  27 --
 .../stringology/exact/stringMatchTest.cpp     |  23 +-
 .../stringology/exact/stringMatchTest.h       |  19 -
 .../indexing/ExactSuffixAutomatonTest.cpp     |  62 ++-
 .../indexing/ExactSuffixAutomatonTest.h       |  19 -
 .../indexing/FactorOracleAutomatonTest.cpp    |  59 ++-
 .../indexing/FactorOracleAutomatonTest.h      |  18 -
 ...ckwardNondeterministicDAWGMatchingTest.cpp |  78 ++--
 ...BackwardNondeterministicDAWGMatchingTest.h |  18 -
 ...alizedLevenshteinMatchingAutomatonTest.cpp | 266 ++++++------
 ...eralizedLevenshteinMatchingAutomatonTest.h |  19 -
 ...venshteinSequenceMatchingAutomatonTest.cpp | 332 +++++++--------
 ...LevenshteinSequenceMatchingAutomatonTest.h |  19 -
 .../matching/HammingMatchingAutomatonTest.cpp | 165 ++++----
 .../matching/HammingMatchingAutomatonTest.h   |  19 -
 .../HammingSequenceMatchingAutomatonTest.cpp  | 204 +++++----
 .../HammingSequenceMatchingAutomatonTest.h    |  19 -
 .../LevenshteinMatchingAutomatonTest.cpp      | 226 +++++-----
 .../LevenshteinMatchingAutomatonTest.h        |  19 -
 ...venshteinSequenceMatchingAutomatonTest.cpp | 259 ++++++------
 ...LevenshteinSequenceMatchingAutomatonTest.h |  19 -
 .../SequenceMatchingAutomatonTest.cpp         |  58 ++-
 .../matching/SequenceMatchingAutomatonTest.h  |  17 -
 .../stringology/query/DAWGMatcherTest.cpp     |  80 ++--
 .../stringology/query/DAWGMatcherTest.h       |  19 -
 .../stringology/query/OracleMatcherTest.cpp   |  77 ++--
 .../stringology/query/OracleMatcherTest.h     |  19 -
 .../simulations/ExactBitParalelismTest.cpp    |  21 +-
 .../simulations/ExactBitParalelismTest.h      |  17 -
 ...eneralizedLevenshteinBitParalelismTest.cpp |  23 +-
 .../GeneralizedLevenshteinBitParalelismTest.h |  17 -
 ...lizedLevenshteinDynamicProgrammingTest.cpp |  61 ++-
 ...ralizedLevenshteinDynamicProgrammingTest.h |  19 -
 .../simulations/HammingBitParalelismTest.cpp  |  23 +-
 .../simulations/HammingBitParalelismTest.h    |  17 -
 .../HammingDynamicProgrammingTest.cpp         |  62 ++-
 .../HammingDynamicProgrammingTest.h           |  19 -
 .../LevenshteinBitParalelismTest.cpp          |  23 +-
 .../LevenshteinBitParalelismTest.h            |  17 -
 .../LevenshteinDynamicProgrammingTest.cpp     |  60 ++-
 .../LevenshteinDynamicProgrammingTest.h       |  19 -
 116 files changed, 3338 insertions(+), 5351 deletions(-)
 delete mode 100644 alib2algo/test-src/automaton/convert/FTAtoPDATest.h
 delete mode 100644 alib2algo/test-src/automaton/determinize/determinizeTest.h
 delete mode 100644 alib2algo/test-src/automaton/properties/EpsilonClosureTest.h
 delete mode 100644 alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.h
 delete mode 100644 alib2algo/test-src/automaton/simplify/FSMTotalTest.h
 delete mode 100644 alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.h
 delete mode 100644 alib2algo/test-src/automaton/simplify/minimizeTest.h
 delete mode 100644 alib2algo/test-src/automaton/simplify/normalizeTest.h
 delete mode 100644 alib2algo/test-src/automaton/simplify/trimTest.h
 delete mode 100644 alib2algo/test-src/automaton/transform/AutomataCompactionTest.h
 delete mode 100644 alib2algo/test-src/automaton/transform/AutomataConcatenationTest.h
 delete mode 100644 alib2algo/test-src/automaton/transform/AutomataUnionTest.h
 delete mode 100644 alib2algo/test-src/automaton/transform/AutomatonIterationTest.h
 delete mode 100644 alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.h
 create mode 100644 alib2algo/test-src/grammar/convert/rg2rgTest.cpp
 delete mode 100644 alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.h
 delete mode 100644 alib2algo/test-src/grammar/properties/GrammarPropertiesTest.h
 delete mode 100644 alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.h
 delete mode 100644 alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.h
 delete mode 100644 alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.h
 delete mode 100644 alib2algo/test-src/grammar/simplify/GrammarToCNFTest.h
 delete mode 100644 alib2algo/test-src/grammar/simplify/GrammarToGNFTest.h
 create mode 100644 alib2algo/test-src/grammar/simplify/TrimTest.cpp
 delete mode 100644 alib2algo/test-src/grammar/toGrammar/rg2rgTest.cpp
 delete mode 100644 alib2algo/test-src/grammar/toGrammar/rg2rgTest.h
 delete mode 100644 alib2algo/test-src/playTest.cpp
 delete mode 100644 alib2algo/test-src/playTest.h
 delete mode 100644 alib2algo/test-src/regexp/RegExpTest.cpp
 delete mode 100644 alib2algo/test-src/regexp/RegExpTest.h
 create mode 100644 alib2algo/test-src/regexp/convert/ToAutomatonTest.cpp
 create mode 100644 alib2algo/test-src/regexp/glushkov/GlushkovTest.cpp
 delete mode 100644 alib2algo/test-src/regexp/properties/RegExpEmptyTest.cpp
 delete mode 100644 alib2algo/test-src/regexp/properties/RegExpEmptyTest.h
 delete mode 100644 alib2algo/test-src/regexp/properties/RegExpEpsilonTest.cpp
 delete mode 100644 alib2algo/test-src/regexp/properties/RegExpEpsilonTest.h
 create mode 100644 alib2algo/test-src/regexp/properties/RegExpPropertiesTest.cpp
 delete mode 100644 alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.h
 delete mode 100644 alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp
 delete mode 100644 alib2algo/test-src/regexp/toAutomaton/re2faTest.h
 delete mode 100644 alib2algo/test-src/regexp/transform/RegExpConcatenateTest.h
 delete mode 100644 alib2algo/test-src/regexp/transform/RegExpDerivationTest.h
 delete mode 100644 alib2algo/test-src/regexp/transform/RegExpIntegralTest.h
 delete mode 100644 alib2algo/test-src/string/compare/compareTest.h
 delete mode 100644 alib2algo/test-src/string/properties/borderArrayTest.h
 delete mode 100644 alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.h
 delete mode 100644 alib2algo/test-src/stringology/compression/LZ77Test.h
 delete mode 100644 alib2algo/test-src/stringology/exact/stringMatchTest.h
 delete mode 100644 alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.h
 delete mode 100644 alib2algo/test-src/stringology/query/DAWGMatcherTest.h
 delete mode 100644 alib2algo/test-src/stringology/query/OracleMatcherTest.h
 delete mode 100644 alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.h
 delete mode 100644 alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.h
 delete mode 100644 alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.h
 delete mode 100644 alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.h
 delete mode 100644 alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.h
 delete mode 100644 alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.h
 delete mode 100644 alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.h

diff --git a/alib2algo/test-src/automaton/convert/FTAtoPDATest.cpp b/alib2algo/test-src/automaton/convert/FTAtoPDATest.cpp
index a576e80e52..5e8ca0332f 100644
--- a/alib2algo/test-src/automaton/convert/FTAtoPDATest.cpp
+++ b/alib2algo/test-src/automaton/convert/FTAtoPDATest.cpp
@@ -1,4 +1,4 @@
-#include "FTAtoPDATest.h"
+#include <catch2/catch.hpp>
 
 #include <alphabet/BottomOfTheStackSymbol.h>
 #include <automaton/TA/DFTA.h>
@@ -9,75 +9,73 @@
 #include <automaton/PDA/NPDA.h>
 #include <automaton/xml/PDA/NPDA.h>
 
-#include "automaton/convert/ToPostfixPushdownAutomaton.h"
+#include <automaton/convert/ToPostfixPushdownAutomaton.h>
 
 #include <factory/XmlDataFactory.hpp>
 
 #include <label/InitialStateLabel.h>
 #include <label/FinalStateLabel.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FTAtoPDATest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( FTAtoPDATest );
-
-void FTAtoPDATest::setUp() {
-}
-
-void FTAtoPDATest::tearDown() {
-}
-
-void FTAtoPDATest::testDFTAtoDPDA() {
-	automaton::DFTA < > automaton;
-
-	const common::ranked_symbol < > a (DefaultSymbolType('a'), DefaultRankType(2));
-	const common::ranked_symbol < > b (DefaultSymbolType('b'), DefaultRankType(1));
-	const common::ranked_symbol < > c (DefaultSymbolType('c'), DefaultRankType(0));
-	const ext::set<common::ranked_symbol < > > alphabet {a, b, c};
-	automaton.setInputAlphabet(alphabet);
-
-	automaton.addState(DefaultStateType(1));
-	automaton.addState(DefaultStateType(2));
-	automaton.addState(DefaultStateType(3));
-
-	ext::vector<DefaultStateType> a1States = {DefaultStateType(1), DefaultStateType(3)};
-	automaton.addTransition(a, a1States, DefaultStateType(1));
-	ext::vector<DefaultStateType> a2States = {DefaultStateType(3), DefaultStateType(3)};
-	automaton.addTransition(a, a2States, DefaultStateType(2));
-	ext::vector<DefaultStateType> bStates = {DefaultStateType(2)};
-	automaton.addTransition(b, bStates, DefaultStateType(1));
-	ext::vector<DefaultStateType> cStates;
-	automaton.addTransition(c, cStates, DefaultStateType(3));
-
-	automaton.addFinalState(DefaultStateType(3));
-
-	automaton::DPDA < > res = automaton::convert::ToPostfixPushdownAutomaton::convert(automaton);
-	factory::XmlDataFactory::toStdout(res);
-}
-
-void FTAtoPDATest::testNFTAtoNPDA() {
-	automaton::NFTA < > automaton;
-
-	const common::ranked_symbol < > a (DefaultSymbolType('a'), DefaultRankType(2));
-	const common::ranked_symbol < > b (DefaultSymbolType('b'), DefaultRankType(1));
-	const common::ranked_symbol < > c (DefaultSymbolType('c'), DefaultRankType(0));
-	const ext::set<common::ranked_symbol < > > alphabet {a, b, c};
-	automaton.setInputAlphabet(alphabet);
-
-	automaton.addState(DefaultStateType(1));
-	automaton.addState(DefaultStateType(2));
-	automaton.addState(DefaultStateType(3));
-
-	ext::vector<DefaultStateType> a1States = {DefaultStateType(1), DefaultStateType(3)};
-	automaton.addTransition(a, a1States, DefaultStateType(1));
-	automaton.addTransition(a, a1States, DefaultStateType(3));
-	ext::vector<DefaultStateType> a2States = {DefaultStateType(3), DefaultStateType(3)};
-	automaton.addTransition(a, a2States, DefaultStateType(2));
-	ext::vector<DefaultStateType> bStates = {DefaultStateType(2)};
-	automaton.addTransition(b, bStates, DefaultStateType(1));
-	ext::vector<DefaultStateType> cStates;
-	automaton.addTransition(c, cStates, DefaultStateType(3));
-
-	automaton.addFinalState(DefaultStateType(3));
-
-	automaton::NPDA < > res = automaton::convert::ToPostfixPushdownAutomaton::convert(automaton);
-	factory::XmlDataFactory::toStdout(res);
+TEST_CASE ( "FTAtoPDA", "[unit][algo][automaton][convert]" ) {
+	SECTION ( "Test DFTA to DPDA" ) {
+		automaton::DFTA < > automaton;
+
+		const common::ranked_symbol < > a (DefaultSymbolType('a'), DefaultRankType(2));
+		const common::ranked_symbol < > b (DefaultSymbolType('b'), DefaultRankType(1));
+		const common::ranked_symbol < > c (DefaultSymbolType('c'), DefaultRankType(0));
+		const ext::set<common::ranked_symbol < > > alphabet {a, b, c};
+		automaton.setInputAlphabet(alphabet);
+
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+
+		ext::vector<DefaultStateType> a1States = {DefaultStateType(1), DefaultStateType(3)};
+		automaton.addTransition(a, a1States, DefaultStateType(1));
+		ext::vector<DefaultStateType> a2States = {DefaultStateType(3), DefaultStateType(3)};
+		automaton.addTransition(a, a2States, DefaultStateType(2));
+		ext::vector<DefaultStateType> bStates = {DefaultStateType(2)};
+		automaton.addTransition(b, bStates, DefaultStateType(1));
+		ext::vector<DefaultStateType> cStates;
+		automaton.addTransition(c, cStates, DefaultStateType(3));
+
+		automaton.addFinalState(DefaultStateType(3));
+
+		automaton::DPDA < > res = automaton::convert::ToPostfixPushdownAutomaton::convert(automaton);
+		CHECK(res.getStates().size() == 2);
+		CHECK(res.getTransitions().size() == 5);
+		CHECK(res.getFinalStates().size() == 1);
+	}
+
+	SECTION ( "Test NFTA to NPDA" ) {
+		automaton::NFTA < > automaton;
+
+		const common::ranked_symbol < > a (DefaultSymbolType('a'), DefaultRankType(2));
+		const common::ranked_symbol < > b (DefaultSymbolType('b'), DefaultRankType(1));
+		const common::ranked_symbol < > c (DefaultSymbolType('c'), DefaultRankType(0));
+		const ext::set<common::ranked_symbol < > > alphabet {a, b, c};
+		automaton.setInputAlphabet(alphabet);
+
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+
+		ext::vector<DefaultStateType> a1States = {DefaultStateType(1), DefaultStateType(3)};
+		automaton.addTransition(a, a1States, DefaultStateType(1));
+		automaton.addTransition(a, a1States, DefaultStateType(3));
+		ext::vector<DefaultStateType> a2States = {DefaultStateType(3), DefaultStateType(3)};
+		automaton.addTransition(a, a2States, DefaultStateType(2));
+		ext::vector<DefaultStateType> bStates = {DefaultStateType(2)};
+		automaton.addTransition(b, bStates, DefaultStateType(1));
+		ext::vector<DefaultStateType> cStates;
+		automaton.addTransition(c, cStates, DefaultStateType(3));
+
+		automaton.addFinalState(DefaultStateType(3));
+
+		automaton::NPDA < > res = automaton::convert::ToPostfixPushdownAutomaton::convert(automaton);
+
+		CHECK(res.getStates().size() == 2);
+		CHECK(res.getTransitions().size() == 5);
+		CHECK(res.getFinalStates().size() == 1);
+	}
 }
diff --git a/alib2algo/test-src/automaton/convert/FTAtoPDATest.h b/alib2algo/test-src/automaton/convert/FTAtoPDATest.h
deleted file mode 100644
index 8a09fd668c..0000000000
--- a/alib2algo/test-src/automaton/convert/FTAtoPDATest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef FTA_TO_PDA_TEST_H_
-#define FTA_TO_PDA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class FTAtoPDATest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( FTAtoPDATest );
-  CPPUNIT_TEST( testDFTAtoDPDA );
-  CPPUNIT_TEST( testNFTAtoNPDA );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testDFTAtoDPDA();
-  void testNFTAtoNPDA();
-};
-
-#endif /* FTA_TO_PDA_TEST_H_ */
diff --git a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
index 169f695eec..5ce25695d9 100644
--- a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
+++ b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
@@ -1,139 +1,141 @@
+#include <catch2/catch.hpp>
 #include <alib/list>
-#include "determinizeTest.h"
 
 #include <automaton/FSM/NFA.h>
 #include <automaton/TA/NFTA.h>
 #include <automaton/PDA/InputDrivenNPDA.h>
 #include <automaton/PDA/InputDrivenDPDA.h>
 #include <automaton/PDA/VisiblyPushdownNPDA.h>
+#include <automaton/PDA/VisiblyPushdownDPDA.h>
 #include <alphabet/BottomOfTheStackSymbol.h>
 
-#include "automaton/determinize/Determinize.h"
+#include <automaton/determinize/Determinize.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( determinizeTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( determinizeTest );
+TEST_CASE ( "Determinize", "[unit][algo][automaton][determinize]" ) {
+	SECTION ( "NFA" ) {
+		automaton::NFA < > automaton(DefaultStateType(1));
 
-void determinizeTest::setUp() {
-}
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+		automaton.addInputSymbol(DefaultSymbolType("a"));
+		automaton.addInputSymbol(DefaultSymbolType("b"));
 
-void determinizeTest::tearDown() {
-}
+		automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
+		automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
 
-void determinizeTest::testDeterminizeNFA() {
-  automaton::NFA < > automaton(DefaultStateType(1));
+		automaton.addFinalState(DefaultStateType(3));
 
-  automaton.addState(DefaultStateType(1));
-  automaton.addState(DefaultStateType(2));
-  automaton.addState(DefaultStateType(3));
-  automaton.addInputSymbol(DefaultSymbolType("a"));
-  automaton.addInputSymbol(DefaultSymbolType("b"));
+		automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > determinized = automaton::determinize::Determinize::determinize(automaton);
 
-  automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
-  automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
+		CHECK(determinized.getStates().size() == 3);
 
-  automaton.addFinalState(DefaultStateType(3));
+	}
 
-  automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > determinized = automaton::determinize::Determinize::determinize(automaton);
+	SECTION ( "IDPDA" ) {
+		automaton::InputDrivenNPDA < > automaton(DefaultStateType(1), DefaultSymbolType('S'));
 
-  CPPUNIT_ASSERT(determinized.getStates().size() == 3);
+		automaton.addInputSymbol(DefaultSymbolType("a"));
+		automaton.addInputSymbol(DefaultSymbolType("b"));
 
-}
+		automaton.setPushdownStoreOperation(DefaultSymbolType("a"), ext::vector<DefaultSymbolType>{}, ext::vector<DefaultSymbolType> {});
+		automaton.setPushdownStoreOperation(DefaultSymbolType("b"), ext::vector<DefaultSymbolType>{}, ext::vector<DefaultSymbolType> {});
 
-void determinizeTest::testDeterminizeIDPDA() {
-  automaton::InputDrivenNPDA < > automaton(DefaultStateType(1), DefaultSymbolType('S'));
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+		automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
+		automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
 
-  automaton.addInputSymbol(DefaultSymbolType("a"));
-  automaton.addInputSymbol(DefaultSymbolType("b"));
+		automaton.addFinalState(DefaultStateType(3));
 
-  automaton.setPushdownStoreOperation(DefaultSymbolType("a"), ext::vector<DefaultSymbolType>{}, ext::vector<DefaultSymbolType> {});
-  automaton.setPushdownStoreOperation(DefaultSymbolType("b"), ext::vector<DefaultSymbolType>{}, ext::vector<DefaultSymbolType> {});
+		automaton::InputDrivenDPDA < DefaultSymbolType, DefaultSymbolType, ext::set < DefaultStateType > > determinized = automaton::determinize::Determinize::determinize(automaton);
 
-  automaton.addState(DefaultStateType(1));
-  automaton.addState(DefaultStateType(2));
-  automaton.addState(DefaultStateType(3));
-  automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
-  automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
+		CHECK(determinized.getStates().size() == 3);
+	}
 
-  automaton.addFinalState(DefaultStateType(3));
+	SECTION ( "VPA" ) {
+		automaton::VisiblyPushdownNPDA < > automaton(DefaultSymbolType(alphabet::BottomOfTheStackSymbol {}));
 
-  automaton::InputDrivenDPDA < DefaultSymbolType, DefaultSymbolType, ext::set < DefaultStateType > > determinized = automaton::determinize::Determinize::determinize(automaton);
+		automaton.addCallInputSymbol(DefaultSymbolType('a'));
+		automaton.addReturnInputSymbol(DefaultSymbolType('^'));
 
-  CPPUNIT_ASSERT(determinized.getStates().size() == 3);
-}
+		automaton.addPushdownStoreSymbol(DefaultSymbolType('A'));
+		automaton.addPushdownStoreSymbol(DefaultSymbolType('B'));
+		automaton.addPushdownStoreSymbol(DefaultSymbolType('C'));
+		automaton.addPushdownStoreSymbol(DefaultSymbolType('D'));
+		automaton.addPushdownStoreSymbol(DefaultSymbolType('E'));
+		automaton.addPushdownStoreSymbol(DefaultSymbolType('F'));
+		automaton.addPushdownStoreSymbol(DefaultSymbolType('T'));
 
-void determinizeTest::testDeterminizeVPA() {
-  automaton::VisiblyPushdownNPDA < > automaton(DefaultSymbolType(alphabet::BottomOfTheStackSymbol {}));
+		automaton.addState(DefaultStateType(0));
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+		automaton.addState(DefaultStateType(4));
+		automaton.addState(DefaultStateType(5));
+		automaton.addState(DefaultStateType(6));
 
-  automaton.addCallInputSymbol(DefaultSymbolType('a'));
-  automaton.addReturnInputSymbol(DefaultSymbolType('^'));
 
-  automaton.addPushdownStoreSymbol(DefaultSymbolType('A'));
-  automaton.addPushdownStoreSymbol(DefaultSymbolType('B'));
-  automaton.addPushdownStoreSymbol(DefaultSymbolType('C'));
-  automaton.addPushdownStoreSymbol(DefaultSymbolType('D'));
-  automaton.addPushdownStoreSymbol(DefaultSymbolType('E'));
-  automaton.addPushdownStoreSymbol(DefaultSymbolType('F'));
-  automaton.addPushdownStoreSymbol(DefaultSymbolType('T'));
+		automaton.addCallTransition(DefaultStateType(0), DefaultSymbolType('a'), DefaultStateType(0), DefaultSymbolType('A'));
+		automaton.addReturnTransition(DefaultStateType(0), DefaultSymbolType('^'), DefaultSymbolType('A'), DefaultStateType(0));
 
-  automaton.addState(DefaultStateType(0));
-  automaton.addState(DefaultStateType(1));
-  automaton.addState(DefaultStateType(2));
-  automaton.addState(DefaultStateType(3));
-  automaton.addState(DefaultStateType(4));
-  automaton.addState(DefaultStateType(5));
-  automaton.addState(DefaultStateType(6));
+		automaton.addCallTransition(DefaultStateType(0), DefaultSymbolType('a'), DefaultStateType(1), DefaultSymbolType('B'));
 
+		automaton.addCallTransition(DefaultStateType(1), DefaultSymbolType('a'), DefaultStateType(2), DefaultSymbolType('C'));
+		automaton.addCallTransition(DefaultStateType(2), DefaultSymbolType('a'), DefaultStateType(2), DefaultSymbolType('D'));
+		automaton.addReturnTransition(DefaultStateType(2), DefaultSymbolType('^'), DefaultSymbolType('D'), DefaultStateType(2));
+		automaton.addReturnTransition(DefaultStateType(2), DefaultSymbolType('^'), DefaultSymbolType('C'), DefaultStateType(3));
 
-  automaton.addCallTransition(DefaultStateType(0), DefaultSymbolType('a'), DefaultStateType(0), DefaultSymbolType('A'));
-  automaton.addReturnTransition(DefaultStateType(0), DefaultSymbolType('^'), DefaultSymbolType('A'), DefaultStateType(0));
+		automaton.addCallTransition(DefaultStateType(3), DefaultSymbolType('a'), DefaultStateType(4), DefaultSymbolType('E'));
+		automaton.addCallTransition(DefaultStateType(4), DefaultSymbolType('a'), DefaultStateType(4), DefaultSymbolType('F'));
+		automaton.addReturnTransition(DefaultStateType(4), DefaultSymbolType('^'), DefaultSymbolType('F'), DefaultStateType(4));
+		automaton.addReturnTransition(DefaultStateType(4), DefaultSymbolType('^'), DefaultSymbolType('E'), DefaultStateType(5));
 
-  automaton.addCallTransition(DefaultStateType(0), DefaultSymbolType('a'), DefaultStateType(1), DefaultSymbolType('B'));
+		automaton.addReturnTransition(DefaultStateType(5), DefaultSymbolType('^'), DefaultSymbolType('B'), DefaultStateType(6));
 
-  automaton.addCallTransition(DefaultStateType(1), DefaultSymbolType('a'), DefaultStateType(2), DefaultSymbolType('C'));
-  automaton.addCallTransition(DefaultStateType(2), DefaultSymbolType('a'), DefaultStateType(2), DefaultSymbolType('D'));
-  automaton.addReturnTransition(DefaultStateType(2), DefaultSymbolType('^'), DefaultSymbolType('D'), DefaultStateType(2));
-  automaton.addReturnTransition(DefaultStateType(2), DefaultSymbolType('^'), DefaultSymbolType('C'), DefaultStateType(3));
+		automaton.addInitialState(DefaultStateType(0));
+		automaton.addFinalState(DefaultStateType(4));
 
-  automaton.addCallTransition(DefaultStateType(3), DefaultSymbolType('a'), DefaultStateType(4), DefaultSymbolType('E'));
-  automaton.addCallTransition(DefaultStateType(4), DefaultSymbolType('a'), DefaultStateType(4), DefaultSymbolType('F'));
-  automaton.addReturnTransition(DefaultStateType(4), DefaultSymbolType('^'), DefaultSymbolType('F'), DefaultStateType(4));
-  automaton.addReturnTransition(DefaultStateType(4), DefaultSymbolType('^'), DefaultSymbolType('E'), DefaultStateType(5));
-
-  automaton.addReturnTransition(DefaultStateType(5), DefaultSymbolType('^'), DefaultSymbolType('B'), DefaultStateType(6));
-
-  automaton.addInitialState(DefaultStateType(0));
-  automaton.addFinalState(DefaultStateType(4));
-}
+		auto determinized = automaton::determinize::Determinize::determinize ( automaton );
+		CHECK ( determinized.getStates().size() == 29 );
+		CHECK ( determinized.getFinalStates().size() == 14 );
+		CHECK ( determinized.getCallTransitions().size() == 28 );
+		CHECK ( determinized.getReturnTransitions().size() == 198 );
+		CHECK ( determinized.getLocalTransitions().size() == 0 );
+		CHECK ( determinized.getCallTransitions().size() == 28 );
 
-void determinizeTest::testDeterminizeNFTA() {
-  automaton::NFTA < char, unsigned, int> automaton;
+	}
 
-  const common::ranked_symbol < char, unsigned > a ('a', 2);
-  const common::ranked_symbol < char, unsigned > b ('b', 1);
-  const common::ranked_symbol < char, unsigned > c ('c', 0);
-  const ext::set<common::ranked_symbol < char, unsigned > > alphabet {a, b, c};
-  automaton.setInputAlphabet(alphabet);
+	SECTION ( "NFTA" ) {
+		automaton::NFTA < char, unsigned, int> automaton;
 
-  automaton.addState(1);
-  automaton.addState(2);
-  automaton.addState(3);
+		const common::ranked_symbol < char, unsigned > a ('a', 2);
+		const common::ranked_symbol < char, unsigned > b ('b', 1);
+		const common::ranked_symbol < char, unsigned > c ('c', 0);
+		const ext::set<common::ranked_symbol < char, unsigned > > alphabet {a, b, c};
+		automaton.setInputAlphabet(alphabet);
 
-  ext::vector<int> a1States = {1, 3};
-  automaton.addTransition(a, a1States, 1);
-  automaton.addTransition(a, a1States, 3);
-  ext::vector<int> a2States = {3, 3};
-  automaton.addTransition(a, a2States, 2);
-  ext::vector<int> bStates = {2};
-  automaton.addTransition(b, bStates, 1);
-  ext::vector<int> cStates;
-  automaton.addTransition(c, cStates, 3);
+		automaton.addState(1);
+		automaton.addState(2);
+		automaton.addState(3);
 
-  automaton.addFinalState(3);
+		ext::vector<int> a1States = {1, 3};
+		automaton.addTransition(a, a1States, 1);
+		automaton.addTransition(a, a1States, 3);
+		ext::vector<int> a2States = {3, 3};
+		automaton.addTransition(a, a2States, 2);
+		ext::vector<int> bStates = {2};
+		automaton.addTransition(b, bStates, 1);
+		ext::vector<int> cStates;
+		automaton.addTransition(c, cStates, 3);
 
+		automaton.addFinalState(3);
 
-  automaton::DFTA < char, unsigned, ext::set < int > > determinized = automaton::determinize::Determinize::determinize(automaton);
+		automaton::DFTA < char, unsigned, ext::set < int > > determinized = automaton::determinize::Determinize::determinize(automaton);
 
-  CPPUNIT_ASSERT(determinized.getStates().size() == 5);
-  CPPUNIT_ASSERT(determinized.getFinalStates().size() == 3);
-  CPPUNIT_ASSERT(determinized.getTransitions().size() == 15);
+		CHECK(determinized.getStates().size() == 5);
+		CHECK(determinized.getFinalStates().size() == 3);
+		CHECK(determinized.getTransitions().size() == 15);
+	}
 }
diff --git a/alib2algo/test-src/automaton/determinize/determinizeTest.h b/alib2algo/test-src/automaton/determinize/determinizeTest.h
deleted file mode 100644
index 8bb94b7742..0000000000
--- a/alib2algo/test-src/automaton/determinize/determinizeTest.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef DETERMINIZE_TEST_H_
-#define DETERMINIZE_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class determinizeTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( determinizeTest );
-  CPPUNIT_TEST( testDeterminizeNFA );
-  CPPUNIT_TEST( testDeterminizeIDPDA );
-  CPPUNIT_TEST( testDeterminizeVPA );
-  CPPUNIT_TEST( testDeterminizeNFTA );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testDeterminizeNFA();
-  void testDeterminizeIDPDA();
-  void testDeterminizeVPA();
-  void testDeterminizeNFTA();
-};
-
-#endif  // DETERMINIZE_TEST_H_
diff --git a/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp b/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp
index 6e8de6b68b..55ef1b266d 100644
--- a/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp
+++ b/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp
@@ -1,46 +1,39 @@
-#include "EpsilonClosureTest.h"
+#include <catch2/catch.hpp>
 
 #include <automaton/FSM/EpsilonNFA.h>
 
 #include "automaton/properties/EpsilonClosure.h"
 #include "automaton/properties/AllEpsilonClosure.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EpsilonClosureTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( EpsilonClosureTest );
-
-void EpsilonClosureTest::setUp() {
-}
-
-void EpsilonClosureTest::tearDown() {
-}
-
-void EpsilonClosureTest::testEpsilonClosure() {
-	DefaultStateType q0 = DefaultStateType ("q0");
-	DefaultStateType q1 = DefaultStateType ("q1");
-	DefaultStateType q2 = DefaultStateType ("q2");
-	DefaultStateType q3 = DefaultStateType ("q3");
-	DefaultStateType q4 = DefaultStateType ("q4");
-	DefaultStateType q5 = DefaultStateType ("q5");
-	DefaultStateType q6 = DefaultStateType ("q6");
-	DefaultStateType q7 = DefaultStateType ("q7");
-	DefaultStateType q8 = DefaultStateType ("q8");
-	DefaultStateType q9 = DefaultStateType ("q9");
-
-	automaton::EpsilonNFA < > automaton(q0);
-	automaton.setStates({q0, q1, q2, q3, q4, q5, q6, q7, q8, q9});
-
-	automaton.addTransition(q0, q1);
-	automaton.addTransition(q1, q2);
-	automaton.addTransition(q2, q3);
-	automaton.addTransition(q3, q4);
-	automaton.addTransition(q4, q1);
-	automaton.addTransition(q5, q6);
-	automaton.addTransition(q6, q1);
-	automaton.addTransition(q8, q8);
-
-	ext::map<DefaultStateType, ext::set<DefaultStateType>> allClosures = automaton::properties::AllEpsilonClosure::allEpsilonClosure(automaton);
-
-	for(const DefaultStateType& state : automaton.getStates()) {
-		CPPUNIT_ASSERT(automaton::properties::EpsilonClosure::epsilonClosure(automaton, state) == allClosures[state]);
+TEST_CASE ( "Epsilon Closure", "[unit][algo][automaton]" ) {
+	SECTION ( "Test closure" ) {
+		DefaultStateType q0 = DefaultStateType ("q0");
+		DefaultStateType q1 = DefaultStateType ("q1");
+		DefaultStateType q2 = DefaultStateType ("q2");
+		DefaultStateType q3 = DefaultStateType ("q3");
+		DefaultStateType q4 = DefaultStateType ("q4");
+		DefaultStateType q5 = DefaultStateType ("q5");
+		DefaultStateType q6 = DefaultStateType ("q6");
+		DefaultStateType q7 = DefaultStateType ("q7");
+		DefaultStateType q8 = DefaultStateType ("q8");
+		DefaultStateType q9 = DefaultStateType ("q9");
+
+		automaton::EpsilonNFA < > automaton(q0);
+		automaton.setStates({q0, q1, q2, q3, q4, q5, q6, q7, q8, q9});
+
+		automaton.addTransition(q0, q1);
+		automaton.addTransition(q1, q2);
+		automaton.addTransition(q2, q3);
+		automaton.addTransition(q3, q4);
+		automaton.addTransition(q4, q1);
+		automaton.addTransition(q5, q6);
+		automaton.addTransition(q6, q1);
+		automaton.addTransition(q8, q8);
+
+		ext::map<DefaultStateType, ext::set<DefaultStateType>> allClosures = automaton::properties::AllEpsilonClosure::allEpsilonClosure(automaton);
+
+		for(const DefaultStateType& state : automaton.getStates()) {
+			CHECK(automaton::properties::EpsilonClosure::epsilonClosure(automaton, state) == allClosures[state]);
+		}
 	}
 }
diff --git a/alib2algo/test-src/automaton/properties/EpsilonClosureTest.h b/alib2algo/test-src/automaton/properties/EpsilonClosureTest.h
deleted file mode 100644
index ccb5ed888a..0000000000
--- a/alib2algo/test-src/automaton/properties/EpsilonClosureTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef EPSILON_CLOSURE_TEST_H_
-#define EPSILON_CLOSURE_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class EpsilonClosureTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( EpsilonClosureTest );
-  CPPUNIT_TEST( testEpsilonClosure );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testEpsilonClosure();
-};
-
-#endif /* EPSILON_CLOSURE_TEST_H_ */
diff --git a/alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.cpp b/alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.cpp
index f83491dd1d..49ff418ecd 100644
--- a/alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.cpp
+++ b/alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.cpp
@@ -1,4 +1,4 @@
-#include "FSMSingleInitialStateTest.h"
+#include <catch2/catch.hpp>
 
 #include "automaton/simplify/SingleInitialState.h"
 #include "automaton/determinize/Determinize.h"
@@ -7,48 +7,41 @@
 
 #include "automaton/FSM/MultiInitialStateNFA.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FSMSingleInitialStateTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( FSMSingleInitialStateTest );
-
-void FSMSingleInitialStateTest::setUp() {
-}
-
-void FSMSingleInitialStateTest::tearDown() {
-}
-
-void FSMSingleInitialStateTest::testSingleInitialState() {
-	DefaultStateType q  = DefaultStateType ("q");
-	DefaultStateType q0 = DefaultStateType ("q0");
-	DefaultStateType q1 = DefaultStateType ("q1");
-	DefaultStateType q2 = DefaultStateType ("q2");
-	DefaultStateType q3 = DefaultStateType ("q3");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	automaton::MultiInitialStateNFA < > automaton1;
-	automaton1.setStates({q0, q1, q2, q3});
-	automaton1.setInitialStates({q0, q1, q2});
-	automaton1.setFinalStates({q3});
-	automaton1.setInputAlphabet({a, b});
-	automaton1.addTransition(q0, a, q1);
-	automaton1.addTransition(q1, b, q2);
-	automaton1.addTransition(q2, a, q3);
-
-	automaton::NFA < > automaton2 = automaton::simplify::SingleInitialState::convert(automaton1);
-
-	automaton::NFA < > automaton3(q);
-	automaton3.setStates({q, q1, q2, q3});
-	automaton3.setFinalStates({q3});
-	automaton3.setInputAlphabet({a, b});
-	automaton3.addTransition(q, a, q3);
-	automaton3.addTransition(q, b, q2);
-	automaton3.addTransition(q, a, q1);
-	automaton3.addTransition(q1, b, q2);
-	automaton3.addTransition(q2, a, q3);
-
-	automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa2 = automaton::simplify::Minimize::minimize(automaton::determinize::Determinize::determinize(automaton2));
-	automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa3 = automaton::simplify::Minimize::minimize(automaton::determinize::Determinize::determinize(automaton3));
-
-	CPPUNIT_ASSERT(automaton::simplify::Normalize::normalize(dfa2) == automaton::simplify::Normalize::normalize(dfa3));
+TEST_CASE ( "FSM Single initial state", "[unit][algo][automaton][simplify]" ) {
+	SECTION ( "MISNFA to single initial state NFA" ) {
+		DefaultStateType q  = DefaultStateType ("q");
+		DefaultStateType q0 = DefaultStateType ("q0");
+		DefaultStateType q1 = DefaultStateType ("q1");
+		DefaultStateType q2 = DefaultStateType ("q2");
+		DefaultStateType q3 = DefaultStateType ("q3");
+
+		DefaultSymbolType a = DefaultSymbolType('a');
+		DefaultSymbolType b = DefaultSymbolType('b');
+
+		automaton::MultiInitialStateNFA < > automaton1;
+		automaton1.setStates({q0, q1, q2, q3});
+		automaton1.setInitialStates({q0, q1, q2});
+		automaton1.setFinalStates({q3});
+		automaton1.setInputAlphabet({a, b});
+		automaton1.addTransition(q0, a, q1);
+		automaton1.addTransition(q1, b, q2);
+		automaton1.addTransition(q2, a, q3);
+
+		automaton::NFA < > automaton2 = automaton::simplify::SingleInitialState::convert(automaton1);
+
+		automaton::NFA < > automaton3(q);
+		automaton3.setStates({q, q1, q2, q3});
+		automaton3.setFinalStates({q3});
+		automaton3.setInputAlphabet({a, b});
+		automaton3.addTransition(q, a, q3);
+		automaton3.addTransition(q, b, q2);
+		automaton3.addTransition(q, a, q1);
+		automaton3.addTransition(q1, b, q2);
+		automaton3.addTransition(q2, a, q3);
+
+		automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa2 = automaton::simplify::Minimize::minimize(automaton::determinize::Determinize::determinize(automaton2));
+		automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa3 = automaton::simplify::Minimize::minimize(automaton::determinize::Determinize::determinize(automaton3));
+
+		CHECK (automaton::simplify::Normalize::normalize(dfa2) == automaton::simplify::Normalize::normalize(dfa3));
+	}
 }
diff --git a/alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.h b/alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.h
deleted file mode 100644
index fee9a58ef3..0000000000
--- a/alib2algo/test-src/automaton/simplify/FSMSingleInitialStateTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef FSM_SINGLE_INITIAL_STATE_TEST_H_
-#define FSM_SINGLE_INITIAL_STATE_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class FSMSingleInitialStateTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( FSMSingleInitialStateTest );
-  CPPUNIT_TEST( testSingleInitialState );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testSingleInitialState();
-};
-
-#endif /* FSM_SINGLE_INITIAL_STATE_TEST_H_ */
diff --git a/alib2algo/test-src/automaton/simplify/FSMTotalTest.cpp b/alib2algo/test-src/automaton/simplify/FSMTotalTest.cpp
index 0cfecbd2d7..644381cb32 100644
--- a/alib2algo/test-src/automaton/simplify/FSMTotalTest.cpp
+++ b/alib2algo/test-src/automaton/simplify/FSMTotalTest.cpp
@@ -1,4 +1,4 @@
-#include "FSMTotalTest.h"
+#include <catch2/catch.hpp>
 
 #include <automaton/FSM/DFA.h>
 
@@ -6,41 +6,34 @@
 #include "automaton/simplify/Normalize.h"
 #include "automaton/simplify/Trim.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( TotalTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( TotalTest );
+TEST_CASE ( "Total automaton", "[unit][algo][automaton][simplify]" ) {
+	SECTION ( "DFA to DFA with total transition function" ) {
+		DefaultStateType q0 = DefaultStateType ("q0");
+		DefaultStateType q1 = DefaultStateType ("q1");
+		DefaultStateType q2 = DefaultStateType ("q2");
 
-void TotalTest::setUp() {
-}
-
-void TotalTest::tearDown() {
-}
-
-void TotalTest::testTotal() {
-	DefaultStateType q0 = DefaultStateType ("q0");
-	DefaultStateType q1 = DefaultStateType ("q1");
-	DefaultStateType q2 = DefaultStateType ("q2");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
+		DefaultSymbolType a = DefaultSymbolType('a');
+		DefaultSymbolType b = DefaultSymbolType('b');
+		DefaultSymbolType c = DefaultSymbolType('c');
 
-	automaton::DFA<> automaton(q0);
-	automaton.setStates({q0, q1, q2});
-	automaton.setFinalStates({q0, q1, q2});
-	automaton.setInputAlphabet({a, b, c});
+		automaton::DFA<> automaton(q0);
+		automaton.setStates({q0, q1, q2});
+		automaton.setFinalStates({q0, q1, q2});
+		automaton.setInputAlphabet({a, b, c});
 
-	automaton.addTransition(q0, a, q0);
-	automaton.addTransition(q0, b, q1);
-	automaton.addTransition(q0, c, q2);
-	automaton.addTransition(q1, b, q1);
-	automaton.addTransition(q1, c, q2);
-	automaton.addTransition(q2, c, q2);
+		automaton.addTransition(q0, a, q0);
+		automaton.addTransition(q0, b, q1);
+		automaton.addTransition(q0, c, q2);
+		automaton.addTransition(q1, b, q1);
+		automaton.addTransition(q1, c, q2);
+		automaton.addTransition(q2, c, q2);
 
-	automaton::DFA<> totalAutomaton = automaton::simplify::Total::total(automaton);
-	CPPUNIT_ASSERT(totalAutomaton.isTotal());
+		automaton::DFA<> totalAutomaton = automaton::simplify::Total::total(automaton);
+		CHECK(totalAutomaton.isTotal());
 
-	automaton::DFA<> trimmedAutomaton = automaton::simplify::Trim::trim(automaton);
-	automaton::DFA<> trimmedTotalAutomaton = automaton::simplify::Trim::trim(totalAutomaton);
+		automaton::DFA<> trimmedAutomaton = automaton::simplify::Trim::trim(automaton);
+		automaton::DFA<> trimmedTotalAutomaton = automaton::simplify::Trim::trim(totalAutomaton);
 
-	CPPUNIT_ASSERT(automaton::simplify::Normalize::normalize(trimmedAutomaton) == automaton::simplify::Normalize::normalize(trimmedTotalAutomaton));
+		CHECK(automaton::simplify::Normalize::normalize(trimmedAutomaton) == automaton::simplify::Normalize::normalize(trimmedTotalAutomaton));
+	}
 }
diff --git a/alib2algo/test-src/automaton/simplify/FSMTotalTest.h b/alib2algo/test-src/automaton/simplify/FSMTotalTest.h
deleted file mode 100644
index 1a7b09f16d..0000000000
--- a/alib2algo/test-src/automaton/simplify/FSMTotalTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef FSM_TOTAL_TEST_H_
-#define FSM_TOTAL_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class TotalTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( TotalTest );
-  CPPUNIT_TEST( testTotal );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testTotal();
-};
-
-#endif /* FSM_TOTAL_TEST_H_ */
diff --git a/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.cpp b/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.cpp
index 1ecee1151a..dd7fe5f2b8 100644
--- a/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.cpp
+++ b/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.cpp
@@ -1,37 +1,31 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "minimizeBrzozowskiTest.h"
 
 #include "automaton/simplify/MinimizeBrzozowski.h"
 #include "automaton/simplify/Minimize.h"
 #include "automaton/simplify/Trim.h"
 #include "automaton/simplify/Normalize.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( minimizeBrzozowskiTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( minimizeBrzozowskiTest );
+TEST_CASE ( "Brzozowski minimization", "[unit][algo][automaton][simplify]" ) {
+	SECTION ( "Test DFA" ) {
+		automaton::DFA < > automaton(DefaultStateType(1));
 
-void minimizeBrzozowskiTest::setUp() {
-}
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+		automaton.addInputSymbol(DefaultSymbolType("a"));
+		automaton.addInputSymbol(DefaultSymbolType("b"));
 
-void minimizeBrzozowskiTest::tearDown() {
-}
+		automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
+		automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
+
+		automaton.addFinalState(DefaultStateType(3));
+
+		automaton::DFA < > minimizedHopcroft = automaton::simplify::Minimize::minimize(automaton);
+		automaton::DFA < DefaultSymbolType, ext::set < ext::set < DefaultStateType > > > minimizedBrzozowski = automaton::simplify::MinimizeBrzozowski::minimize(automaton);
 
-void minimizeBrzozowskiTest::testMinimizeBrzozowski() {
-  automaton::DFA < > automaton(DefaultStateType(1));
-
-  automaton.addState(DefaultStateType(1));
-  automaton.addState(DefaultStateType(2));
-  automaton.addState(DefaultStateType(3));
-  automaton.addInputSymbol(DefaultSymbolType("a"));
-  automaton.addInputSymbol(DefaultSymbolType("b"));
-  
-  automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
-  automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
-
-  automaton.addFinalState(DefaultStateType(3));
-  
-  automaton::DFA < > minimizedHopcroft = automaton::simplify::Minimize::minimize(automaton);
-  automaton::DFA < DefaultSymbolType, ext::set < ext::set < DefaultStateType > > > minimizedBrzozowski = automaton::simplify::MinimizeBrzozowski::minimize(automaton);
-
-  CPPUNIT_ASSERT(minimizedHopcroft.getStates().size() == 3);
-  CPPUNIT_ASSERT(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(minimizedHopcroft)) == automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(minimizedBrzozowski)));
+		CHECK(minimizedHopcroft.getStates().size() == 3);
+		CHECK(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(minimizedHopcroft)) == automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(minimizedBrzozowski)));
+	}
 }
diff --git a/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.h b/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.h
deleted file mode 100644
index 0039075c8b..0000000000
--- a/alib2algo/test-src/automaton/simplify/minimizeBrzozowskiTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef MINIMIZE_BRZOZOWSKI_TEST_H_
-#define MINIMIZE_BRZOZOWSKI_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class minimizeBrzozowskiTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( minimizeBrzozowskiTest );
-  CPPUNIT_TEST( testMinimizeBrzozowski );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testMinimizeBrzozowski();
-};
-
-#endif  // MINIMIZE_BRZOZOWSKI_TEST_H_
diff --git a/alib2algo/test-src/automaton/simplify/minimizeTest.cpp b/alib2algo/test-src/automaton/simplify/minimizeTest.cpp
index 2f653fca81..5583ff41d1 100644
--- a/alib2algo/test-src/automaton/simplify/minimizeTest.cpp
+++ b/alib2algo/test-src/automaton/simplify/minimizeTest.cpp
@@ -1,178 +1,172 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "minimizeTest.h"
 
 #include "automaton/simplify/Minimize.h"
 #include <factory/XmlDataFactory.hpp>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( minimizeTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( minimizeTest );
-
-void minimizeTest::setUp() {
-}
-
-void minimizeTest::tearDown() {
-}
+TEST_CASE ( "Minimization", "[unit][algo][automaton][simplify]" ) {
+	SECTION ( "DFA" ) {
+		automaton::DFA < > automaton(DefaultStateType(1));
 
-void minimizeTest::testMinimizeDFA() {
-	automaton::DFA < > automaton(DefaultStateType(1));
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+		automaton.addInputSymbol(DefaultSymbolType("a"));
+		automaton.addInputSymbol(DefaultSymbolType("b"));
 
-	automaton.addState(DefaultStateType(1));
-	automaton.addState(DefaultStateType(2));
-	automaton.addState(DefaultStateType(3));
-	automaton.addInputSymbol(DefaultSymbolType("a"));
-	automaton.addInputSymbol(DefaultSymbolType("b"));
+		automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
+		automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
 
-	automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
-	automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
+		automaton.addFinalState(DefaultStateType(3));
 
-	automaton.addFinalState(DefaultStateType(3));
+		automaton::DFA<> minimized = automaton::simplify::Minimize::minimize(automaton);
 
-	automaton::DFA<> minimized = automaton::simplify::Minimize::minimize(automaton);
+		CHECK(minimized.getStates().size() == 3);
 
-	CPPUNIT_ASSERT(minimized.getStates().size() == 3);
-
-}
+	}
 
-void minimizeTest::testMinimizeDFTA() {
-	automaton::DFTA < > automaton;
+	SECTION ( "DFTA" ) {
+		automaton::DFTA < > automaton;
 
-	ext::vector<DefaultStateType> q;
+		ext::vector<DefaultStateType> q;
 
-	for (int i = 0; i <= 10; ++i) {
-		DefaultStateType state (i);
-		q.push_back(state);
-		automaton.addState(state);
-	}
+		for (int i = 0; i <= 10; ++i) {
+			DefaultStateType state (i);
+			q.push_back(state);
+			automaton.addState(state);
+		}
 
-	automaton.addFinalState(q[9]);
-	automaton.addFinalState(q[10]);
-
-	const common::ranked_symbol < > a (DefaultSymbolType("a"), DefaultRankType(3));
-	const common::ranked_symbol < > b (DefaultSymbolType("b"), DefaultRankType(2));
-	const common::ranked_symbol < > c (DefaultSymbolType("c"), DefaultRankType(1));
-	const common::ranked_symbol < > d (DefaultSymbolType("d"), DefaultRankType(0));
-	const common::ranked_symbol < > e (DefaultSymbolType("e"), DefaultRankType(0));
-	const common::ranked_symbol < > f (DefaultSymbolType("f"), DefaultRankType(0));
-	const common::ranked_symbol < > g (DefaultSymbolType("g"), DefaultRankType(0));
-
-	automaton.addInputSymbol(a);
-	automaton.addInputSymbol(b);
-	automaton.addInputSymbol(c);
-	automaton.addInputSymbol(d);
-	automaton.addInputSymbol(e);
-	automaton.addInputSymbol(f);
-	automaton.addInputSymbol(g);
-
-	automaton.addTransition(d, {}, q[0]);
-	automaton.addTransition(e, {}, q[1]);
-
-	for (int i = 0; i <= 1; ++i) {
-		for (int j = 0; j <= 1; ++j) {
-			automaton.addTransition(b, {q[i], q[j]}, q[2]);
+		automaton.addFinalState(q[9]);
+		automaton.addFinalState(q[10]);
+
+		const common::ranked_symbol < > a (DefaultSymbolType("a"), DefaultRankType(3));
+		const common::ranked_symbol < > b (DefaultSymbolType("b"), DefaultRankType(2));
+		const common::ranked_symbol < > c (DefaultSymbolType("c"), DefaultRankType(1));
+		const common::ranked_symbol < > d (DefaultSymbolType("d"), DefaultRankType(0));
+		const common::ranked_symbol < > e (DefaultSymbolType("e"), DefaultRankType(0));
+		const common::ranked_symbol < > f (DefaultSymbolType("f"), DefaultRankType(0));
+		const common::ranked_symbol < > g (DefaultSymbolType("g"), DefaultRankType(0));
+
+		automaton.addInputSymbol(a);
+		automaton.addInputSymbol(b);
+		automaton.addInputSymbol(c);
+		automaton.addInputSymbol(d);
+		automaton.addInputSymbol(e);
+		automaton.addInputSymbol(f);
+		automaton.addInputSymbol(g);
+
+		automaton.addTransition(d, {}, q[0]);
+		automaton.addTransition(e, {}, q[1]);
+
+		for (int i = 0; i <= 1; ++i) {
+			for (int j = 0; j <= 1; ++j) {
+				automaton.addTransition(b, {q[i], q[j]}, q[2]);
+			}
 		}
-	}
 
-	automaton.addTransition(b, {q[2], q[2]}, q[6]);
-	automaton.addTransition(f, {}, q[3]);
-	for (int i = 3; i < 5; ++i) {
-		automaton.addTransition(c, {q[i]}, q[i+1]);
-	}
+		automaton.addTransition(b, {q[2], q[2]}, q[6]);
+		automaton.addTransition(f, {}, q[3]);
+		for (int i = 3; i < 5; ++i) {
+			automaton.addTransition(c, {q[i]}, q[i+1]);
+		}
 
-	automaton.addTransition(c, {q[5]}, q[7]);
-	automaton.addTransition(g, {}, q[8]);
+		automaton.addTransition(c, {q[5]}, q[7]);
+		automaton.addTransition(g, {}, q[8]);
 
-	for (int i = 6; i <= 8; ++i) {
-		for (int j = 6; j <= 8; ++j) {
-			for (int k = 6; k <= 8; ++k) {
-				automaton.addTransition(a, {q[i], q[j], q[k]}, q[9]);
+		for (int i = 6; i <= 8; ++i) {
+			for (int j = 6; j <= 8; ++j) {
+				for (int k = 6; k <= 8; ++k) {
+					automaton.addTransition(a, {q[i], q[j], q[k]}, q[9]);
+				}
 			}
 		}
-	}
 
-	automaton.addTransition(a, {q[9], q[9], q[9]}, q[10]);
-
-	automaton::DFTA < > minimal;
-	minimal.addState(q[0]);
-	minimal.addState(q[2]);
-	minimal.addState(q[3]);
-	minimal.addState(q[4]);
-	minimal.addState(q[5]);
-	minimal.addState(q[6]);
-	minimal.addState(q[9]);
-	minimal.addState(q[10]);
-	minimal.setFinalStates(automaton.getFinalStates());
-	minimal.setInputAlphabet(automaton.getInputAlphabet());
-	minimal.addTransition(d, {}, q[0]);
-	minimal.addTransition(e, {}, q[0]);
-	minimal.addTransition(b, {q[0], q[0]}, q[2]);
-	minimal.addTransition(b, {q[2], q[2]}, q[6]);
-	minimal.addTransition(f, {}, q[3]);
-
-	for (int i = 3; i < 5; ++i) {
-		minimal.addTransition(c, {q[i]}, q[i+1]);
-	}
+		automaton.addTransition(a, {q[9], q[9], q[9]}, q[10]);
+
+		automaton::DFTA < > minimal;
+		minimal.addState(q[0]);
+		minimal.addState(q[2]);
+		minimal.addState(q[3]);
+		minimal.addState(q[4]);
+		minimal.addState(q[5]);
+		minimal.addState(q[6]);
+		minimal.addState(q[9]);
+		minimal.addState(q[10]);
+		minimal.setFinalStates(automaton.getFinalStates());
+		minimal.setInputAlphabet(automaton.getInputAlphabet());
+		minimal.addTransition(d, {}, q[0]);
+		minimal.addTransition(e, {}, q[0]);
+		minimal.addTransition(b, {q[0], q[0]}, q[2]);
+		minimal.addTransition(b, {q[2], q[2]}, q[6]);
+		minimal.addTransition(f, {}, q[3]);
+
+		for (int i = 3; i < 5; ++i) {
+			minimal.addTransition(c, {q[i]}, q[i+1]);
+		}
 
-	minimal.addTransition(c, {q[5]}, q[6]);
-	minimal.addTransition(g, {}, q[6]);
-	minimal.addTransition(a, {q[6], q[6], q[6]}, q[9]);
-	minimal.addTransition(a, {q[9], q[9], q[9]}, q[10]);
-
-	automaton::DFTA<> minimized = automaton::simplify::Minimize::minimize(automaton);
-	CPPUNIT_ASSERT(minimized == minimal);
-
-/*	automaton::DFTA < > automaton;
-
-	const DefaultStateType q0 ("0");
-	const DefaultStateType q1 ("1");
-	const DefaultStateType q00 ("00");
-	const DefaultStateType q11 ("11");
-	automaton.addState(q0);
-	automaton.addState(q1);
-	automaton.addState(q00);
-	automaton.addState(q11);
-
-	const common::ranked_symbol < > st ("t", 0);
-	const common::ranked_symbol < > sf ("f", 0);
-	const common::ranked_symbol < > snot ("not", 1);
-	const common::ranked_symbol < > sor ("or", 2);
-	automaton.addInputSymbol(st);
-	automaton.addInputSymbol(sf);
-	automaton.addInputSymbol(snot);
-	automaton.addInputSymbol(sor);
-
-	automaton.addTransition(st, {}, q1);
-	automaton.addTransition(sf, {}, q0);
-
-	automaton.addTransition(snot, {q0}, q1);
-	automaton.addTransition(snot, {q1}, q0);
-	automaton.addTransition(snot, {q00}, q1);
-	automaton.addTransition(snot, {q11}, q0);
-
-	automaton.addTransition(sor, {q0, q0}, q00);
-	automaton.addTransition(sor, {q0, q00}, q00);
-	automaton.addTransition(sor, {q00, q0}, q00);
-	automaton.addTransition(sor, {q00, q00}, q00);
-	automaton.addTransition(sor, {q0, q1}, q1);
-	automaton.addTransition(sor, {q0, q11}, q1);
-	automaton.addTransition(sor, {q00, q1}, q1);
-	automaton.addTransition(sor, {q00, q11}, q1);
-	automaton.addTransition(sor, {q1, q0}, q1);
-	automaton.addTransition(sor, {q1, q00}, q1);
-	automaton.addTransition(sor, {q11, q0}, q1);
-	automaton.addTransition(sor, {q11, q00}, q1);
-	automaton.addTransition(sor, {q1, q1}, q11);
-	automaton.addTransition(sor, {q1, q11}, q11);
-	automaton.addTransition(sor, {q11, q1}, q11);
-	automaton.addTransition(sor, {q11, q11}, q11);
-
-	automaton.addFinalState(q1);
-	automaton.addFinalState(q11);
-
-	automaton::DFTA<> minimized = automaton::simplify::Minimize::minimize(automaton);
-	std::cout << minimized << std::endl;
-	CPPUNIT_ASSERT(minimized.getStates().size() == 2);
-	CPPUNIT_ASSERT(minimized.getFinalStates().size() == 1);
-	CPPUNIT_ASSERT(minimized.getTransitions().size() == 8);
-	CPPUNIT_ASSERT(minimized.getInputAlphabet().size() == 4);
-*/
+		minimal.addTransition(c, {q[5]}, q[6]);
+		minimal.addTransition(g, {}, q[6]);
+		minimal.addTransition(a, {q[6], q[6], q[6]}, q[9]);
+		minimal.addTransition(a, {q[9], q[9], q[9]}, q[10]);
+
+		automaton::DFTA<> minimized = automaton::simplify::Minimize::minimize(automaton);
+		CHECK(minimized == minimal);
+
+		/*	automaton::DFTA < > automaton;
+
+			const DefaultStateType q0 ("0");
+			const DefaultStateType q1 ("1");
+			const DefaultStateType q00 ("00");
+			const DefaultStateType q11 ("11");
+			automaton.addState(q0);
+			automaton.addState(q1);
+			automaton.addState(q00);
+			automaton.addState(q11);
+
+			const common::ranked_symbol < > st ("t", 0);
+			const common::ranked_symbol < > sf ("f", 0);
+			const common::ranked_symbol < > snot ("not", 1);
+			const common::ranked_symbol < > sor ("or", 2);
+			automaton.addInputSymbol(st);
+			automaton.addInputSymbol(sf);
+			automaton.addInputSymbol(snot);
+			automaton.addInputSymbol(sor);
+
+			automaton.addTransition(st, {}, q1);
+			automaton.addTransition(sf, {}, q0);
+
+			automaton.addTransition(snot, {q0}, q1);
+			automaton.addTransition(snot, {q1}, q0);
+			automaton.addTransition(snot, {q00}, q1);
+			automaton.addTransition(snot, {q11}, q0);
+
+			automaton.addTransition(sor, {q0, q0}, q00);
+			automaton.addTransition(sor, {q0, q00}, q00);
+			automaton.addTransition(sor, {q00, q0}, q00);
+			automaton.addTransition(sor, {q00, q00}, q00);
+			automaton.addTransition(sor, {q0, q1}, q1);
+			automaton.addTransition(sor, {q0, q11}, q1);
+			automaton.addTransition(sor, {q00, q1}, q1);
+			automaton.addTransition(sor, {q00, q11}, q1);
+			automaton.addTransition(sor, {q1, q0}, q1);
+			automaton.addTransition(sor, {q1, q00}, q1);
+			automaton.addTransition(sor, {q11, q0}, q1);
+			automaton.addTransition(sor, {q11, q00}, q1);
+			automaton.addTransition(sor, {q1, q1}, q11);
+			automaton.addTransition(sor, {q1, q11}, q11);
+			automaton.addTransition(sor, {q11, q1}, q11);
+			automaton.addTransition(sor, {q11, q11}, q11);
+
+			automaton.addFinalState(q1);
+			automaton.addFinalState(q11);
+
+			automaton::DFTA<> minimized = automaton::simplify::Minimize::minimize(automaton);
+			std::cout << minimized << std::endl;
+			CPPUNIT_ASSERT(minimized.getStates().size() == 2);
+			CPPUNIT_ASSERT(minimized.getFinalStates().size() == 1);
+			CPPUNIT_ASSERT(minimized.getTransitions().size() == 8);
+			CPPUNIT_ASSERT(minimized.getInputAlphabet().size() == 4);
+			*/
+	}
 }
diff --git a/alib2algo/test-src/automaton/simplify/minimizeTest.h b/alib2algo/test-src/automaton/simplify/minimizeTest.h
deleted file mode 100644
index 50813dbd68..0000000000
--- a/alib2algo/test-src/automaton/simplify/minimizeTest.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef MINIMIZE_TEST_H_
-#define MINIMIZE_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class minimizeTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE( minimizeTest );
-	CPPUNIT_TEST( testMinimizeDFA );
-	CPPUNIT_TEST( testMinimizeDFTA );
-	CPPUNIT_TEST_SUITE_END();
-
-public:
-	void setUp();
-	void tearDown();
-
-	void testMinimizeDFA();
-	void testMinimizeDFTA();
-};
-
-#endif  // MINIMIZE_TEST_H_
diff --git a/alib2algo/test-src/automaton/simplify/normalizeTest.cpp b/alib2algo/test-src/automaton/simplify/normalizeTest.cpp
index b45dc838cc..8422c1ad82 100644
--- a/alib2algo/test-src/automaton/simplify/normalizeTest.cpp
+++ b/alib2algo/test-src/automaton/simplify/normalizeTest.cpp
@@ -1,49 +1,42 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "normalizeTest.h"
 
 #include "automaton/simplify/Normalize.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( normalizeTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( normalizeTest );
-
-void normalizeTest::setUp() {
-}
-
-void normalizeTest::tearDown() {
-}
-
-void normalizeTest::testNormalize() {
-  automaton::DFA < > automaton(DefaultStateType(0));
-
-  automaton.addState(DefaultStateType(0));
-  automaton.addState(DefaultStateType(1));
-  automaton.addState(DefaultStateType(2));
-  automaton.addInputSymbol(DefaultSymbolType("a"));
-  automaton.addInputSymbol(DefaultSymbolType("b"));
+TEST_CASE ( "Normalize", "[unit][algo][automaton][simplify]" ) {
+	SECTION ( "DFA" ) {
+		automaton::DFA < > automaton(DefaultStateType(0));
 
-  automaton.addTransition(DefaultStateType(0), DefaultSymbolType("a"), DefaultStateType(1));
-  automaton.addTransition(DefaultStateType(1), DefaultSymbolType("b"), DefaultStateType(2));
+		automaton.addState(DefaultStateType(0));
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addInputSymbol(DefaultSymbolType("a"));
+		automaton.addInputSymbol(DefaultSymbolType("b"));
 
-  automaton.addFinalState(DefaultStateType(2));
+		automaton.addTransition(DefaultStateType(0), DefaultSymbolType("a"), DefaultStateType(1));
+		automaton.addTransition(DefaultStateType(1), DefaultSymbolType("b"), DefaultStateType(2));
 
-  automaton::DFA < DefaultSymbolType, unsigned > normalized = automaton::simplify::Normalize::normalize(automaton);
+		automaton.addFinalState(DefaultStateType(2));
 
-  CPPUNIT_ASSERT(normalized.getStates().size() == automaton.getStates().size());
+		automaton::DFA < DefaultSymbolType, unsigned > normalized = automaton::simplify::Normalize::normalize(automaton);
 
-  CPPUNIT_ASSERT(normalized.getTransitions().size() == automaton.getTransitions().size());
+		CHECK(normalized.getStates().size() == automaton.getStates().size());
+		CHECK(normalized.getTransitions().size() == automaton.getTransitions().size());
 
-  automaton::DFA < DefaultSymbolType, unsigned > reference(0);
+		automaton::DFA < DefaultSymbolType, unsigned > reference(0);
 
-  reference.addState(0);
-  reference.addState(1);
-  reference.addState(2);
-  reference.addInputSymbol(DefaultSymbolType("a"));
-  reference.addInputSymbol(DefaultSymbolType("b"));
+		reference.addState(0);
+		reference.addState(1);
+		reference.addState(2);
+		reference.addInputSymbol(DefaultSymbolType("a"));
+		reference.addInputSymbol(DefaultSymbolType("b"));
 
-  reference.addTransition(0, DefaultSymbolType("a"), 1);
-  reference.addTransition(1, DefaultSymbolType("b"), 2);
+		reference.addTransition(0, DefaultSymbolType("a"), 1);
+		reference.addTransition(1, DefaultSymbolType("b"), 2);
 
-  reference.addFinalState(2);
+		reference.addFinalState(2);
 
-  CPPUNIT_ASSERT ( normalized == reference );
+		CHECK ( normalized == reference );
+	}
 }
diff --git a/alib2algo/test-src/automaton/simplify/normalizeTest.h b/alib2algo/test-src/automaton/simplify/normalizeTest.h
deleted file mode 100644
index 3f915a4861..0000000000
--- a/alib2algo/test-src/automaton/simplify/normalizeTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef NORMALIZE_TEST_H_
-#define NORMALIZE_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class normalizeTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( normalizeTest );
-  CPPUNIT_TEST( testNormalize );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testNormalize();
-};
-
-#endif  // NORMALIZE_TEST_H_
diff --git a/alib2algo/test-src/automaton/simplify/trimTest.cpp b/alib2algo/test-src/automaton/simplify/trimTest.cpp
index c2be0d96e5..bf7f50f8d0 100644
--- a/alib2algo/test-src/automaton/simplify/trimTest.cpp
+++ b/alib2algo/test-src/automaton/simplify/trimTest.cpp
@@ -1,116 +1,83 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "trimTest.h"
 
 #include "automaton/simplify/Trim.h"
-#include "grammar/simplify/Trim.h"
 
 #include "automaton/FSM/DFA.h"
-#include "grammar/Regular/RightRG.h"
 #include "automaton/TA/DFTA.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( trimTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( trimTest );
-
-void trimTest::setUp() {
-}
-
-void trimTest::tearDown() {
-}
-
-void trimTest::testTrimAutomaton() {
-	automaton::DFA < > automaton(DefaultStateType(1));
-
-	automaton.addState(DefaultStateType(1));
-	automaton.addState(DefaultStateType(2));
-	automaton.addState(DefaultStateType(3));
-	automaton.addInputSymbol(DefaultSymbolType("a"));
-	automaton.addInputSymbol(DefaultSymbolType("b"));
+TEST_CASE ( "Trim Automaton", "[unit][algo][automaton][simplify]" ) {
+	SECTION ( "DFA" ) {
+		automaton::DFA < > automaton(DefaultStateType(1));
 
-	automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
-	automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
-	automaton.addTransition(DefaultStateType(3), DefaultSymbolType("b"), DefaultStateType(1));
+		automaton.addState(DefaultStateType(1));
+		automaton.addState(DefaultStateType(2));
+		automaton.addState(DefaultStateType(3));
+		automaton.addInputSymbol(DefaultSymbolType("a"));
+		automaton.addInputSymbol(DefaultSymbolType("b"));
 
-	automaton.addFinalState(DefaultStateType(1));
+		automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
+		automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
+		automaton.addTransition(DefaultStateType(3), DefaultSymbolType("b"), DefaultStateType(1));
 
-	automaton::DFA<> trimed = automaton::simplify::Trim::trim(automaton);
+		automaton.addFinalState(DefaultStateType(1));
 
-	CPPUNIT_ASSERT(trimed.getStates().size() == 2);
-}
+		automaton::DFA<> trimed = automaton::simplify::Trim::trim(automaton);
 
-void trimTest::testTrimGrammar() {
-	grammar::RightRG < > rrGrammar(DefaultSymbolType(1));
-
-	rrGrammar.addNonterminalSymbol(DefaultSymbolType(1));
-	rrGrammar.addNonterminalSymbol(DefaultSymbolType(2));
-	rrGrammar.addNonterminalSymbol(DefaultSymbolType(3));
-	rrGrammar.addNonterminalSymbol(DefaultSymbolType(4));
-	rrGrammar.addNonterminalSymbol(DefaultSymbolType(5));
-	rrGrammar.addNonterminalSymbol(DefaultSymbolType(6));
-	rrGrammar.addTerminalSymbol(DefaultSymbolType("a"));
-	rrGrammar.addTerminalSymbol(DefaultSymbolType("b"));
-	
-	rrGrammar.addRule(DefaultSymbolType(1), ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(2)));
-	rrGrammar.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(3)));
-	rrGrammar.addRule(DefaultSymbolType(3), DefaultSymbolType("a"));
-
-	rrGrammar.addRule(DefaultSymbolType(4), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(5)));
-	rrGrammar.addRule(DefaultSymbolType(5), DefaultSymbolType("a"));
-	rrGrammar.addRule(DefaultSymbolType(5), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(2)));
-	rrGrammar.addRule(DefaultSymbolType(6), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(6)));
-
-	grammar::RightRG < > trimed = grammar::simplify::Trim::trim(rrGrammar);
-
-	CPPUNIT_ASSERT(trimed.getNonterminalAlphabet().size() == 3);
-}
+		CHECK (trimed.getStates().size() == 2);
+	}
 
-void trimTest::testTrimDFTA() {
-	automaton::DFTA < > automaton;
 
-	ext::vector<DefaultStateType> q;
-	for (int i = 0; i <= 11; ++i) {
-		DefaultStateType state (i);
-		q.push_back(state);
-		automaton.addState(state);
+	SECTION ( "DFTA" ) {
+		automaton::DFTA < > automaton;
+
+		ext::vector<DefaultStateType> q;
+		for (int i = 0; i <= 11; ++i) {
+			DefaultStateType state (i);
+			q.push_back(state);
+			automaton.addState(state);
+		}
+		automaton.addFinalState(q[2]);
+		automaton.addFinalState(q[11]);
+
+		const common::ranked_symbol < > a (DefaultSymbolType("a"), DefaultRankType(2));
+		const common::ranked_symbol < > b (DefaultSymbolType("b"), DefaultRankType(1));
+		const common::ranked_symbol < > c (DefaultSymbolType("c"), DefaultRankType(0));
+		automaton.addInputSymbol(a);
+		automaton.addInputSymbol(b);
+		automaton.addInputSymbol(c);
+
+		automaton.addTransition(c, {}, q[0]);
+		automaton.addTransition(a, {q[0], q[0]}, q[1]);
+		automaton.addTransition(b, {q[1]}, q[2]);
+
+		//unreachable and useless
+		automaton.addTransition(a, {q[3], q[4]}, q[5]);
+		automaton.addTransition(b, {q[5]}, q[6]);
+
+		//useless
+		automaton.addTransition(a, {q[2], q[2]}, q[7]);
+		automaton.addTransition(a, {q[7], q[7]}, q[8]);
+
+		//unreachable
+		automaton.addTransition(a, {q[9], q[9]}, q[10]);
+		automaton.addTransition(a, {q[10], q[10]}, q[11]);
+
+		automaton::DFTA<> trimed = automaton::simplify::Trim::trim(automaton);
+
+		automaton::DFTA<> correct;
+		correct.addState(q[0]);
+		correct.addState(q[1]);
+		correct.addState(q[2]);
+		correct.addFinalState(q[2]);
+		correct.addInputSymbol(a);
+		correct.addInputSymbol(b);
+		correct.addInputSymbol(c);
+		correct.addTransition(c, {}, q[0]);
+		correct.addTransition(a, {q[0], q[0]}, q[1]);
+		correct.addTransition(b, {q[1]}, q[2]);
+
+		CHECK (trimed == correct);
 	}
-	automaton.addFinalState(q[2]);
-	automaton.addFinalState(q[11]);
-
-	const common::ranked_symbol < > a (DefaultSymbolType("a"), DefaultRankType(2));
-	const common::ranked_symbol < > b (DefaultSymbolType("b"), DefaultRankType(1));
-	const common::ranked_symbol < > c (DefaultSymbolType("c"), DefaultRankType(0));
-	automaton.addInputSymbol(a);
-	automaton.addInputSymbol(b);
-	automaton.addInputSymbol(c);
-
-	automaton.addTransition(c, {}, q[0]);
-	automaton.addTransition(a, {q[0], q[0]}, q[1]);
-	automaton.addTransition(b, {q[1]}, q[2]);
-
-	//unreachable and useless
-	automaton.addTransition(a, {q[3], q[4]}, q[5]);
-	automaton.addTransition(b, {q[5]}, q[6]);
-
-	//useless
-	automaton.addTransition(a, {q[2], q[2]}, q[7]);
-	automaton.addTransition(a, {q[7], q[7]}, q[8]);
-
-	//unreachable
-	automaton.addTransition(a, {q[9], q[9]}, q[10]);
-	automaton.addTransition(a, {q[10], q[10]}, q[11]);
-
-	automaton::DFTA<> trimed = automaton::simplify::Trim::trim(automaton);
-
-	automaton::DFTA<> correct;
-	correct.addState(q[0]);
-	correct.addState(q[1]);
-	correct.addState(q[2]);
-	correct.addFinalState(q[2]);
-	correct.addInputSymbol(a);
-	correct.addInputSymbol(b);
-	correct.addInputSymbol(c);
-	correct.addTransition(c, {}, q[0]);
-	correct.addTransition(a, {q[0], q[0]}, q[1]);
-	correct.addTransition(b, {q[1]}, q[2]);
-
-	CPPUNIT_ASSERT(trimed == correct);
 }
diff --git a/alib2algo/test-src/automaton/simplify/trimTest.h b/alib2algo/test-src/automaton/simplify/trimTest.h
deleted file mode 100644
index 79b6736ce6..0000000000
--- a/alib2algo/test-src/automaton/simplify/trimTest.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef TRIM_TEST_H_
-#define TRIM_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class trimTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE( trimTest );
-	CPPUNIT_TEST( testTrimAutomaton );
-	CPPUNIT_TEST( testTrimGrammar );
-	CPPUNIT_TEST( testTrimDFTA );
-	CPPUNIT_TEST_SUITE_END();
-
-public:
-	void setUp();
-	void tearDown();
-
-	void testTrimAutomaton();
-	void testTrimGrammar();
-	void testTrimDFTA();
-};
-
-#endif	// TRIM_TEST_H_
diff --git a/alib2algo/test-src/automaton/transform/AutomataCompactionTest.cpp b/alib2algo/test-src/automaton/transform/AutomataCompactionTest.cpp
index 7dd26aa048..3ae781f59b 100644
--- a/alib2algo/test-src/automaton/transform/AutomataCompactionTest.cpp
+++ b/alib2algo/test-src/automaton/transform/AutomataCompactionTest.cpp
@@ -1,123 +1,114 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "AutomataCompactionTest.h"
 
 #include "automaton/transform/Compaction.h"
 #include <automaton/FSM/DFA.h>
 #include <automaton/FSM/CompactNFA.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AutomataCompactionTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( AutomataCompactionTest );
-
-void AutomataCompactionTest::setUp() {
-}
-
-void AutomataCompactionTest::tearDown() {
-}
-
-void AutomataCompactionTest::testAutomataCompaction1() {
-	DefaultStateType q0 = DefaultStateType("0");
-	DefaultStateType q1 = DefaultStateType("1");
-	DefaultStateType q2 = DefaultStateType("2");
-	DefaultStateType q3 = DefaultStateType("3");
-	DefaultStateType q4 = DefaultStateType("4");
-	DefaultStateType q5 = DefaultStateType("5");
-	DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
-
-	automaton::DFA<> m1(q0);
-	automaton::CompactNFA < > m2(q0);
-
-	m1.setInputAlphabet({a, b});
-	m1.setStates({q0, q1, q2, q3, q4, q5});
-	m1.addTransition(q0, a, q1);
-	m1.addTransition(q1, b, q2);
-	m1.addTransition(q2, a, q3);
-	m1.addTransition(q3, b, q4);
-	m1.addTransition(q4, a, q5);
-	m1.addFinalState(q5);
-
-	m2.setInputAlphabet({a, b});
-	m2.setStates({q0, q5});
-	m2.addTransition(q0, ext::vector <DefaultSymbolType > {a, b, a, b, a}, q5);
-	m2.addFinalState(q5);
-
-	automaton::CompactNFA < > c1 = automaton::transform::Compaction::convert(m1);
-
-	CPPUNIT_ASSERT(c1 == m2);
-
-}
-
-void AutomataCompactionTest::testAutomataCompaction2() {
-	DefaultStateType q0 = DefaultStateType("0");
-	DefaultStateType q1 = DefaultStateType("1");
-	DefaultStateType q2 = DefaultStateType("2");
-	DefaultStateType q3 = DefaultStateType("3");
-	DefaultStateType q4 = DefaultStateType("4");
-	DefaultStateType q5 = DefaultStateType("5");
-	DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
-
-	automaton::DFA<> m1(q0);
-	automaton::CompactNFA < > m2(q0);
-
-	m1.setInputAlphabet({a, b});
-	m1.setStates({q0, q1, q2, q3, q4, q5});
-	m1.addTransition(q0, a, q1);
-	m1.addTransition(q1, b, q2);
-	m1.addTransition(q2, a, q3);
-	m1.addTransition(q3, b, q4);
-	m1.addTransition(q4, a, q5);
-	m1.addTransition(q5, a, q1);
-	m1.addFinalState(q5);
-
-	m2.setInputAlphabet({a, b});
-	m2.setStates({q0, q5});
-	m2.addTransition(q0, ext::vector < DefaultSymbolType > { a, b, a, b, a }, q5);
-	m2.addTransition(q5, ext::vector < DefaultSymbolType > { a, b, a, b, a }, q5);
-	m2.addFinalState(q5);
-
-	automaton::CompactNFA < > c1 = automaton::transform::Compaction::convert(m1);
-
-	CPPUNIT_ASSERT(c1 == m2);
-
-}
-
-void AutomataCompactionTest::testAutomataCompaction3() {
-	DefaultStateType q0 = DefaultStateType("0");
-	DefaultStateType q1 = DefaultStateType("1");
-	DefaultStateType q2 = DefaultStateType("2");
-	DefaultStateType q3 = DefaultStateType("3");
-	DefaultStateType q4 = DefaultStateType("4");
-	DefaultStateType q5 = DefaultStateType("5");
-	DefaultStateType q6 = DefaultStateType("6");
-	DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
-
-	automaton::DFA<> m1(q0);
-	automaton::CompactNFA < > m2(q0);
-
-	m1.setInputAlphabet({a, b});
-	m1.setStates({q0, q1, q2, q3, q4, q5, q6});
-	m1.addTransition(q0, a, q1);
-	m1.addTransition(q1, a, q2);
-	m1.addTransition(q2, a, q3);
-	m1.addTransition(q3, a, q4);
-	m1.addTransition(q4, a, q2);
-	m1.addTransition(q1, b, q5);
-	m1.addTransition(q5, b, q6);
-	m1.addTransition(q6, a, q0);
-	m1.addFinalState(q3);
-	m1.addFinalState(q5);
-
-	m2.setInputAlphabet({a, b});
-	m2.setStates({q0, q1, q3, q5});
-	m2.addTransition(q0, ext::vector < DefaultSymbolType > {a}, q1);
-	m2.addTransition(q1, ext::vector < DefaultSymbolType > {a, a}, q3);
-	m2.addTransition(q3, ext::vector < DefaultSymbolType > {a, a, a}, q3);
-	m2.addTransition(q1, ext::vector < DefaultSymbolType > {b}, q5);
-	m2.addTransition(q5, ext::vector < DefaultSymbolType > {b, a, a}, q1);
-	m2.addFinalState(q3);
-	m2.addFinalState(q5);
-
-	automaton::CompactNFA < > c1 = automaton::transform::Compaction::convert(m1);
-
-	CPPUNIT_ASSERT(c1 == m2);
-
+TEST_CASE ( "Automata Compaction", "[unit][algo][automaton][transform]" ) {
+	SECTION ( "DFA" ) {
+		{
+			DefaultStateType q0 = DefaultStateType("0");
+			DefaultStateType q1 = DefaultStateType("1");
+			DefaultStateType q2 = DefaultStateType("2");
+			DefaultStateType q3 = DefaultStateType("3");
+			DefaultStateType q4 = DefaultStateType("4");
+			DefaultStateType q5 = DefaultStateType("5");
+			DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
+
+			automaton::DFA<> m1(q0);
+			automaton::CompactNFA < > m2(q0);
+
+			m1.setInputAlphabet({a, b});
+			m1.setStates({q0, q1, q2, q3, q4, q5});
+			m1.addTransition(q0, a, q1);
+			m1.addTransition(q1, b, q2);
+			m1.addTransition(q2, a, q3);
+			m1.addTransition(q3, b, q4);
+			m1.addTransition(q4, a, q5);
+			m1.addFinalState(q5);
+
+			m2.setInputAlphabet({a, b});
+			m2.setStates({q0, q5});
+			m2.addTransition(q0, ext::vector <DefaultSymbolType > {a, b, a, b, a}, q5);
+			m2.addFinalState(q5);
+
+			automaton::CompactNFA < > c1 = automaton::transform::Compaction::convert(m1);
+
+			CHECK (c1 == m2);
+		}{
+			DefaultStateType q0 = DefaultStateType("0");
+			DefaultStateType q1 = DefaultStateType("1");
+			DefaultStateType q2 = DefaultStateType("2");
+			DefaultStateType q3 = DefaultStateType("3");
+			DefaultStateType q4 = DefaultStateType("4");
+			DefaultStateType q5 = DefaultStateType("5");
+			DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
+
+			automaton::DFA<> m1(q0);
+			automaton::CompactNFA < > m2(q0);
+
+			m1.setInputAlphabet({a, b});
+			m1.setStates({q0, q1, q2, q3, q4, q5});
+			m1.addTransition(q0, a, q1);
+			m1.addTransition(q1, b, q2);
+			m1.addTransition(q2, a, q3);
+			m1.addTransition(q3, b, q4);
+			m1.addTransition(q4, a, q5);
+			m1.addTransition(q5, a, q1);
+			m1.addFinalState(q5);
+
+			m2.setInputAlphabet({a, b});
+			m2.setStates({q0, q5});
+			m2.addTransition(q0, ext::vector < DefaultSymbolType > { a, b, a, b, a }, q5);
+			m2.addTransition(q5, ext::vector < DefaultSymbolType > { a, b, a, b, a }, q5);
+			m2.addFinalState(q5);
+
+			automaton::CompactNFA < > c1 = automaton::transform::Compaction::convert(m1);
+
+			CHECK (c1 == m2);
+
+		}
+		{
+			DefaultStateType q0 = DefaultStateType("0");
+			DefaultStateType q1 = DefaultStateType("1");
+			DefaultStateType q2 = DefaultStateType("2");
+			DefaultStateType q3 = DefaultStateType("3");
+			DefaultStateType q4 = DefaultStateType("4");
+			DefaultStateType q5 = DefaultStateType("5");
+			DefaultStateType q6 = DefaultStateType("6");
+			DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
+
+			automaton::DFA<> m1(q0);
+			automaton::CompactNFA < > m2(q0);
+
+			m1.setInputAlphabet({a, b});
+			m1.setStates({q0, q1, q2, q3, q4, q5, q6});
+			m1.addTransition(q0, a, q1);
+			m1.addTransition(q1, a, q2);
+			m1.addTransition(q2, a, q3);
+			m1.addTransition(q3, a, q4);
+			m1.addTransition(q4, a, q2);
+			m1.addTransition(q1, b, q5);
+			m1.addTransition(q5, b, q6);
+			m1.addTransition(q6, a, q0);
+			m1.addFinalState(q3);
+			m1.addFinalState(q5);
+
+			m2.setInputAlphabet({a, b});
+			m2.setStates({q0, q1, q3, q5});
+			m2.addTransition(q0, ext::vector < DefaultSymbolType > {a}, q1);
+			m2.addTransition(q1, ext::vector < DefaultSymbolType > {a, a}, q3);
+			m2.addTransition(q3, ext::vector < DefaultSymbolType > {a, a, a}, q3);
+			m2.addTransition(q1, ext::vector < DefaultSymbolType > {b}, q5);
+			m2.addTransition(q5, ext::vector < DefaultSymbolType > {b, a, a}, q1);
+			m2.addFinalState(q3);
+			m2.addFinalState(q5);
+
+			automaton::CompactNFA < > c1 = automaton::transform::Compaction::convert(m1);
+
+			CHECK (c1 == m2);
+		}
+	}
 }
diff --git a/alib2algo/test-src/automaton/transform/AutomataCompactionTest.h b/alib2algo/test-src/automaton/transform/AutomataCompactionTest.h
deleted file mode 100644
index 5f739feed3..0000000000
--- a/alib2algo/test-src/automaton/transform/AutomataCompactionTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef AUTOMATA_COMPACTION_TEST_H_
-#define AUTOMATA_COMPACTION_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class AutomataCompactionTest : public CppUnit::TestFixture {
-
-	CPPUNIT_TEST_SUITE( AutomataCompactionTest );
-	CPPUNIT_TEST( testAutomataCompaction1 );
-	CPPUNIT_TEST( testAutomataCompaction2 );
-	CPPUNIT_TEST( testAutomataCompaction3 );
-	CPPUNIT_TEST_SUITE_END();
-
-public:
-	void setUp();
-	void tearDown();
-
-	void testAutomataCompaction1();
-	void testAutomataCompaction2();
-	void testAutomataCompaction3();
-};
-
-#endif /* AUTOMATA_COMPACTION_TEST_H_ */
diff --git a/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.cpp b/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.cpp
index ca08491af2..702b60f084 100644
--- a/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.cpp
+++ b/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.cpp
@@ -1,5 +1,6 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "AutomataConcatenationTest.h"
 
 #include "automaton/transform/AutomataConcatenation.h"
 #include "automaton/transform/AutomataConcatenationEpsilonTransition.h"
@@ -11,79 +12,71 @@
 #include "automaton/simplify/Total.h"
 #include "automaton/determinize/Determinize.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AutomataConcatenationTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( AutomataConcatenationTest );
-
-void AutomataConcatenationTest::setUp() {
-}
-
-void AutomataConcatenationTest::tearDown() {
-}
-
-void AutomataConcatenationTest::testAutomataConcatenation() {
-	// based on Melichar, 2.79
-
-	DefaultStateType q1a = DefaultStateType("1");
-	DefaultStateType q2a = DefaultStateType("2");
-	DefaultStateType q0a = DefaultStateType("0");
-	DefaultStateType q1b = DefaultStateType("1'");
-	DefaultStateType q2b = DefaultStateType("2'");
-	DefaultStateType q0b = DefaultStateType("0'");
-	DefaultStateType q0102 = DefaultStateType("q0102");
-	DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
+TEST_CASE ( "Automata Concatenation", "[unit][algo][automaton][transform]" ) {
+	SECTION ( "NFA/DFA" ) {
+		// based on Melichar, 2.79
 
-	automaton::DFA<> m1(q1a);
-	automaton::DFA<> m2(q1b);
-	automaton::NFA < >  m3(q1a);
+		DefaultStateType q1a = DefaultStateType("1");
+		DefaultStateType q2a = DefaultStateType("2");
+		DefaultStateType q0a = DefaultStateType("0");
+		DefaultStateType q1b = DefaultStateType("1'");
+		DefaultStateType q2b = DefaultStateType("2'");
+		DefaultStateType q0b = DefaultStateType("0'");
+		DefaultStateType q0102 = DefaultStateType("q0102");
+		DefaultSymbolType a(DefaultSymbolType('a')), b(DefaultSymbolType('b'));
 
-	m1.setInputAlphabet({a, b});
-	m1.setStates({q1a, q2a, q0a});
-	m1.addTransition(q1a, a, q2a);
-	m1.addTransition(q1a, b, q0a);
-	m1.addTransition(q2a, a, q2a);
-	m1.addTransition(q2a, b, q0a);
-	m1.addTransition(q0a, a, q0a);
-	m1.addTransition(q0a, b, q0a);
-	m1.addFinalState(q2a);
+		automaton::DFA<> m1(q1a);
+		automaton::DFA<> m2(q1b);
+		automaton::NFA < >  m3(q1a);
 
-	m2.setInputAlphabet({a, b});
-	m2.setStates({q1b, q2b});
-	m2.addTransition(q1b, b, q2b);
-	m2.addTransition(q2b, b, q2b);
-	m2.addFinalState(q2b);
+		m1.setInputAlphabet({a, b});
+		m1.setStates({q1a, q2a, q0a});
+		m1.addTransition(q1a, a, q2a);
+		m1.addTransition(q1a, b, q0a);
+		m1.addTransition(q2a, a, q2a);
+		m1.addTransition(q2a, b, q0a);
+		m1.addTransition(q0a, a, q0a);
+		m1.addTransition(q0a, b, q0a);
+		m1.addFinalState(q2a);
 
-	m3.setInputAlphabet({a, b});
-	m3.setStates({q1a, q1b, q2a, q2b, q0a, q0b, q0102});
-	m3.addTransition(q1a, a, q2a);
-	m3.addTransition(q1a, a, q1b);
-	m3.addTransition(q1a, b, q0a);
-	m3.addTransition(q2a, a, q2a);
-	m3.addTransition(q2a, a, q1b);
-	m3.addTransition(q2a, b, q0a);
-	m3.addTransition(q0a, a, q0a);
-	m3.addTransition(q0a, b, q0a);
-	m3.addTransition(q1b, a, q0b);
-	m3.addTransition(q1b, b, q2b);
-	m3.addTransition(q2b, a, q0b);
-	m3.addTransition(q2b, b, q2b);
-	m3.addTransition(q0b, a, q0b);
-	m3.addTransition(q0b, b, q0b);
-	m3.setFinalStates({q2b});
+		m2.setInputAlphabet({a, b});
+		m2.setStates({q1b, q2b});
+		m2.addTransition(q1b, b, q2b);
+		m2.addTransition(q2b, b, q2b);
+		m2.addFinalState(q2b);
 
-	auto u11 = automaton::transform::AutomataConcatenationEpsilonTransition::concatenation(automaton::NFA<>(automaton::DFA<>(m1)), automaton::NFA < > (m2));
-	auto u12 = automaton::transform::AutomataConcatenationEpsilonTransition::concatenation(automaton::DFA<>(m1), automaton::DFA<>(m2));
-	auto u21 = automaton::transform::AutomataConcatenation::concatenation(automaton::NFA<>(automaton::DFA<>(m1)), automaton::NFA < > (m2));
-	auto u22 = automaton::transform::AutomataConcatenation::concatenation(automaton::DFA<>(m1), automaton::DFA<>(m2));
+		m3.setInputAlphabet({a, b});
+		m3.setStates({q1a, q1b, q2a, q2b, q0a, q0b, q0102});
+		m3.addTransition(q1a, a, q2a);
+		m3.addTransition(q1a, a, q1b);
+		m3.addTransition(q1a, b, q0a);
+		m3.addTransition(q2a, a, q2a);
+		m3.addTransition(q2a, a, q1b);
+		m3.addTransition(q2a, b, q0a);
+		m3.addTransition(q0a, a, q0a);
+		m3.addTransition(q0a, b, q0a);
+		m3.addTransition(q1b, a, q0b);
+		m3.addTransition(q1b, b, q2b);
+		m3.addTransition(q2b, a, q0b);
+		m3.addTransition(q2b, b, q2b);
+		m3.addTransition(q0b, a, q0b);
+		m3.addTransition(q0b, b, q0b);
+		m3.setFinalStates({q2b});
 
-	automaton::DFA < DefaultSymbolType, unsigned > umdfa (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(m3)))));
-	automaton::DFA < DefaultSymbolType, unsigned > umdfa11(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u11)))));
-	automaton::DFA < DefaultSymbolType, unsigned > umdfa12(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u12)))));
-	automaton::DFA < DefaultSymbolType, unsigned > umdfa21(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u21)))));
-	automaton::DFA < DefaultSymbolType, unsigned > umdfa22(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u22)))));
+		auto u11 = automaton::transform::AutomataConcatenationEpsilonTransition::concatenation(automaton::NFA<>(automaton::DFA<>(m1)), automaton::NFA < > (m2));
+		auto u12 = automaton::transform::AutomataConcatenationEpsilonTransition::concatenation(automaton::DFA<>(m1), automaton::DFA<>(m2));
+		auto u21 = automaton::transform::AutomataConcatenation::concatenation(automaton::NFA<>(automaton::DFA<>(m1)), automaton::NFA < > (m2));
+		auto u22 = automaton::transform::AutomataConcatenation::concatenation(automaton::DFA<>(m1), automaton::DFA<>(m2));
 
-	CPPUNIT_ASSERT(umdfa11 == umdfa);
-	CPPUNIT_ASSERT(umdfa12 == umdfa);
-	CPPUNIT_ASSERT(umdfa21 == umdfa);
-	CPPUNIT_ASSERT(umdfa22 == umdfa);
+		automaton::DFA < DefaultSymbolType, unsigned > umdfa (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(m3)))));
+		automaton::DFA < DefaultSymbolType, unsigned > umdfa11(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u11)))));
+		automaton::DFA < DefaultSymbolType, unsigned > umdfa12(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u12)))));
+		automaton::DFA < DefaultSymbolType, unsigned > umdfa21(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u21)))));
+		automaton::DFA < DefaultSymbolType, unsigned > umdfa22(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u22)))));
 
+		CHECK(umdfa11 == umdfa);
+		CHECK(umdfa12 == umdfa);
+		CHECK(umdfa21 == umdfa);
+		CHECK(umdfa22 == umdfa);
+	}
 }
diff --git a/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.h b/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.h
deleted file mode 100644
index aa7dbecb20..0000000000
--- a/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef AUTOMATA_CONCAT_TEST_H_
-#define AUTOMATA_CONCAT_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class AutomataConcatenationTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( AutomataConcatenationTest );
-  CPPUNIT_TEST( testAutomataConcatenation );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testAutomataConcatenation();
-};
-
-#endif /* AUTOMATA_CONCAT_TEST_H_ */
diff --git a/alib2algo/test-src/automaton/transform/AutomataUnionTest.cpp b/alib2algo/test-src/automaton/transform/AutomataUnionTest.cpp
index ee38f8eab0..6e3a23fe21 100644
--- a/alib2algo/test-src/automaton/transform/AutomataUnionTest.cpp
+++ b/alib2algo/test-src/automaton/transform/AutomataUnionTest.cpp
@@ -1,5 +1,6 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "AutomataUnionTest.h"
 
 #include "automaton/transform/AutomataUnionCartesianProduct.h"
 #include "automaton/transform/AutomataUnionEpsilonTransition.h"
@@ -12,16 +13,8 @@
 
 #include <exception/CommonException.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AutomataUnionTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( AutomataUnionTest );
-
-void AutomataUnionTest::setUp() {
-}
-
-void AutomataUnionTest::tearDown() {
-}
-
-void AutomataUnionTest::testAutomataUnion() {
+TEST_CASE ( "Automata Union", "[unit][algo][automaton][transform]" ) {
+	SECTION ( "NFA/DFA" ) {
 	// based on Melichar, 2.72
 
 	DefaultStateType q1a = DefaultStateType("1");
@@ -69,15 +62,15 @@ void AutomataUnionTest::testAutomataUnion() {
 	m3.setFinalStates({q20, q02});
 
 	auto u1 = automaton::transform::AutomataUnionEpsilonTransition::unification(m1, m2);
-	CPPUNIT_ASSERT_THROW(automaton::transform::AutomataUnionCartesianProduct::unification(m1, m2), exception::CommonException);
-	CPPUNIT_ASSERT_THROW(automaton::transform::AutomataUnionCartesianProduct::unification(automaton::NFA < > (m1), automaton::NFA < > ( m2 )), exception::CommonException);
+	CHECK_THROWS_AS(automaton::transform::AutomataUnionCartesianProduct::unification(m1, m2), exception::CommonException);
+	CHECK_THROWS_AS(automaton::transform::AutomataUnionCartesianProduct::unification(automaton::NFA < > (m1), automaton::NFA < > ( m2 )), exception::CommonException);
 	auto u2 = automaton::transform::AutomataUnionEpsilonTransition::unification(automaton::simplify::Total::total(m1), automaton::simplify::Total::total(m2));
 
 	auto umdfa(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(m3)))));
 	auto umdfa1(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u1)))));
 	auto umdfa2(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(u2)))));
 
-	CPPUNIT_ASSERT(umdfa1 == umdfa);
-	CPPUNIT_ASSERT(umdfa2 == umdfa);
-
+	CHECK(umdfa1 == umdfa);
+	CHECK(umdfa2 == umdfa);
+}
 }
diff --git a/alib2algo/test-src/automaton/transform/AutomataUnionTest.h b/alib2algo/test-src/automaton/transform/AutomataUnionTest.h
deleted file mode 100644
index d45ef404d8..0000000000
--- a/alib2algo/test-src/automaton/transform/AutomataUnionTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef AUTOMATA_UNION_TEST_H_
-#define AUTOMATA_UNION_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class AutomataUnionTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( AutomataUnionTest );
-  CPPUNIT_TEST( testAutomataUnion );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testAutomataUnion();
-};
-
-#endif /* AUTOMATA_UNION_TEST_H_ */
diff --git a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp
index 31e6d3d326..b02ab93fe0 100644
--- a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp
+++ b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp
@@ -1,5 +1,6 @@
+#include <catch2/catch.hpp>
+
 #include <alib/list>
-#include "AutomatonIterationTest.h"
 
 #include "automaton/transform/AutomatonIteration.h"
 #include "automaton/transform/AutomatonIterationEpsilonTransition.h"
@@ -11,54 +12,46 @@
 #include "automaton/simplify/Total.h"
 #include "automaton/determinize/Determinize.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( AutomatonIterationTest, "automaton" );
-CPPUNIT_TEST_SUITE_REGISTRATION( AutomatonIterationTest );
-
-void AutomatonIterationTest::setUp() {
-}
-
-void AutomatonIterationTest::tearDown() {
-}
-
-void AutomatonIterationTest::testAutomatonIteration() {
-
-	// Melichar 2.83
-	DefaultStateType q0 = DefaultStateType(0);
-	DefaultStateType q1 = DefaultStateType(1);
-	DefaultStateType q2 = DefaultStateType(2);
-	DefaultStateType q3 = DefaultStateType(3);
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	automaton::DFA < > m1(q1);
-	m1.setStates({q1, q2, q3});
-	m1.addFinalState(q3);
-	m1.setInputAlphabet({a, b});
-	m1.addTransition(q1, a, q2);
-	m1.addTransition(q2, b, q2);
-	m1.addTransition(q2, a, q3);
-	m1.addTransition(q3, a, q1);
-
-	automaton::EpsilonNFA < > res(q0);
-	res.setStates({q0, q1, q2, q3});
-	res.setInputAlphabet({a, b});
-	res.setFinalStates({q0, q3});
-
-	res.addTransition(q1, a, q2);
-	res.addTransition(q2, b, q2);
-	res.addTransition(q2, a, q3);
-	res.addTransition(q3, a, q1);
-
-	res.addTransition(q0, q1);
-	res.addTransition(q3, q1);
-
-	auto i2 = automaton::transform::AutomatonIterationEpsilonTransition::iteration(m1);
-	auto i1 = automaton::transform::AutomatonIteration::iteration(m1);
-
-	auto mdfa1 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(i1)))));
-	auto mdfa2 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(i2)))));
-	auto mdfa3 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(res)))));
-
-	CPPUNIT_ASSERT(mdfa1 == mdfa2);
-	CPPUNIT_ASSERT(mdfa1 == mdfa3);
+TEST_CASE ( "Automata Iteration", "[unit][algo][automaton][transform]" ) {
+	SECTION ( "NFA/DFA" ) {
+		// Melichar 2.83
+		DefaultStateType q0 = DefaultStateType(0);
+		DefaultStateType q1 = DefaultStateType(1);
+		DefaultStateType q2 = DefaultStateType(2);
+		DefaultStateType q3 = DefaultStateType(3);
+		DefaultSymbolType a = DefaultSymbolType('a');
+		DefaultSymbolType b = DefaultSymbolType('b');
+
+		automaton::DFA < > m1(q1);
+		m1.setStates({q1, q2, q3});
+		m1.addFinalState(q3);
+		m1.setInputAlphabet({a, b});
+		m1.addTransition(q1, a, q2);
+		m1.addTransition(q2, b, q2);
+		m1.addTransition(q2, a, q3);
+		m1.addTransition(q3, a, q1);
+
+		automaton::EpsilonNFA < > res(q0);
+		res.setStates({q0, q1, q2, q3});
+		res.setInputAlphabet({a, b});
+		res.setFinalStates({q0, q3});
+
+		res.addTransition(q1, a, q2);
+		res.addTransition(q2, b, q2);
+		res.addTransition(q2, a, q3);
+		res.addTransition(q3, a, q1);
+
+		res.addTransition(q0, q1);
+		res.addTransition(q3, q1);
+
+		auto i2 = automaton::transform::AutomatonIterationEpsilonTransition::iteration(m1);
+		auto i1 = automaton::transform::AutomatonIteration::iteration(m1);
+
+		auto mdfa1 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(i1)))));
+		auto mdfa2 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(i2)))));
+		auto mdfa3 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemoverIncoming::remove(res)))));
+
+		CHECK(mdfa1 == mdfa2);
+		CHECK(mdfa1 == mdfa3);
+	}
 }
diff --git a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.h b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.h
deleted file mode 100644
index 28119050ac..0000000000
--- a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef AUTOMATA_ITER_TEST_H_
-#define AUTOMATA_ITER_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class AutomatonIterationTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( AutomatonIterationTest );
-  CPPUNIT_TEST( testAutomatonIteration );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testAutomatonIteration();
-};
-
-#endif /* AUTOMATA_ITER_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.cpp b/alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.cpp
index cb6b6bcaa1..e8788ae261 100644
--- a/alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.cpp
+++ b/alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.cpp
@@ -1,4 +1,4 @@
-#include "GrammarCFGtoPDATest.h"
+#include <catch2/catch.hpp>
 
 #include <alphabet/BottomOfTheStackSymbol.h>
 #include <grammar/ContextFree/CFG.h>
@@ -11,18 +11,8 @@
 #include <label/InitialStateLabel.h>
 #include <label/FinalStateLabel.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarCFGtoPDATest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarCFGtoPDATest );
-
-void GrammarCFGtoPDATest::setUp() {
-}
-
-void GrammarCFGtoPDATest::tearDown() {
-}
-
-void GrammarCFGtoPDATest::testTopDown()
-{
-	{
+TEST_CASE ( "CFG to PDA", "[unit][algo][grammar][convert]" ) {
+	SECTION ( "Top down" ) {
 		std::string nE = "E";
 		std::string nT = "T";
 		std::string nF = "F";
@@ -59,13 +49,10 @@ void GrammarCFGtoPDATest::testTopDown()
 		for ( char symbol : pda.getInputAlphabet ( ) )
 			pda.addTransition ( q, symbol, ext::vector<ext::variant < char, std::string >>{symbol}, q, ext::vector<ext::variant < char, std::string >>{});
 
-		CPPUNIT_ASSERT(pda == grammar::convert::ToAutomaton::convert(grammar));
+		CHECK (pda == grammar::convert::ToAutomaton::convert(grammar));
 	}
-}
 
-void GrammarCFGtoPDATest::testBottomUp()
-{
-	{
+	SECTION ( "Bottom up" ) {
 		DefaultSymbolType nE = DefaultSymbolType('E');
 		DefaultSymbolType nT = DefaultSymbolType('T');
 		DefaultSymbolType nF = DefaultSymbolType('F');
@@ -109,6 +96,6 @@ void GrammarCFGtoPDATest::testBottomUp()
 
 		pda.addTransition(q, ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > >{bots, nE}, r, ext::vector < ext::variant < DefaultSymbolType, DefaultSymbolType > >{});
 
-		CPPUNIT_ASSERT(pda == grammar::convert::ToAutomatonBottomUp::convert(grammar));
+		CHECK (pda == grammar::convert::ToAutomatonBottomUp::convert(grammar));
 	}
 }
diff --git a/alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.h b/alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.h
deleted file mode 100644
index 21164e6062..0000000000
--- a/alib2algo/test-src/grammar/convert/GrammarCFGtoPDATest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef GRAMMAR_CFG_TO_PDA_TEST_H_
-#define GRAMMAR_CFG_TO_PDA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarCFGtoPDATest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarCFGtoPDATest );
-  CPPUNIT_TEST( testBottomUp );
-  CPPUNIT_TEST( testTopDown );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testBottomUp();
-  void testTopDown();
-};
-
-#endif /* GRAMMAR_CFG_TO_PDA_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/convert/rg2rgTest.cpp b/alib2algo/test-src/grammar/convert/rg2rgTest.cpp
new file mode 100644
index 0000000000..aaa83a5605
--- /dev/null
+++ b/alib2algo/test-src/grammar/convert/rg2rgTest.cpp
@@ -0,0 +1,69 @@
+#include <catch2/catch.hpp>
+
+#include "grammar/convert/ToGrammarLeftRG.h"
+#include "grammar/convert/ToGrammarRightRG.h"
+
+TEST_CASE ( "Left <-> Right Regular Grammar", "[unit][algo][grammar][convert]" ) {
+	SECTION ( "Right to left" ) {
+		grammar::RightRG < > rrGrammar(DefaultSymbolType(1));
+
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(1));
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(2));
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(3));
+		rrGrammar.addTerminalSymbol(DefaultSymbolType("a"));
+		rrGrammar.addTerminalSymbol(DefaultSymbolType("b"));
+
+		rrGrammar.addRule(DefaultSymbolType(1), ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(2)));
+		rrGrammar.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(3)));
+		rrGrammar.addRule(DefaultSymbolType(3), DefaultSymbolType("a"));
+
+		grammar::LeftRG < > lrGrammar = grammar::convert::ToGrammarLeftRG::convert(rrGrammar);
+
+		DefaultSymbolType four ( object::AnyObject < int > ( 1, 1 ) );
+		grammar::LeftRG < > lrGrammarRef ( four );
+
+		lrGrammarRef.addNonterminalSymbol(DefaultSymbolType(1));
+		lrGrammarRef.addNonterminalSymbol(DefaultSymbolType(2));
+		lrGrammarRef.addNonterminalSymbol(DefaultSymbolType(3));
+		lrGrammarRef.addTerminalSymbol(DefaultSymbolType("a"));
+		lrGrammarRef.addTerminalSymbol(DefaultSymbolType("b"));
+
+		lrGrammarRef.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType(1), DefaultSymbolType("a")));
+		lrGrammarRef.addRule(DefaultSymbolType(2), DefaultSymbolType("a"));
+		lrGrammarRef.addRule(DefaultSymbolType(3), ext::make_pair(DefaultSymbolType(2), DefaultSymbolType("b")));
+		lrGrammarRef.addRule(four, ext::make_pair(DefaultSymbolType(3), DefaultSymbolType("a")));
+
+		CHECK(lrGrammarRef == lrGrammar);
+	}
+	SECTION ( "Left to right" ) {
+		grammar::LeftRG < > lrGrammar(DefaultSymbolType(4));
+
+		lrGrammar.addNonterminalSymbol(DefaultSymbolType(2));
+		lrGrammar.addNonterminalSymbol(DefaultSymbolType(3));
+		lrGrammar.addNonterminalSymbol(DefaultSymbolType(4));
+		lrGrammar.addTerminalSymbol(DefaultSymbolType("a"));
+		lrGrammar.addTerminalSymbol(DefaultSymbolType("b"));
+
+		lrGrammar.addRule(DefaultSymbolType(2), DefaultSymbolType("a"));
+		lrGrammar.addRule(DefaultSymbolType(3), ext::make_pair(DefaultSymbolType(2), DefaultSymbolType("b")));
+		lrGrammar.addRule(DefaultSymbolType(4), ext::make_pair(DefaultSymbolType(3), DefaultSymbolType("a")));
+
+		grammar::RightRG < > rrGrammar = grammar::convert::ToGrammarRightRG::convert(lrGrammar);
+
+		DefaultSymbolType five ( object::AnyObject < int > ( 4, 1 ) );
+		grammar::RightRG < > rrGrammarRef ( five );
+
+		rrGrammarRef.addNonterminalSymbol(DefaultSymbolType(2));
+		rrGrammarRef.addNonterminalSymbol(DefaultSymbolType(3));
+		rrGrammarRef.addNonterminalSymbol(DefaultSymbolType(4));
+		rrGrammarRef.addTerminalSymbol(DefaultSymbolType("a"));
+		rrGrammarRef.addTerminalSymbol(DefaultSymbolType("b"));
+
+		rrGrammarRef.addRule(five, ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(2)));
+		rrGrammarRef.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(3)));
+		rrGrammarRef.addRule(DefaultSymbolType(3), DefaultSymbolType("a"));
+		rrGrammarRef.addRule(DefaultSymbolType(3), ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(4)));
+
+		CHECK(rrGrammarRef == rrGrammar);
+	}
+}
diff --git a/alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.cpp b/alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.cpp
index 76ac22a25b..5f00c06f64 100644
--- a/alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.cpp
+++ b/alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.cpp
@@ -1,4 +1,4 @@
-#include "GrammarGenerateUpToLength.h"
+#include <catch2/catch.hpp>
 
 #include <grammar/generate/GenerateUpToLength.h>
 
@@ -8,16 +8,7 @@
 
 #include <factory/StringDataFactory.hpp>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarGenerateUpToLength, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarGenerateUpToLength );
-
-void GrammarGenerateUpToLength::setUp() {
-}
-
-void GrammarGenerateUpToLength::tearDown() {
-}
-
-unsigned countStrings ( const ext::trie < DefaultSymbolType, bool > & node ) {
+static unsigned countStrings ( const ext::trie < DefaultSymbolType, bool > & node ) {
 	unsigned res = node.getData ( );
 
 	for ( const auto & child : node.getChildren ( ) )
@@ -26,179 +17,184 @@ unsigned countStrings ( const ext::trie < DefaultSymbolType, bool > & node ) {
 	return res;
 }
 
-void GrammarGenerateUpToLength::testGenerate1() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b});
-	grammar1.setGeneratesEpsilon(false);
-
-	ext::set<string::LinearString < >> strings;
-
-	ext::trie < DefaultSymbolType, bool > generated = grammar::generate::GenerateUpToLength::generate(grammar1, 5);
-
-	generated.nicePrint ( std::cout );
-	std::cout << std::endl;
-
-	for(const string::LinearString < > & str : strings) {
-		bool flag = true;
-		ext::trie < DefaultSymbolType, bool > * node = & generated;
-		for ( const DefaultSymbolType & symbol : str.getContent ( ) ) {
-			auto iter = node->getChildren ( ).find ( symbol );
-			if ( iter == node->getChildren ( ).end ( ) ) {
-				flag = false;
-				break;
+TEST_CASE ( "Generate Up To", "[unit][algo][grammar][generate]" ) {
+	SECTION ( "Test eps-free CFG" ) {
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b});
+			grammar1.setGeneratesEpsilon(false);
+
+			ext::set<string::LinearString < >> strings;
+
+			ext::trie < DefaultSymbolType, bool > generated = grammar::generate::GenerateUpToLength::generate(grammar1, 5);
+
+			std::ostringstream oss;
+			generated.nicePrint ( oss );
+			CAPTURE ( oss.str ( ) );
+
+			for(const string::LinearString < > & str : strings) {
+				bool flag = true;
+				ext::trie < DefaultSymbolType, bool > * node = & generated;
+				for ( const DefaultSymbolType & symbol : str.getContent ( ) ) {
+					auto iter = node->getChildren ( ).find ( symbol );
+					if ( iter == node->getChildren ( ).end ( ) ) {
+						flag = false;
+						break;
+					}
+					node = & iter->second;
+				}
+
+				CAPTURE ( factory::StringDataFactory::toString ( str ) );
+				CHECK ( ( flag && node->getData ( ) == true ) );
 			}
-			node = & iter->second;
-		}
-
-		CPPUNIT_ASSERT ( flag && node->getData ( ) == true );
-		std::cout << factory::StringDataFactory::toString ( str ) << std::endl;
-	}
-
-	CPPUNIT_ASSERT(strings.size ( ) == countStrings ( generated ) );
-}
 
-void GrammarGenerateUpToLength::testGenerate2() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-	DefaultSymbolType d = DefaultSymbolType('d');
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c, d});
-	grammar1.addRule(S, {A, D});
-	grammar1.addRule(S, {A});
-	grammar1.addRule(S, {D});
-	grammar1.addRule(A, {a, A, d});
-	grammar1.addRule(A, {a, d});
-	grammar1.addRule(A, {B, C});
-	grammar1.addRule(A, {B});
-	grammar1.addRule(A, {C});
-	grammar1.addRule(B, {b, B, c});
-	grammar1.addRule(B, {b, c});
-	grammar1.addRule(C, {c, C});
-	grammar1.addRule(C, {c});
-	grammar1.addRule(D, {d, D});
-	grammar1.addRule(D, {d});
-	grammar1.setGeneratesEpsilon(true);
-
-	ext::set<string::LinearString < >> strings;
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c, c}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c, c}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, c, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c, d}));
-
-	ext::trie < DefaultSymbolType, bool > generated = grammar::generate::GenerateUpToLength::generate(grammar1, 3);
-
-	generated.nicePrint ( std::cout );
-	std::cout << std::endl;
-
-	for(const string::LinearString < > & str : strings) {
-		bool flag = true;
-		ext::trie < DefaultSymbolType, bool > * node = & generated;
-		for ( const DefaultSymbolType & symbol : str.getContent ( ) ) {
-			auto iter = node->getChildren ( ).find ( symbol );
-			if ( iter == node->getChildren ( ).end ( ) ) {
-				flag = false;
-				break;
-			}
-			node = & iter->second;
+			CHECK (strings.size ( ) == countStrings ( generated ) );
 		}
-
-		CPPUNIT_ASSERT ( flag && node->getData ( ) == true );
-		std::cout << factory::StringDataFactory::toString ( str ) << std::endl;
-	}
-
-	CPPUNIT_ASSERT(strings.size ( ) == countStrings ( generated ) );
-}
-
-void GrammarGenerateUpToLength::testGenerate3() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-	DefaultSymbolType d = DefaultSymbolType('d');
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c, d});
-	grammar1.addRule(S, {A, D});
-	grammar1.addRule(S, {D});
-	grammar1.addRule(A, {a, A, d});
-	grammar1.addRule(A, {a, d});
-	grammar1.addRule(A, {B, C});
-	grammar1.addRule(A, {B});
-	grammar1.addRule(A, {C});
-	grammar1.addRule(B, {b, B, c});
-	grammar1.addRule(B, {b, c});
-	grammar1.addRule(C, {c, C});
-	grammar1.addRule(C, {c});
-	grammar1.addRule(D, {d, D});
-	grammar1.addRule(D, {d});
-
-	ext::set<string::LinearString < >> strings;
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d, d}));
-	strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c, d}));
-
-	ext::trie < DefaultSymbolType, bool > generated = grammar::generate::GenerateUpToLength::generate(grammar1, 3);
-
-	generated.nicePrint ( std::cout );
-	std::cout << std::endl;
-
-	for(const string::LinearString < > & str : strings) {
-		bool flag = true;
-		ext::trie < DefaultSymbolType, bool > * node = & generated;
-		for ( const DefaultSymbolType & symbol : str.getContent ( ) ) {
-			auto iter = node->getChildren ( ).find ( symbol );
-			if ( iter == node->getChildren ( ).end ( ) ) {
-				flag = false;
-				break;
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+			DefaultSymbolType d = DefaultSymbolType('d');
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c, d});
+			grammar1.addRule(S, {A, D});
+			grammar1.addRule(S, {A});
+			grammar1.addRule(S, {D});
+			grammar1.addRule(A, {a, A, d});
+			grammar1.addRule(A, {a, d});
+			grammar1.addRule(A, {B, C});
+			grammar1.addRule(A, {B});
+			grammar1.addRule(A, {C});
+			grammar1.addRule(B, {b, B, c});
+			grammar1.addRule(B, {b, c});
+			grammar1.addRule(C, {c, C});
+			grammar1.addRule(C, {c});
+			grammar1.addRule(D, {d, D});
+			grammar1.addRule(D, {d});
+			grammar1.setGeneratesEpsilon(true);
+
+			ext::set<string::LinearString < >> strings;
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c, c}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c, c}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, c, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c, d}));
+
+			ext::trie < DefaultSymbolType, bool > generated = grammar::generate::GenerateUpToLength::generate(grammar1, 3);
+
+			std::ostringstream oss;
+			generated.nicePrint ( oss );
+			CAPTURE ( oss.str ( ) );
+
+			for(const string::LinearString < > & str : strings) {
+				bool flag = true;
+				ext::trie < DefaultSymbolType, bool > * node = & generated;
+				for ( const DefaultSymbolType & symbol : str.getContent ( ) ) {
+					auto iter = node->getChildren ( ).find ( symbol );
+					if ( iter == node->getChildren ( ).end ( ) ) {
+						flag = false;
+						break;
+					}
+					node = & iter->second;
+				}
+
+				CAPTURE ( factory::StringDataFactory::toString ( str ) );
+				CHECK ( ( flag && node->getData ( ) == true ) );
 			}
-			node = & iter->second;
+
+			CHECK (strings.size ( ) == countStrings ( generated ) );
 		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+			DefaultSymbolType d = DefaultSymbolType('d');
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c, d});
+			grammar1.addRule(S, {A, D});
+			grammar1.addRule(S, {D});
+			grammar1.addRule(A, {a, A, d});
+			grammar1.addRule(A, {a, d});
+			grammar1.addRule(A, {B, C});
+			grammar1.addRule(A, {B});
+			grammar1.addRule(A, {C});
+			grammar1.addRule(B, {b, B, c});
+			grammar1.addRule(B, {b, c});
+			grammar1.addRule(C, {c, C});
+			grammar1.addRule(C, {c});
+			grammar1.addRule(D, {d, D});
+			grammar1.addRule(D, {d});
+
+			ext::set<string::LinearString < >> strings;
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{d, d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{a, d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, c, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{c, d, d}));
+			strings.insert(string::LinearString < >(ext::vector<DefaultSymbolType>{b, c, d}));
+
+			ext::trie < DefaultSymbolType, bool > generated = grammar::generate::GenerateUpToLength::generate(grammar1, 3);
+
+			std::ostringstream oss;
+			generated.nicePrint ( oss );
+			CAPTURE ( oss.str ( ) );
+
+			for(const string::LinearString < > & str : strings) {
+				bool flag = true;
+				ext::trie < DefaultSymbolType, bool > * node = & generated;
+				for ( const DefaultSymbolType & symbol : str.getContent ( ) ) {
+					auto iter = node->getChildren ( ).find ( symbol );
+					if ( iter == node->getChildren ( ).end ( ) ) {
+						flag = false;
+						break;
+					}
+					node = & iter->second;
+				}
+
+				CAPTURE ( factory::StringDataFactory::toString ( str ) );
+				CHECK ( ( flag && node->getData ( ) == true ) );
+			}
 
-		CPPUNIT_ASSERT ( flag && node->getData ( ) == true );
-		std::cout << factory::StringDataFactory::toString ( str ) << std::endl;
+			CHECK(strings.size ( ) == countStrings ( generated ) );
+		}
 	}
-
-	CPPUNIT_ASSERT(strings.size ( ) == countStrings ( generated ) );
 }
diff --git a/alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.h b/alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.h
deleted file mode 100644
index bce267fbef..0000000000
--- a/alib2algo/test-src/grammar/generate/GrammarGenerateUpToLength.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef GRAMMAR_GENERATE_UP_TO_LENGTH_TEST_H_
-#define GRAMMAR_GENERATE_UP_TO_LENGTH_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarGenerateUpToLength : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarGenerateUpToLength );
-  CPPUNIT_TEST( testGenerate1 );
-  CPPUNIT_TEST( testGenerate2 );
-  CPPUNIT_TEST( testGenerate3 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testGenerate1();
-  void testGenerate2();
-  void testGenerate3();
-};
-
-#endif /* GRAMMAR_GENERATE_UP_TO_LENGTH_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/properties/GrammarPropertiesTest.cpp b/alib2algo/test-src/grammar/properties/GrammarPropertiesTest.cpp
index 0c8478a7cd..09ed469675 100644
--- a/alib2algo/test-src/grammar/properties/GrammarPropertiesTest.cpp
+++ b/alib2algo/test-src/grammar/properties/GrammarPropertiesTest.cpp
@@ -1,4 +1,4 @@
-#include "GrammarPropertiesTest.h"
+#include <catch2/catch.hpp>
 
 #include <grammar/Grammar.h>
 #include <grammar/ContextFree/CFG.h>
@@ -8,146 +8,138 @@
 #include "grammar/properties/NonterminalUnitRuleCycle.h"
 #include "grammar/properties/RecursiveNonterminal.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarPropertiesTest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarPropertiesTest );
-
-void GrammarPropertiesTest::setUp() {
-}
-
-void GrammarPropertiesTest::tearDown() {
-}
-
-void GrammarPropertiesTest::testNullable() {
-	DefaultSymbolType X = DefaultSymbolType('X');
-	DefaultSymbolType Y = DefaultSymbolType('Y');
-	DefaultSymbolType Z = DefaultSymbolType('Z');
-	DefaultSymbolType d = DefaultSymbolType('d');
-
-	grammar::CFG < > grammar(X);
-	grammar.setTerminalAlphabet({d});
-	grammar.setNonterminalAlphabet({{X, Y, Z}});
-	grammar.setInitialSymbol(X);
-
-	grammar.addRule(X, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ d });
-	grammar.addRule(X, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ Y });
-	grammar.addRule(Y, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ d });
-	grammar.addRule(Y, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ });
-	grammar.addRule(Z, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ d });
-	grammar.addRule(Z, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ X, Y, Z });
-
-	ext::set<DefaultSymbolType> res = {X, Y};
-	CPPUNIT_ASSERT(res == grammar::properties::NullableNonterminals::getNullableNonterminals(grammar));
-}
-
-void GrammarPropertiesTest::testUnitRules() {
-	DefaultSymbolType S = DefaultSymbolType('S');
-	DefaultSymbolType A = DefaultSymbolType('A');
-	DefaultSymbolType B = DefaultSymbolType('B');
-	DefaultSymbolType C = DefaultSymbolType('C');
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	grammar::LeftLG < > llg(S);
-	llg.setTerminalAlphabet({a, b});
-	llg.setNonterminalAlphabet({S, A, B, C});
-	llg.setInitialSymbol(S);
-
-	llg.addRule(S, ext::make_pair(A, ext::vector<DefaultSymbolType>{}));
-	llg.addRule(S, ext::make_pair(B, ext::vector<DefaultSymbolType>{}));
-	llg.addRule(A, ext::make_pair(A, ext::vector<DefaultSymbolType>{a}));
-	llg.addRule(A, ext::make_pair(B, ext::vector<DefaultSymbolType>{}));
-	llg.addRule(A, ext::make_pair(C, ext::vector<DefaultSymbolType>{}));
-	llg.addRule(B, ext::make_pair(B, ext::vector<DefaultSymbolType>{b, a}));
-	llg.addRule(B, ext::make_pair(C, ext::vector<DefaultSymbolType>{b}));
-	llg.addRule(C, {b});
-	llg.addRule(C, ext::make_pair(C, ext::vector<DefaultSymbolType>{a}));
-
-	ext::set<DefaultSymbolType> N_S = {S, A, B, C};
-	ext::set<DefaultSymbolType> N_A = {A, B, C};
-	ext::set<DefaultSymbolType> N_B = {B};
-	ext::set<DefaultSymbolType> N_C = {C};
-
-	CPPUNIT_ASSERT(N_S == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, S));
-	CPPUNIT_ASSERT(N_A == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, A));
-	CPPUNIT_ASSERT(N_B == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, B));
-	CPPUNIT_ASSERT(N_C == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, C));
-}
-
-void GrammarPropertiesTest::testRecursive() {
-	{
-		DefaultSymbolType A = DefaultSymbolType('A');
-		DefaultSymbolType B = DefaultSymbolType('B');
-		DefaultSymbolType C = DefaultSymbolType('C');
-		DefaultSymbolType D = DefaultSymbolType('D');
-
-		DefaultSymbolType a = DefaultSymbolType('a');
-		DefaultSymbolType b = DefaultSymbolType('b');
-
-		grammar::CFG < > cfg(A);
-		cfg.setTerminalAlphabet({a, b});
-		cfg.setNonterminalAlphabet({A, B, C, D});
-		cfg.setInitialSymbol(A);
-
-		cfg.addRule(A, {B});
-		cfg.addRule(B, {C});
-		cfg.addRule(C, {D});
-		cfg.addRule(D, {A});
-		cfg.addRule(D, {});
-
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, A));
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, B));
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, C));
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, D));
+TEST_CASE ( "Grammar properties", "[unit][algo][grammar][properties]" ) {
+	SECTION ( "Test Nullable" ) {
+		DefaultSymbolType X = DefaultSymbolType('X');
+		DefaultSymbolType Y = DefaultSymbolType('Y');
+		DefaultSymbolType Z = DefaultSymbolType('Z');
+		DefaultSymbolType d = DefaultSymbolType('d');
+
+		grammar::CFG < > grammar(X);
+		grammar.setTerminalAlphabet({d});
+		grammar.setNonterminalAlphabet({{X, Y, Z}});
+		grammar.setInitialSymbol(X);
+
+		grammar.addRule(X, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ d });
+		grammar.addRule(X, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ Y });
+		grammar.addRule(Y, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ d });
+		grammar.addRule(Y, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ });
+		grammar.addRule(Z, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ d });
+		grammar.addRule(Z, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{ X, Y, Z });
+
+		ext::set<DefaultSymbolType> res = {X, Y};
+		CHECK(res == grammar::properties::NullableNonterminals::getNullableNonterminals(grammar));
 	}
-	{
+	SECTION ( "Test Unit rules" ) {
+		DefaultSymbolType S = DefaultSymbolType('S');
 		DefaultSymbolType A = DefaultSymbolType('A');
 		DefaultSymbolType B = DefaultSymbolType('B');
 		DefaultSymbolType C = DefaultSymbolType('C');
-		DefaultSymbolType D = DefaultSymbolType('D');
-
 		DefaultSymbolType a = DefaultSymbolType('a');
 		DefaultSymbolType b = DefaultSymbolType('b');
 
-		grammar::CFG < > cfg(A);
-		cfg.setTerminalAlphabet({a, b});
-		cfg.setNonterminalAlphabet({A, B, C, D});
-		cfg.setInitialSymbol(A);
-
-		cfg.addRule(A, {B});
-		cfg.addRule(B, {C});
-		cfg.addRule(C, {D});
-		cfg.addRule(D, {B});
-		cfg.addRule(D, {});
-
-		CPPUNIT_ASSERT(!grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, A));
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, B));
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, C));
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, D));
+		grammar::LeftLG < > llg(S);
+		llg.setTerminalAlphabet({a, b});
+		llg.setNonterminalAlphabet({S, A, B, C});
+		llg.setInitialSymbol(S);
+
+		llg.addRule(S, ext::make_pair(A, ext::vector<DefaultSymbolType>{}));
+		llg.addRule(S, ext::make_pair(B, ext::vector<DefaultSymbolType>{}));
+		llg.addRule(A, ext::make_pair(A, ext::vector<DefaultSymbolType>{a}));
+		llg.addRule(A, ext::make_pair(B, ext::vector<DefaultSymbolType>{}));
+		llg.addRule(A, ext::make_pair(C, ext::vector<DefaultSymbolType>{}));
+		llg.addRule(B, ext::make_pair(B, ext::vector<DefaultSymbolType>{b, a}));
+		llg.addRule(B, ext::make_pair(C, ext::vector<DefaultSymbolType>{b}));
+		llg.addRule(C, {b});
+		llg.addRule(C, ext::make_pair(C, ext::vector<DefaultSymbolType>{a}));
+
+		ext::set<DefaultSymbolType> N_S = {S, A, B, C};
+		ext::set<DefaultSymbolType> N_A = {A, B, C};
+		ext::set<DefaultSymbolType> N_B = {B};
+		ext::set<DefaultSymbolType> N_C = {C};
+
+		CHECK(N_S == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, S));
+		CHECK(N_A == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, A));
+		CHECK(N_B == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, B));
+		CHECK(N_C == grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(llg, C));
 	}
-	{
-		DefaultSymbolType A = DefaultSymbolType('A');
-		DefaultSymbolType B = DefaultSymbolType('B');
-		DefaultSymbolType C = DefaultSymbolType('C');
-		DefaultSymbolType D = DefaultSymbolType('D');
-
-		DefaultSymbolType a = DefaultSymbolType('a');
-		DefaultSymbolType b = DefaultSymbolType('b');
 
-		grammar::CFG < > cfg(A);
-		cfg.setTerminalAlphabet({a, b});
-		cfg.setNonterminalAlphabet({A, B, C, D});
-		cfg.setInitialSymbol(A);
-
-		cfg.addRule(A, {B});
-		cfg.addRule(B, {C, D, A});
-		cfg.addRule(C, {a});
-		cfg.addRule(C, {});
-		cfg.addRule(D, {b});
-		cfg.addRule(D, {});
-
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, A));
-		CPPUNIT_ASSERT(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, B));
-		CPPUNIT_ASSERT(!grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, C));
-		CPPUNIT_ASSERT(!grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, D));
+	SECTION ( "Test recursive nonterminals" ) {
+		{
+			DefaultSymbolType A = DefaultSymbolType('A');
+			DefaultSymbolType B = DefaultSymbolType('B');
+			DefaultSymbolType C = DefaultSymbolType('C');
+			DefaultSymbolType D = DefaultSymbolType('D');
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::CFG < > cfg(A);
+			cfg.setTerminalAlphabet({a, b});
+			cfg.setNonterminalAlphabet({A, B, C, D});
+			cfg.setInitialSymbol(A);
+
+			cfg.addRule(A, {B});
+			cfg.addRule(B, {C});
+			cfg.addRule(C, {D});
+			cfg.addRule(D, {A});
+			cfg.addRule(D, {});
+
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, A));
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, B));
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, C));
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, D));
+		}
+		{
+			DefaultSymbolType A = DefaultSymbolType('A');
+			DefaultSymbolType B = DefaultSymbolType('B');
+			DefaultSymbolType C = DefaultSymbolType('C');
+			DefaultSymbolType D = DefaultSymbolType('D');
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::CFG < > cfg(A);
+			cfg.setTerminalAlphabet({a, b});
+			cfg.setNonterminalAlphabet({A, B, C, D});
+			cfg.setInitialSymbol(A);
+
+			cfg.addRule(A, {B});
+			cfg.addRule(B, {C});
+			cfg.addRule(C, {D});
+			cfg.addRule(D, {B});
+			cfg.addRule(D, {});
+
+			CHECK(!grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, A));
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, B));
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, C));
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, D));
+		}
+		{
+			DefaultSymbolType A = DefaultSymbolType('A');
+			DefaultSymbolType B = DefaultSymbolType('B');
+			DefaultSymbolType C = DefaultSymbolType('C');
+			DefaultSymbolType D = DefaultSymbolType('D');
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::CFG < > cfg(A);
+			cfg.setTerminalAlphabet({a, b});
+			cfg.setNonterminalAlphabet({A, B, C, D});
+			cfg.setInitialSymbol(A);
+
+			cfg.addRule(A, {B});
+			cfg.addRule(B, {C, D, A});
+			cfg.addRule(C, {a});
+			cfg.addRule(C, {});
+			cfg.addRule(D, {b});
+			cfg.addRule(D, {});
+
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, A));
+			CHECK(grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, B));
+			CHECK(!grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, C));
+			CHECK(!grammar::properties::RecursiveNonterminal::isNonterminalRecursive(cfg, D));
+		}
 	}
 }
diff --git a/alib2algo/test-src/grammar/properties/GrammarPropertiesTest.h b/alib2algo/test-src/grammar/properties/GrammarPropertiesTest.h
deleted file mode 100644
index 554472f62d..0000000000
--- a/alib2algo/test-src/grammar/properties/GrammarPropertiesTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef GRAMMAR_PROPERTIES_TEST_H_
-#define GRAMMAR_PROPERTIES_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarPropertiesTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarPropertiesTest );
-  CPPUNIT_TEST( testUnitRules );
-  CPPUNIT_TEST( testNullable );
-  CPPUNIT_TEST( testRecursive );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testUnitRules();
-  void testNullable();
-  void testRecursive();
-};
-
-#endif /* GRAMMAR_PROPERTIES_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.cpp b/alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.cpp
index 4a7f343798..1dd7384dfa 100644
--- a/alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.cpp
+++ b/alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.cpp
@@ -1,134 +1,127 @@
-#include "GrammarEpsilonRemoverTest.h"
+#include <catch2/catch.hpp>
 
 #include "grammar/simplify/EpsilonRemover.h"
 
 #include "grammar/ContextFree/CFG.h"
 #include "grammar/ContextFree/EpsilonFreeCFG.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarEpsilonRemoverTest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarEpsilonRemoverTest );
-
-void GrammarEpsilonRemoverTest::setUp() {
-}
-
-void GrammarEpsilonRemoverTest::tearDown() {
-}
-
-void GrammarEpsilonRemoverTest::testRemoveEpsilonRules1() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	grammar::CFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b});
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::EpsilonRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D});
-	grammar3.setTerminalAlphabet({a, b});
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarEpsilonRemoverTest::testRemoveEpsilonRules2() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-	DefaultSymbolType d = DefaultSymbolType('d');
-
-	grammar::CFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c, d});
-	grammar1.addRule(S, {A, D});
-	grammar1.addRule(A, {a, A, d});
-	grammar1.addRule(A, {B, C});
-	grammar1.addRule(B, {b, B, c});
-	grammar1.addRule(B, {});
-	grammar1.addRule(C, {c, C});
-	grammar1.addRule(C, {});
-	grammar1.addRule(D, {d, D});
-	grammar1.addRule(D, {});
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::EpsilonRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D});
-	grammar3.setTerminalAlphabet({a, b, c, d});
-	grammar3.addRule(S, {A, D});
-	grammar3.addRule(S, {A});
-	grammar3.addRule(S, {D});
-	grammar3.addRule(A, {a, A, d});
-	grammar3.addRule(A, {a, d});
-	grammar3.addRule(A, {B, C});
-	grammar3.addRule(A, {B});
-	grammar3.addRule(A, {C});
-	grammar3.addRule(B, {b, B, c});
-	grammar3.addRule(B, {b, c});
-	grammar3.addRule(C, {c, C});
-	grammar3.addRule(C, {c});
-	grammar3.addRule(D, {d, D});
-	grammar3.addRule(D, {d});
-	grammar3.setGeneratesEpsilon(true);
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarEpsilonRemoverTest::testRemoveEpsilonRules3() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-	DefaultSymbolType d = DefaultSymbolType('d');
-
-	grammar::CFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c, d});
-	grammar1.addRule(S, {A, D});
-	grammar1.addRule(A, {a, A, d});
-	grammar1.addRule(A, {B, C});
-	grammar1.addRule(B, {b, B, c});
-	grammar1.addRule(B, {});
-	grammar1.addRule(C, {c, C});
-	grammar1.addRule(C, {});
-	grammar1.addRule(D, {d, D});
-	grammar1.addRule(D, {d});
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::EpsilonRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D});
-	grammar3.setTerminalAlphabet({a, b, c, d});
-	grammar3.addRule(S, {A, D});
-	grammar3.addRule(S, {D});
-	grammar3.addRule(A, {a, A, d});
-	grammar3.addRule(A, {a, d});
-	grammar3.addRule(A, {B, C});
-	grammar3.addRule(A, {B});
-	grammar3.addRule(A, {C});
-	grammar3.addRule(B, {b, B, c});
-	grammar3.addRule(B, {b, c});
-	grammar3.addRule(C, {c, C});
-	grammar3.addRule(C, {c});
-	grammar3.addRule(D, {d, D});
-	grammar3.addRule(D, {d});
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
+TEST_CASE ( "Epsilon remover", "[unit][algo][grammar][simplify]" ) {
+	SECTION ( "Test CFG" ) {
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::CFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b});
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::EpsilonRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D});
+			grammar3.setTerminalAlphabet({a, b});
+
+			CHECK (grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+			DefaultSymbolType d = DefaultSymbolType('d');
+
+			grammar::CFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c, d});
+			grammar1.addRule(S, {A, D});
+			grammar1.addRule(A, {a, A, d});
+			grammar1.addRule(A, {B, C});
+			grammar1.addRule(B, {b, B, c});
+			grammar1.addRule(B, {});
+			grammar1.addRule(C, {c, C});
+			grammar1.addRule(C, {});
+			grammar1.addRule(D, {d, D});
+			grammar1.addRule(D, {});
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::EpsilonRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D});
+			grammar3.setTerminalAlphabet({a, b, c, d});
+			grammar3.addRule(S, {A, D});
+			grammar3.addRule(S, {A});
+			grammar3.addRule(S, {D});
+			grammar3.addRule(A, {a, A, d});
+			grammar3.addRule(A, {a, d});
+			grammar3.addRule(A, {B, C});
+			grammar3.addRule(A, {B});
+			grammar3.addRule(A, {C});
+			grammar3.addRule(B, {b, B, c});
+			grammar3.addRule(B, {b, c});
+			grammar3.addRule(C, {c, C});
+			grammar3.addRule(C, {c});
+			grammar3.addRule(D, {d, D});
+			grammar3.addRule(D, {d});
+			grammar3.setGeneratesEpsilon(true);
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+			DefaultSymbolType d = DefaultSymbolType('d');
+
+			grammar::CFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c, d});
+			grammar1.addRule(S, {A, D});
+			grammar1.addRule(A, {a, A, d});
+			grammar1.addRule(A, {B, C});
+			grammar1.addRule(B, {b, B, c});
+			grammar1.addRule(B, {});
+			grammar1.addRule(C, {c, C});
+			grammar1.addRule(C, {});
+			grammar1.addRule(D, {d, D});
+			grammar1.addRule(D, {d});
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::EpsilonRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D});
+			grammar3.setTerminalAlphabet({a, b, c, d});
+			grammar3.addRule(S, {A, D});
+			grammar3.addRule(S, {D});
+			grammar3.addRule(A, {a, A, d});
+			grammar3.addRule(A, {a, d});
+			grammar3.addRule(A, {B, C});
+			grammar3.addRule(A, {B});
+			grammar3.addRule(A, {C});
+			grammar3.addRule(B, {b, B, c});
+			grammar3.addRule(B, {b, c});
+			grammar3.addRule(C, {c, C});
+			grammar3.addRule(C, {c});
+			grammar3.addRule(D, {d, D});
+			grammar3.addRule(D, {d});
+
+			CHECK(grammar2 == grammar3);
+		}
+	}
 }
diff --git a/alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.h b/alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.h
deleted file mode 100644
index b536b53c98..0000000000
--- a/alib2algo/test-src/grammar/simplify/GrammarEpsilonRemoverTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef GRAMMAR_EPSILON_REMOVER_TEST_H_
-#define GRAMMAR_EPSILON_REMOVER_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarEpsilonRemoverTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarEpsilonRemoverTest );
-  CPPUNIT_TEST( testRemoveEpsilonRules1 );
-  CPPUNIT_TEST( testRemoveEpsilonRules2 );
-  CPPUNIT_TEST( testRemoveEpsilonRules3 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testRemoveEpsilonRules1();
-  void testRemoveEpsilonRules2();
-  void testRemoveEpsilonRules3();
-};
-
-#endif /* GRAMMAR_EPSILON_REMOVER_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.cpp b/alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.cpp
index eec5bb9017..ca1373c9b6 100644
--- a/alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.cpp
+++ b/alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.cpp
@@ -1,4 +1,4 @@
-#include "GrammarLeftRecursionRemoverTest.h"
+#include <catch2/catch.hpp>
 
 #include "grammar/simplify/LeftRecursionRemover.h"
 #include "grammar/generate/GenerateUpToLength.h"
@@ -12,202 +12,187 @@
 #include <factory/StringDataFactory.hpp>
 #include <common/createUnique.hpp>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarLeftRecursionRemoverTest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarLeftRecursionRemoverTest );
-
-void GrammarLeftRecursionRemoverTest::setUp() {
-}
-
-void GrammarLeftRecursionRemoverTest::tearDown() {
-}
-
-void GrammarLeftRecursionRemoverTest::testRemoveLefRecursion1() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b});
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D});
-	grammar3.setTerminalAlphabet({a, b});
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarLeftRecursionRemoverTest::testRemoveLefRecursion2() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c});
-	grammar1.addRule(S, {A});
-	grammar1.addRule(A, {A, a});
-	grammar1.addRule(A, {A, b});
-	grammar1.addRule(A, {c});
-
-	DefaultSymbolType Aprimed = common::createUnique(A, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-
-	std::cout << factory::StringDataFactory::toString ( grammar1 ) << std::endl;
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, Aprimed, B, C, D});
-	grammar3.setTerminalAlphabet({a, b, c});
-	grammar3.addRule(S, {c, Aprimed});
-	grammar3.addRule(S, {c});
-	grammar3.addRule(A, {c, Aprimed});
-	grammar3.addRule(A, {c});
-	grammar3.addRule(Aprimed, {a, Aprimed});
-	grammar3.addRule(Aprimed, {a});
-	grammar3.addRule(Aprimed, {b, Aprimed});
-	grammar3.addRule(Aprimed, {b});
-
-	std::cout << factory::StringDataFactory::toString( grammar2 ) << std::endl;
-	std::cout << factory::StringDataFactory::toString( grammar3 ) << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarLeftRecursionRemoverTest::testRemoveLefRecursion3() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C});
-	grammar1.setTerminalAlphabet({a, b, c});
-	grammar1.addRule(S, {A});
-	grammar1.addRule(A, {B, a});
-	grammar1.addRule(B, {A, b});
-	grammar1.addRule(A, {c});
-
-	DefaultSymbolType Bprimed = common::createUnique(B, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-
-	std::cout << factory::StringDataFactory::toString ( grammar1 ) << std::endl;
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, Bprimed, C});
-	grammar3.setTerminalAlphabet({a, b, c});
-	grammar3.addRule(S, {c});
-	grammar3.addRule(S, {c, b, Bprimed, a});
-	grammar3.addRule(S, {c, b, a});
-	grammar3.addRule(A, {B, a});
-	grammar3.addRule(A, {c});
-	grammar3.addRule(B, {c, b});
-	grammar3.addRule(B, {c, b, Bprimed});
-	grammar3.addRule(Bprimed, {a, b, Bprimed});
-	grammar3.addRule(Bprimed, {a, b});
-
-	std::cout << factory::StringDataFactory::toString ( grammar2 ) << std::endl;
-	std::cout << factory::StringDataFactory::toString ( grammar3 ) << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarLeftRecursionRemoverTest::testRemoveLefRecursion4() {
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	grammar::EpsilonFreeCFG < > grammar1(A);
-	grammar1.setNonterminalAlphabet({A, B, C});
-	grammar1.setTerminalAlphabet({a, b});
-	grammar1.addRule(A, {B, C});
-	grammar1.addRule(A, {a});
-	grammar1.addRule(B, {C, A});
-	grammar1.addRule(B, {A, b});
-	grammar1.addRule(C, {A, B});
-	grammar1.addRule(C, {C, C});
-	grammar1.addRule(C, {a});
-
-	DefaultSymbolType Bprimed = common::createUnique(B, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType Cprimed = common::createUnique(C, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-
-	std::cout << factory::StringDataFactory::toString ( grammar1 ) << std::endl;
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(A);
-	grammar3.setNonterminalAlphabet({A, B, Bprimed, C, Cprimed});
-	grammar3.setTerminalAlphabet({a, b});
-	grammar3.addRule(A, {B, C});
-	grammar3.addRule(A, {a});
-	grammar3.addRule(B, {C, A});
-	grammar3.addRule(B, {a, b});
-	grammar3.addRule(B, {C, A, Bprimed});
-	grammar3.addRule(B, {a, b, Bprimed});
-	grammar3.addRule(Bprimed, {C, b, Bprimed});
-	grammar3.addRule(Bprimed, {C, b});
-	grammar3.addRule(C, {a, b, C, B});
-	grammar3.addRule(C, {a, b, Bprimed, C, B});
-	grammar3.addRule(C, {a, B});
-	grammar3.addRule(C, {a});
-	grammar3.addRule(C, {a, b, C, B, Cprimed});
-	grammar3.addRule(C, {a, b, Bprimed, C, B, Cprimed});
-	grammar3.addRule(C, {a, B, Cprimed});
-	grammar3.addRule(C, {a, Cprimed});
-	grammar3.addRule(Cprimed, {A, C, B, Cprimed});
-	grammar3.addRule(Cprimed, {A, Bprimed, C, B, Cprimed});
-	grammar3.addRule(Cprimed, {C, Cprimed});
-	grammar3.addRule(Cprimed, {A, C, B});
-	grammar3.addRule(Cprimed, {A, Bprimed, C, B});
-	grammar3.addRule(Cprimed, {C});
-
-	std::cout << factory::StringDataFactory::toString( grammar2 ) << std::endl;
-	std::cout << factory::StringDataFactory::toString( grammar3 ) << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarLeftRecursionRemoverTest::testRemoveLefRecursion5() {
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	grammar::EpsilonFreeCFG < > grammar1(A);
-	grammar1.setNonterminalAlphabet({A, B, C});
-	grammar1.setTerminalAlphabet({a, b});
-	grammar1.addRule(A, {B, C});
-	grammar1.addRule(A, {a});
-	grammar1.addRule(B, {C, A});
-	grammar1.addRule(B, {A, b});
-	grammar1.addRule(C, {A, B});
-	grammar1.addRule(C, {C, C});
-	grammar1.addRule(C, {a});
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
-
-	CPPUNIT_ASSERT(grammar::generate::GenerateUpToLength::generate(grammar1, 7) == grammar::generate::GenerateUpToLength::generate(grammar2, 7));
+TEST_CASE ( "Left recursion remover", "[unit][algo][grammar][simplify]" ) {
+	SECTION ( "Test eps-free CFG" ) {
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b});
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D});
+			grammar3.setTerminalAlphabet({a, b});
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c});
+			grammar1.addRule(S, {A});
+			grammar1.addRule(A, {A, a});
+			grammar1.addRule(A, {A, b});
+			grammar1.addRule(A, {c});
+
+			DefaultSymbolType Aprimed = common::createUnique(A, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, Aprimed, B, C, D});
+			grammar3.setTerminalAlphabet({a, b, c});
+			grammar3.addRule(S, {c, Aprimed});
+			grammar3.addRule(S, {c});
+			grammar3.addRule(A, {c, Aprimed});
+			grammar3.addRule(A, {c});
+			grammar3.addRule(Aprimed, {a, Aprimed});
+			grammar3.addRule(Aprimed, {a});
+			grammar3.addRule(Aprimed, {b, Aprimed});
+			grammar3.addRule(Aprimed, {b});
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C});
+			grammar1.setTerminalAlphabet({a, b, c});
+			grammar1.addRule(S, {A});
+			grammar1.addRule(A, {B, a});
+			grammar1.addRule(B, {A, b});
+			grammar1.addRule(A, {c});
+
+			DefaultSymbolType Bprimed = common::createUnique(B, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, Bprimed, C});
+			grammar3.setTerminalAlphabet({a, b, c});
+			grammar3.addRule(S, {c});
+			grammar3.addRule(S, {c, b, Bprimed, a});
+			grammar3.addRule(S, {c, b, a});
+			grammar3.addRule(A, {B, a});
+			grammar3.addRule(A, {c});
+			grammar3.addRule(B, {c, b});
+			grammar3.addRule(B, {c, b, Bprimed});
+			grammar3.addRule(Bprimed, {a, b, Bprimed});
+			grammar3.addRule(Bprimed, {a, b});
+
+			CAPTURE ( factory::StringDataFactory::toString( grammar1 ) );
+			CAPTURE ( factory::StringDataFactory::toString( grammar2 ) );
+			CAPTURE ( factory::StringDataFactory::toString( grammar3 ) );
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::EpsilonFreeCFG < > grammar1(A);
+			grammar1.setNonterminalAlphabet({A, B, C});
+			grammar1.setTerminalAlphabet({a, b});
+			grammar1.addRule(A, {B, C});
+			grammar1.addRule(A, {a});
+			grammar1.addRule(B, {C, A});
+			grammar1.addRule(B, {A, b});
+			grammar1.addRule(C, {A, B});
+			grammar1.addRule(C, {C, C});
+			grammar1.addRule(C, {a});
+
+			DefaultSymbolType Bprimed = common::createUnique(B, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType Cprimed = common::createUnique(C, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+			CAPTURE ( factory::StringDataFactory::toString( grammar1 ) );
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(A);
+			grammar3.setNonterminalAlphabet({A, B, Bprimed, C, Cprimed});
+			grammar3.setTerminalAlphabet({a, b});
+			grammar3.addRule(A, {B, C});
+			grammar3.addRule(A, {a});
+			grammar3.addRule(B, {C, A});
+			grammar3.addRule(B, {a, b});
+			grammar3.addRule(B, {C, A, Bprimed});
+			grammar3.addRule(B, {a, b, Bprimed});
+			grammar3.addRule(Bprimed, {C, b, Bprimed});
+			grammar3.addRule(Bprimed, {C, b});
+			grammar3.addRule(C, {a, b, C, B});
+			grammar3.addRule(C, {a, b, Bprimed, C, B});
+			grammar3.addRule(C, {a, B});
+			grammar3.addRule(C, {a});
+			grammar3.addRule(C, {a, b, C, B, Cprimed});
+			grammar3.addRule(C, {a, b, Bprimed, C, B, Cprimed});
+			grammar3.addRule(C, {a, B, Cprimed});
+			grammar3.addRule(C, {a, Cprimed});
+			grammar3.addRule(Cprimed, {A, C, B, Cprimed});
+			grammar3.addRule(Cprimed, {A, Bprimed, C, B, Cprimed});
+			grammar3.addRule(Cprimed, {C, Cprimed});
+			grammar3.addRule(Cprimed, {A, C, B});
+			grammar3.addRule(Cprimed, {A, Bprimed, C, B});
+			grammar3.addRule(Cprimed, {C});
+
+			CAPTURE ( factory::StringDataFactory::toString( grammar2 ) );
+			CAPTURE ( factory::StringDataFactory::toString( grammar3 ) );
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::EpsilonFreeCFG < > grammar1(A);
+			grammar1.setNonterminalAlphabet({A, B, C});
+			grammar1.setTerminalAlphabet({a, b});
+			grammar1.addRule(A, {B, C});
+			grammar1.addRule(A, {a});
+			grammar1.addRule(B, {C, A});
+			grammar1.addRule(B, {A, b});
+			grammar1.addRule(C, {A, B});
+			grammar1.addRule(C, {C, C});
+			grammar1.addRule(C, {a});
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::LeftRecursionRemover::remove(grammar1);
+
+			CHECK(grammar::generate::GenerateUpToLength::generate(grammar1, 7) == grammar::generate::GenerateUpToLength::generate(grammar2, 7));
+		}
+	}
 }
diff --git a/alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.h b/alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.h
deleted file mode 100644
index 8e22bbbdf6..0000000000
--- a/alib2algo/test-src/grammar/simplify/GrammarLeftRecursionRemoverTest.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef GRAMMAR_LEFT_RECURSION_REMOVER_TEST_H_
-#define GRAMMAR_LEFT_RECURSION_REMOVER_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarLeftRecursionRemoverTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarLeftRecursionRemoverTest );
-  CPPUNIT_TEST( testRemoveLefRecursion1 );
-  CPPUNIT_TEST( testRemoveLefRecursion2 );
-  CPPUNIT_TEST( testRemoveLefRecursion3 );
-  CPPUNIT_TEST( testRemoveLefRecursion4 );
-  CPPUNIT_TEST( testRemoveLefRecursion5 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testRemoveLefRecursion1();
-  void testRemoveLefRecursion2();
-  void testRemoveLefRecursion3();
-  void testRemoveLefRecursion4();
-  void testRemoveLefRecursion5();
-};
-
-#endif /* GRAMMAR_LEFT_RECURSION_REMOVER_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.cpp b/alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.cpp
index 6ea9683ca4..d68d7e4e16 100644
--- a/alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.cpp
+++ b/alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.cpp
@@ -1,130 +1,123 @@
-#include "GrammarSimpleRulesRemoverTest.h"
+#include <catch2/catch.hpp>
 
 #include "grammar/simplify/SimpleRulesRemover.h"
 
 #include "grammar/ContextFree/CFG.h"
 #include "grammar/ContextFree/EpsilonFreeCFG.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarSimpleRulesRemoverTest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarSimpleRulesRemoverTest );
-
-void GrammarSimpleRulesRemoverTest::setUp() {
-}
-
-void GrammarSimpleRulesRemoverTest::tearDown() {
-}
-
-void GrammarSimpleRulesRemoverTest::testRemoveSimpleRulesRules1() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-
-	grammar::CFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b});
-
-	grammar::CFG < > grammar2 = grammar::simplify::SimpleRulesRemover::remove(grammar1);
-
-	grammar::CFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D});
-	grammar3.setTerminalAlphabet({a, b});
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarSimpleRulesRemoverTest::testRemoveSimpleRulesRules2() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-	DefaultSymbolType d = DefaultSymbolType('d');
-
-	grammar::CFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c, d});
-	grammar1.addRule(S, {A});
-	grammar1.addRule(A, {a, A, d, D});
-	grammar1.addRule(A, {B});
-	grammar1.addRule(B, {b, B, c, C});
-	grammar1.addRule(B, {});
-	grammar1.addRule(C, {c, C});
-	grammar1.addRule(C, {});
-	grammar1.addRule(D, {d, D});
-	grammar1.addRule(D, {});
-
-	grammar::CFG < > grammar2 = grammar::simplify::SimpleRulesRemover::remove(grammar1);
-
-	grammar::CFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D});
-	grammar3.setTerminalAlphabet({a, b, c, d});
-	grammar3.addRule(S, {a, A, d, D});
-	grammar3.addRule(S, {b, B, c, C});
-	grammar3.addRule(S, {});
-	grammar3.addRule(A, {a, A, d, D});
-	grammar3.addRule(A, {b, B, c, C});
-	grammar3.addRule(A, {});
-	grammar3.addRule(B, {b, B, c, C});
-	grammar3.addRule(B, {});
-	grammar3.addRule(C, {c, C});
-	grammar3.addRule(C, {});
-	grammar3.addRule(D, {d, D});
-	grammar3.addRule(D, {});
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarSimpleRulesRemoverTest::testRemoveSimpleRulesRules3() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType('a');
-	DefaultSymbolType b = DefaultSymbolType('b');
-	DefaultSymbolType c = DefaultSymbolType('c');
-	DefaultSymbolType d = DefaultSymbolType('d');
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c, d});
-	grammar1.addRule(S, {A});
-	grammar1.addRule(A, {a, A, d, D});
-	grammar1.addRule(A, {B});
-	grammar1.addRule(B, {b, B, c, C});
-	grammar1.addRule(B, {c});
-	grammar1.addRule(C, {c, C});
-	grammar1.addRule(C, {b});
-	grammar1.addRule(D, {d, D});
-	grammar1.addRule(D, {a});
-
-	grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::SimpleRulesRemover::remove(grammar1);
-
-	grammar::EpsilonFreeCFG < > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D});
-	grammar3.setTerminalAlphabet({a, b, c, d});
-	grammar3.addRule(S, {a, A, d, D});
-	grammar3.addRule(S, {b, B, c, C});
-	grammar3.addRule(S, {c});
-	grammar3.addRule(A, {a, A, d, D});
-	grammar3.addRule(A, {b, B, c, C});
-	grammar3.addRule(A, {c});
-	grammar3.addRule(B, {b, B, c, C});
-	grammar3.addRule(B, {c});
-	grammar3.addRule(C, {c, C});
-	grammar3.addRule(C, {b});
-	grammar3.addRule(D, {d, D});
-	grammar3.addRule(D, {a});
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
+TEST_CASE ( "Simple rules remover", "[unit][algo][grammar][simplify]" ) {
+	SECTION ( "Test CFG" ) {
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+
+			grammar::CFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b});
+
+			grammar::CFG < > grammar2 = grammar::simplify::SimpleRulesRemover::remove(grammar1);
+
+			grammar::CFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D});
+			grammar3.setTerminalAlphabet({a, b});
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+			DefaultSymbolType d = DefaultSymbolType('d');
+
+			grammar::CFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c, d});
+			grammar1.addRule(S, {A});
+			grammar1.addRule(A, {a, A, d, D});
+			grammar1.addRule(A, {B});
+			grammar1.addRule(B, {b, B, c, C});
+			grammar1.addRule(B, {});
+			grammar1.addRule(C, {c, C});
+			grammar1.addRule(C, {});
+			grammar1.addRule(D, {d, D});
+			grammar1.addRule(D, {});
+
+			grammar::CFG < > grammar2 = grammar::simplify::SimpleRulesRemover::remove(grammar1);
+
+			grammar::CFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D});
+			grammar3.setTerminalAlphabet({a, b, c, d});
+			grammar3.addRule(S, {a, A, d, D});
+			grammar3.addRule(S, {b, B, c, C});
+			grammar3.addRule(S, {});
+			grammar3.addRule(A, {a, A, d, D});
+			grammar3.addRule(A, {b, B, c, C});
+			grammar3.addRule(A, {});
+			grammar3.addRule(B, {b, B, c, C});
+			grammar3.addRule(B, {});
+			grammar3.addRule(C, {c, C});
+			grammar3.addRule(C, {});
+			grammar3.addRule(D, {d, D});
+			grammar3.addRule(D, {});
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType('a');
+			DefaultSymbolType b = DefaultSymbolType('b');
+			DefaultSymbolType c = DefaultSymbolType('c');
+			DefaultSymbolType d = DefaultSymbolType('d');
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c, d});
+			grammar1.addRule(S, {A});
+			grammar1.addRule(A, {a, A, d, D});
+			grammar1.addRule(A, {B});
+			grammar1.addRule(B, {b, B, c, C});
+			grammar1.addRule(B, {c});
+			grammar1.addRule(C, {c, C});
+			grammar1.addRule(C, {b});
+			grammar1.addRule(D, {d, D});
+			grammar1.addRule(D, {a});
+
+			grammar::EpsilonFreeCFG < > grammar2 = grammar::simplify::SimpleRulesRemover::remove(grammar1);
+
+			grammar::EpsilonFreeCFG < > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D});
+			grammar3.setTerminalAlphabet({a, b, c, d});
+			grammar3.addRule(S, {a, A, d, D});
+			grammar3.addRule(S, {b, B, c, C});
+			grammar3.addRule(S, {c});
+			grammar3.addRule(A, {a, A, d, D});
+			grammar3.addRule(A, {b, B, c, C});
+			grammar3.addRule(A, {c});
+			grammar3.addRule(B, {b, B, c, C});
+			grammar3.addRule(B, {c});
+			grammar3.addRule(C, {c, C});
+			grammar3.addRule(C, {b});
+			grammar3.addRule(D, {d, D});
+			grammar3.addRule(D, {a});
+
+			CHECK(grammar2 == grammar3);
+		}
+	}
 }
diff --git a/alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.h b/alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.h
deleted file mode 100644
index fe17db1714..0000000000
--- a/alib2algo/test-src/grammar/simplify/GrammarSimpleRulesRemoverTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef GRAMMAR_SIMPLE_RULES_REMOVER_TEST_H_
-#define GRAMMAR_SIMPLE_RULES_REMOVER_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarSimpleRulesRemoverTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarSimpleRulesRemoverTest );
-  CPPUNIT_TEST( testRemoveSimpleRulesRules1 );
-  CPPUNIT_TEST( testRemoveSimpleRulesRules2 );
-  CPPUNIT_TEST( testRemoveSimpleRulesRules3 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testRemoveSimpleRulesRules1();
-  void testRemoveSimpleRulesRules2();
-  void testRemoveSimpleRulesRules3();
-};
-
-#endif /* GRAMMAR_SIMPLE_RULES_REMOVER_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/simplify/GrammarToCNFTest.cpp b/alib2algo/test-src/grammar/simplify/GrammarToCNFTest.cpp
index c66a594015..ad45309c68 100644
--- a/alib2algo/test-src/grammar/simplify/GrammarToCNFTest.cpp
+++ b/alib2algo/test-src/grammar/simplify/GrammarToCNFTest.cpp
@@ -1,4 +1,4 @@
-#include "GrammarToCNFTest.h"
+#include <catch2/catch.hpp>
 
 #include "grammar/simplify/ToCNF.h"
 
@@ -9,94 +9,86 @@
 
 #include <grammar/Grammar.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarToCNFTest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarToCNFTest );
-
-void GrammarToCNFTest::setUp() {
-}
-
-void GrammarToCNFTest::tearDown() {
-}
-
-void GrammarToCNFTest::testToCNFRules1() {
-	std::string S = "S";
-	std::string A = "A";
-	std::string B = "B";
-	std::string C = "C";
-	std::string D = "D";
-
-	char a = 'a';
-	char b = 'b';
-
-	grammar::CFG < char, std::string > grammar1 ( S );
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b});
-
-	grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar2 = grammar::simplify::ToCNF::convert ( grammar1 );
-
-	grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar3 ( ext::vector < ext::variant < char, std::string > > { S } );
-	grammar3.setNonterminalAlphabet({{S}, {A}, {B}, {C}, {D}, {a}, {b}});
-	grammar3.setTerminalAlphabet({a, b});
-	grammar3.addRule ( ext::vector < ext::variant < char, std::string > > { a }, a);
-	grammar3.addRule ( ext::vector < ext::variant < char, std::string > > { b }, b);
-
-	std::cout << grammar2 << std::endl;
-	std::cout << grammar3 << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarToCNFTest::testToCNFRules2() {
-	std::string S = "S";
-	std::string X = "X";
-	std::string Y = "Y";
-
-	char a = 'a';
-	char b = 'b';
-	char c = 'c';
-
-	grammar::CFG < char, std::string > grammar1 ( S );
-	grammar1.setNonterminalAlphabet({S, X, Y});
-	grammar1.setTerminalAlphabet({a, b, c});
-	grammar1.addRule(S, {a, X, b, X});
-	grammar1.addRule(X, {a, Y});
-	grammar1.addRule(X, {b, Y});
-	grammar1.addRule(X, {});
-	grammar1.addRule(Y, {X});
-	grammar1.addRule(Y, {c});
-
-	grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar2 = grammar::simplify::ToCNF::convert(grammar1);
-
-	ext::vector < ext::variant < char, std::string > > Xb { X, b };
-	ext::vector < ext::variant < char, std::string > > aX { a, X };
-	ext::vector < ext::variant < char, std::string > > bX { b, X };
-
-	grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar3 ( ext::vector < ext::variant < char, std::string > > { S } );
-	grammar3.setNonterminalAlphabet({{S}, {X}, {Y}, {a}, {b}, {c}, {Xb}, {aX}, {bX}});
-	grammar3.setTerminalAlphabet({a, b, c});
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { aX }, ext::vector < ext::variant < char, std::string > > { bX } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { bX } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { Xb } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { b } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { aX }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { X } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { bX }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { b }, ext::vector < ext::variant < char, std::string > > { X } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Xb }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { X }, ext::vector < ext::variant < char, std::string > > { b } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { Y } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { b }, ext::vector < ext::variant < char, std::string > > { Y } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, a);
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, b);
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { Y } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { b }, ext::vector < ext::variant < char, std::string > > { Y } ) );
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, a);
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, b);
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, c);
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { a }, a);
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { b }, b);
-	grammar3.addRule( ext::vector < ext::variant < char, std::string > > { c }, c);
-
-	std::cout << grammar2 << std::endl;
-	std::cout << grammar3 << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
+TEST_CASE ( "Test to CNF", "[unit][algo][grammar][simplify]" ) {
+	SECTION ( "Test CFG" ) {
+		{
+			std::string S = "S";
+			std::string A = "A";
+			std::string B = "B";
+			std::string C = "C";
+			std::string D = "D";
+
+			char a = 'a';
+			char b = 'b';
+
+			grammar::CFG < char, std::string > grammar1 ( S );
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b});
+
+			grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar2 = grammar::simplify::ToCNF::convert ( grammar1 );
+
+			grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar3 ( ext::vector < ext::variant < char, std::string > > { S } );
+			grammar3.setNonterminalAlphabet({{S}, {A}, {B}, {C}, {D}, {a}, {b}});
+			grammar3.setTerminalAlphabet({a, b});
+			grammar3.addRule ( ext::vector < ext::variant < char, std::string > > { a }, a);
+			grammar3.addRule ( ext::vector < ext::variant < char, std::string > > { b }, b);
+
+			CAPTURE ( grammar2, grammar3 );
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			std::string S = "S";
+			std::string X = "X";
+			std::string Y = "Y";
+
+			char a = 'a';
+			char b = 'b';
+			char c = 'c';
+
+			grammar::CFG < char, std::string > grammar1 ( S );
+			grammar1.setNonterminalAlphabet({S, X, Y});
+			grammar1.setTerminalAlphabet({a, b, c});
+			grammar1.addRule(S, {a, X, b, X});
+			grammar1.addRule(X, {a, Y});
+			grammar1.addRule(X, {b, Y});
+			grammar1.addRule(X, {});
+			grammar1.addRule(Y, {X});
+			grammar1.addRule(Y, {c});
+
+			grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar2 = grammar::simplify::ToCNF::convert(grammar1);
+
+			ext::vector < ext::variant < char, std::string > > Xb { X, b };
+			ext::vector < ext::variant < char, std::string > > aX { a, X };
+			ext::vector < ext::variant < char, std::string > > bX { b, X };
+
+			grammar::CNF < char, ext::vector < ext::variant < char, std::string > > > grammar3 ( ext::vector < ext::variant < char, std::string > > { S } );
+			grammar3.setNonterminalAlphabet({{S}, {X}, {Y}, {a}, {b}, {c}, {Xb}, {aX}, {bX}});
+			grammar3.setTerminalAlphabet({a, b, c});
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { aX }, ext::vector < ext::variant < char, std::string > > { bX } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { bX } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { Xb } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { S }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { b } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { aX }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { X } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { bX }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { b }, ext::vector < ext::variant < char, std::string > > { X } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Xb }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { X }, ext::vector < ext::variant < char, std::string > > { b } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { Y } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { b }, ext::vector < ext::variant < char, std::string > > { Y } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, a);
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { X }, b);
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { a }, ext::vector < ext::variant < char, std::string > > { Y } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, ext::make_pair ( ext::vector < ext::variant < char, std::string > > { b }, ext::vector < ext::variant < char, std::string > > { Y } ) );
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, a);
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, b);
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { Y }, c);
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { a }, a);
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { b }, b);
+			grammar3.addRule( ext::vector < ext::variant < char, std::string > > { c }, c);
+
+			CAPTURE ( grammar2, grammar3 );
+
+			CHECK(grammar2 == grammar3);
+		}
+	}
 }
 
diff --git a/alib2algo/test-src/grammar/simplify/GrammarToCNFTest.h b/alib2algo/test-src/grammar/simplify/GrammarToCNFTest.h
deleted file mode 100644
index 85081c5b4d..0000000000
--- a/alib2algo/test-src/grammar/simplify/GrammarToCNFTest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef GRAMMAR_TO_CNF_TEST_H_
-#define GRAMMAR_TO_CNF_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarToCNFTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarToCNFTest );
-  CPPUNIT_TEST( testToCNFRules1 );
-  CPPUNIT_TEST( testToCNFRules2 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testToCNFRules1();
-  void testToCNFRules2();
-};
-
-#endif /* GRAMMAR_TO_CNF_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.cpp b/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.cpp
index 81174c8231..006e9d7235 100644
--- a/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.cpp
+++ b/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.cpp
@@ -1,4 +1,4 @@
-#include "GrammarToGNFTest.h"
+#include <catch2/catch.hpp>
 
 #include "grammar/simplify/ToGNF.h"
 #include "grammar/generate/GenerateUpToLength.h"
@@ -12,165 +12,148 @@
 
 #include "container/string/ObjectsVariant.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GrammarToGNFTest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( GrammarToGNFTest );
-
-void GrammarToGNFTest::setUp() {
-}
-
-void GrammarToGNFTest::tearDown() {
-}
-
-void GrammarToGNFTest::testRemoveToGNFRules1() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType("a");
-	DefaultSymbolType b = DefaultSymbolType("b");
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b});
-
-	DefaultSymbolType aprimed = common::createUnique(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType bprimed = common::createUnique(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-
-	grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
-
-	grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, C, D, aprimed, bprimed});
-	grammar3.setTerminalAlphabet({a, b});
-	grammar3.addRule(aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(bprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-
-	std::cout << grammar2 << std::endl;
-	std::cout << grammar3 << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarToGNFTest::testRemoveToGNFRules2() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-	DefaultSymbolType D = DefaultSymbolType("D");
-
-	DefaultSymbolType a = DefaultSymbolType("a");
-	DefaultSymbolType b = DefaultSymbolType("b");
-	DefaultSymbolType c = DefaultSymbolType("c");
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C, D});
-	grammar1.setTerminalAlphabet({a, b, c});
-	grammar1.addRule(S, {A});
-	grammar1.addRule(A, {A, a});
-	grammar1.addRule(A, {A, b});
-	grammar1.addRule(A, {c});
-
-	DefaultSymbolType Aprimed = common::createUnique(A, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType aprimed = common::createUnique(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType bprimed = common::createUnique(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType cprimed = common::createUnique(c, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-
-	std::cout << grammar1 << std::endl;
-
-	grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
-
-	grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, Aprimed, B, C, D, aprimed, bprimed, cprimed});
-	grammar3.setTerminalAlphabet({a, b, c});
-	grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
-	grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
-	grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(Aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
-	grammar3.addRule(Aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(Aprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
-	grammar3.addRule(Aprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(bprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(cprimed, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-
-	std::cout << grammar2 << std::endl;
-	std::cout << grammar3 << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarToGNFTest::testRemoveToGNFRules3() {
-	DefaultSymbolType S = DefaultSymbolType("S");
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-
-	DefaultSymbolType a = DefaultSymbolType("a");
-	DefaultSymbolType b = DefaultSymbolType("b");
-	DefaultSymbolType c = DefaultSymbolType("c");
-
-	grammar::EpsilonFreeCFG < > grammar1(S);
-	grammar1.setNonterminalAlphabet({S, A, B, C});
-	grammar1.setTerminalAlphabet({a, b, c});
-	grammar1.addRule(S, {A});
-	grammar1.addRule(A, {B, a});
-	grammar1.addRule(B, {A, b});
-	grammar1.addRule(A, {c});
-
-	DefaultSymbolType Bprimed = common::createUnique(B, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType aprimed = common::createUnique(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType bprimed = common::createUnique(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-	DefaultSymbolType cprimed = common::createUnique(c, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
-
-	std::cout << grammar1 << std::endl;
-
-	grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
-
-	grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar3(S);
-	grammar3.setNonterminalAlphabet({S, A, B, Bprimed, C, aprimed, bprimed, cprimed});
-	grammar3.setTerminalAlphabet({a, b, c});
-	grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed, aprimed}));
-	grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, aprimed}));
-	grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, aprimed}));
-	grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed, aprimed}));
-	grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(B, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed}));
-	grammar3.addRule(B, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed}));
-	grammar3.addRule(Bprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed}));
-	grammar3.addRule(Bprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed}));
-	grammar3.addRule(aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(bprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-	grammar3.addRule(cprimed, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
-
-	std::cout << grammar2 << std::endl;
-	std::cout << grammar3 << std::endl;
-
-	CPPUNIT_ASSERT(grammar2 == grammar3);
-}
-
-void GrammarToGNFTest::testRemoveToGNFRules4() {
-	DefaultSymbolType A = DefaultSymbolType("A");
-	DefaultSymbolType B = DefaultSymbolType("B");
-	DefaultSymbolType C = DefaultSymbolType("C");
-
-	DefaultSymbolType a = DefaultSymbolType("a");
-	DefaultSymbolType b = DefaultSymbolType("b");
-
-	grammar::EpsilonFreeCFG < > grammar1(A);
-	grammar1.setNonterminalAlphabet({A, B, C});
-	grammar1.setTerminalAlphabet({a, b});
-	grammar1.addRule(A, {B, C});
-	grammar1.addRule(A, {a});
-	grammar1.addRule(B, {C, A});
-	grammar1.addRule(B, {A, b});
-	grammar1.addRule(C, {A, B});
-	grammar1.addRule(C, {C, C});
-	grammar1.addRule(C, {a});
-
-	grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
-
-	CPPUNIT_ASSERT(grammar::generate::GenerateUpToLength::generate(grammar1, 7) == grammar::generate::GenerateUpToLength::generate(grammar2, 7));
+TEST_CASE ( "Test to GNF", "[unit][algo][grammar][simplify]" ) {
+	SECTION ( "Test CFG" ) {
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType("a");
+			DefaultSymbolType b = DefaultSymbolType("b");
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b});
+
+			DefaultSymbolType aprimed = common::createUnique(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType bprimed = common::createUnique(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+			grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+			grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, C, D, aprimed, bprimed});
+			grammar3.setTerminalAlphabet({a, b});
+			grammar3.addRule(aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(bprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+
+			CAPTURE ( grammar2, grammar3 ) ;
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+			DefaultSymbolType D = DefaultSymbolType("D");
+
+			DefaultSymbolType a = DefaultSymbolType("a");
+			DefaultSymbolType b = DefaultSymbolType("b");
+			DefaultSymbolType c = DefaultSymbolType("c");
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C, D});
+			grammar1.setTerminalAlphabet({a, b, c});
+			grammar1.addRule(S, {A});
+			grammar1.addRule(A, {A, a});
+			grammar1.addRule(A, {A, b});
+			grammar1.addRule(A, {c});
+
+			DefaultSymbolType Aprimed = common::createUnique(A, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType aprimed = common::createUnique(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType bprimed = common::createUnique(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType cprimed = common::createUnique(c, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+			grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+			grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, Aprimed, B, C, D, aprimed, bprimed, cprimed});
+			grammar3.setTerminalAlphabet({a, b, c});
+			grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
+			grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
+			grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(Aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
+			grammar3.addRule(Aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(Aprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{Aprimed}));
+			grammar3.addRule(Aprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(bprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(cprimed, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+
+			CAPTURE ( grammar1, grammar2, grammar3 ) ;
+
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType S = DefaultSymbolType("S");
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+
+			DefaultSymbolType a = DefaultSymbolType("a");
+			DefaultSymbolType b = DefaultSymbolType("b");
+			DefaultSymbolType c = DefaultSymbolType("c");
+
+			grammar::EpsilonFreeCFG < > grammar1(S);
+			grammar1.setNonterminalAlphabet({S, A, B, C});
+			grammar1.setTerminalAlphabet({a, b, c});
+			grammar1.addRule(S, {A});
+			grammar1.addRule(A, {B, a});
+			grammar1.addRule(B, {A, b});
+			grammar1.addRule(A, {c});
+
+			DefaultSymbolType Bprimed = common::createUnique(B, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType aprimed = common::createUnique(a, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType bprimed = common::createUnique(b, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+			DefaultSymbolType cprimed = common::createUnique(c, grammar1.getTerminalAlphabet(), grammar1.getNonterminalAlphabet());
+
+			grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+			grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar3(S);
+			grammar3.setNonterminalAlphabet({S, A, B, Bprimed, C, aprimed, bprimed, cprimed});
+			grammar3.setTerminalAlphabet({a, b, c});
+			grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed, aprimed}));
+			grammar3.addRule(S, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, aprimed}));
+			grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, aprimed}));
+			grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed, aprimed}));
+			grammar3.addRule(A, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(B, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed}));
+			grammar3.addRule(B, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed}));
+			grammar3.addRule(Bprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed, Bprimed}));
+			grammar3.addRule(Bprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{bprimed}));
+			grammar3.addRule(aprimed, ext::make_pair(a, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(bprimed, ext::make_pair(b, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+			grammar3.addRule(cprimed, ext::make_pair(c, ext::vector<ext::variant<DefaultSymbolType,DefaultSymbolType>>{}));
+
+			CAPTURE ( grammar1, grammar2, grammar3 );
+			CHECK(grammar2 == grammar3);
+		}
+		{
+			DefaultSymbolType A = DefaultSymbolType("A");
+			DefaultSymbolType B = DefaultSymbolType("B");
+			DefaultSymbolType C = DefaultSymbolType("C");
+
+			DefaultSymbolType a = DefaultSymbolType("a");
+			DefaultSymbolType b = DefaultSymbolType("b");
+
+			grammar::EpsilonFreeCFG < > grammar1(A);
+			grammar1.setNonterminalAlphabet({A, B, C});
+			grammar1.setTerminalAlphabet({a, b});
+			grammar1.addRule(A, {B, C});
+			grammar1.addRule(A, {a});
+			grammar1.addRule(B, {C, A});
+			grammar1.addRule(B, {A, b});
+			grammar1.addRule(C, {A, B});
+			grammar1.addRule(C, {C, C});
+			grammar1.addRule(C, {a});
+
+			grammar::GNF < DefaultSymbolType, ext::variant < DefaultSymbolType, DefaultSymbolType > > grammar2 = grammar::simplify::ToGNF::convert(grammar1);
+
+			CHECK(grammar::generate::GenerateUpToLength::generate(grammar1, 7) == grammar::generate::GenerateUpToLength::generate(grammar2, 7));
+		}
+	}
 }
diff --git a/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.h b/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.h
deleted file mode 100644
index d47c6f6537..0000000000
--- a/alib2algo/test-src/grammar/simplify/GrammarToGNFTest.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef GRAMMAR_TO_GNF_TEST_H_
-#define GRAMMAR_TO_GNF_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GrammarToGNFTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( GrammarToGNFTest );
-  CPPUNIT_TEST( testRemoveToGNFRules1 );
-  CPPUNIT_TEST( testRemoveToGNFRules2 );
-  CPPUNIT_TEST( testRemoveToGNFRules3 );
-  CPPUNIT_TEST( testRemoveToGNFRules4 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testRemoveToGNFRules1();
-  void testRemoveToGNFRules2();
-  void testRemoveToGNFRules3();
-  void testRemoveToGNFRules4();
-};
-
-#endif /* GRAMMAR_TO_GNF_TEST_H_ */
diff --git a/alib2algo/test-src/grammar/simplify/TrimTest.cpp b/alib2algo/test-src/grammar/simplify/TrimTest.cpp
new file mode 100644
index 0000000000..2113e4e457
--- /dev/null
+++ b/alib2algo/test-src/grammar/simplify/TrimTest.cpp
@@ -0,0 +1,34 @@
+#include <catch2/catch.hpp>
+
+#include "grammar/simplify/Trim.h"
+#include "grammar/Regular/RightRG.h"
+
+TEST_CASE ( "Trim Grammar", "[unit][algo][grammar][simplify]" ) {
+	SECTION ( "Test CFG" ) {
+
+		grammar::RightRG < > rrGrammar(DefaultSymbolType(1));
+
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(1));
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(2));
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(3));
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(4));
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(5));
+		rrGrammar.addNonterminalSymbol(DefaultSymbolType(6));
+		rrGrammar.addTerminalSymbol(DefaultSymbolType("a"));
+		rrGrammar.addTerminalSymbol(DefaultSymbolType("b"));
+
+		rrGrammar.addRule(DefaultSymbolType(1), ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(2)));
+		rrGrammar.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(3)));
+		rrGrammar.addRule(DefaultSymbolType(3), DefaultSymbolType("a"));
+
+		rrGrammar.addRule(DefaultSymbolType(4), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(5)));
+		rrGrammar.addRule(DefaultSymbolType(5), DefaultSymbolType("a"));
+		rrGrammar.addRule(DefaultSymbolType(5), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(2)));
+		rrGrammar.addRule(DefaultSymbolType(6), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(6)));
+
+		grammar::RightRG < > trimed = grammar::simplify::Trim::trim(rrGrammar);
+
+		CHECK(trimed.getNonterminalAlphabet().size() == 3);
+	}
+}
+
diff --git a/alib2algo/test-src/grammar/toGrammar/rg2rgTest.cpp b/alib2algo/test-src/grammar/toGrammar/rg2rgTest.cpp
deleted file mode 100644
index bb1dcada1e..0000000000
--- a/alib2algo/test-src/grammar/toGrammar/rg2rgTest.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <alib/list>
-#include "rg2rgTest.h"
-
-#include "grammar/convert/ToGrammarLeftRG.h"
-#include "grammar/convert/ToGrammarRightRG.h"
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( rg2rgTest, "grammar" );
-CPPUNIT_TEST_SUITE_REGISTRATION( rg2rgTest );
-
-void rg2rgTest::setUp() {
-}
-
-void rg2rgTest::tearDown() {
-}
-
-void rg2rgTest::testConversion() {
-  grammar::RightRG < > rrGrammar(DefaultSymbolType(1));
-
-  rrGrammar.addNonterminalSymbol(DefaultSymbolType(1));
-  rrGrammar.addNonterminalSymbol(DefaultSymbolType(2));
-  rrGrammar.addNonterminalSymbol(DefaultSymbolType(3));
-  rrGrammar.addTerminalSymbol(DefaultSymbolType("a"));
-  rrGrammar.addTerminalSymbol(DefaultSymbolType("b"));
-  
-  rrGrammar.addRule(DefaultSymbolType(1), ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(2)));
-  rrGrammar.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(3)));
-  rrGrammar.addRule(DefaultSymbolType(3), DefaultSymbolType("a"));
-
-  grammar::LeftRG < > lrGrammar = grammar::convert::ToGrammarLeftRG::convert(rrGrammar);
-
-  DefaultSymbolType four ( object::AnyObject < int > ( 1, 1 ) );
-  grammar::LeftRG < > lrGrammarRef ( four );
-
-  lrGrammarRef.addNonterminalSymbol(DefaultSymbolType(1));
-  lrGrammarRef.addNonterminalSymbol(DefaultSymbolType(2));
-  lrGrammarRef.addNonterminalSymbol(DefaultSymbolType(3));
-  lrGrammarRef.addTerminalSymbol(DefaultSymbolType("a"));
-  lrGrammarRef.addTerminalSymbol(DefaultSymbolType("b"));
-
-  lrGrammarRef.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType(1), DefaultSymbolType("a")));
-  lrGrammarRef.addRule(DefaultSymbolType(2), DefaultSymbolType("a"));
-  lrGrammarRef.addRule(DefaultSymbolType(3), ext::make_pair(DefaultSymbolType(2), DefaultSymbolType("b")));
-  lrGrammarRef.addRule(four, ext::make_pair(DefaultSymbolType(3), DefaultSymbolType("a")));
-
-  CPPUNIT_ASSERT(lrGrammarRef == lrGrammar);
-}
-
-void rg2rgTest::testConversion2() {
-  grammar::LeftRG < > lrGrammar(DefaultSymbolType(4));
-
-  lrGrammar.addNonterminalSymbol(DefaultSymbolType(2));
-  lrGrammar.addNonterminalSymbol(DefaultSymbolType(3));
-  lrGrammar.addNonterminalSymbol(DefaultSymbolType(4));
-  lrGrammar.addTerminalSymbol(DefaultSymbolType("a"));
-  lrGrammar.addTerminalSymbol(DefaultSymbolType("b"));
-
-  lrGrammar.addRule(DefaultSymbolType(2), DefaultSymbolType("a"));
-  lrGrammar.addRule(DefaultSymbolType(3), ext::make_pair(DefaultSymbolType(2), DefaultSymbolType("b")));
-  lrGrammar.addRule(DefaultSymbolType(4), ext::make_pair(DefaultSymbolType(3), DefaultSymbolType("a")));
-
-  grammar::RightRG < > rrGrammar = grammar::convert::ToGrammarRightRG::convert(lrGrammar);
-
-  DefaultSymbolType five ( object::AnyObject < int > ( 4, 1 ) );
-  grammar::RightRG < > rrGrammarRef ( five );
-
-  rrGrammarRef.addNonterminalSymbol(DefaultSymbolType(2));
-  rrGrammarRef.addNonterminalSymbol(DefaultSymbolType(3));
-  rrGrammarRef.addNonterminalSymbol(DefaultSymbolType(4));
-  rrGrammarRef.addTerminalSymbol(DefaultSymbolType("a"));
-  rrGrammarRef.addTerminalSymbol(DefaultSymbolType("b"));
-
-  rrGrammarRef.addRule(five, ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(2)));
-  rrGrammarRef.addRule(DefaultSymbolType(2), ext::make_pair(DefaultSymbolType("b"), DefaultSymbolType(3)));
-  rrGrammarRef.addRule(DefaultSymbolType(3), DefaultSymbolType("a"));
-  rrGrammarRef.addRule(DefaultSymbolType(3), ext::make_pair(DefaultSymbolType("a"), DefaultSymbolType(4)));
-
-  CPPUNIT_ASSERT(rrGrammarRef == rrGrammar);
-}
diff --git a/alib2algo/test-src/grammar/toGrammar/rg2rgTest.h b/alib2algo/test-src/grammar/toGrammar/rg2rgTest.h
deleted file mode 100644
index 923e4442d3..0000000000
--- a/alib2algo/test-src/grammar/toGrammar/rg2rgTest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef RG2RG_TEST_H_
-#define RG2RG_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class rg2rgTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( rg2rgTest );
-  CPPUNIT_TEST( testConversion );
-  CPPUNIT_TEST( testConversion2 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testConversion();
-  void testConversion2();
-};
-
-#endif  // RG2RG_TEST_H_
diff --git a/alib2algo/test-src/main.cpp b/alib2algo/test-src/main.cpp
index adb58324a1..4ed06df1f7 100644
--- a/alib2algo/test-src/main.cpp
+++ b/alib2algo/test-src/main.cpp
@@ -1,166 +1,2 @@
-#include <version.hpp>
-
-#include <tclap/CmdLine.h>
-
-#include <cppunit/CompilerOutputter.h>
-#include <cppunit/extensions/TestFactoryRegistry.h>
-#include <cppunit/ui/text/TestRunner.h>
-#include <cppunit/TestResultCollector.h>
-#include <cppunit/TestResult.h>
-#include <cppunit/XmlOutputter.h>
-
-#include <cppunit/Test.h>
-#include <cppunit/TestFailure.h>
-#include <cppunit/portability/Stream.h>
-#include <cppunit/TestListener.h>
-#include <cppunit/SourceLine.h>
-#include <cppunit/Exception.h>
-
-#include <exception/CommonException.h>
-
-CPPUNIT_NS_BEGIN
-
-class CPPUNIT_API TestProgressListener : public TestListener
-{
-public:
-	TestProgressListener();
-
-	virtual ~TestProgressListener();
-
-	void startTest( Test *test );
-
-	void addFailure( const TestFailure &failure );
-
-	void endTest( Test *test );
-
-	int getResult() const;
-
-	void printResults() const;
-
-private:
-	TestProgressListener( const TestProgressListener &copy );
-
-	void operator =( const TestProgressListener &copy );
-
-private:
-	int m_Failures;
-	int m_Tests;
-	int m_Assertions;
-	bool m_lastTestFailed;
-};
-
-TestProgressListener::TestProgressListener() : m_Failures( 0 ), m_Tests(0), m_Assertions(0), m_lastTestFailed( false )
-{
-}
-
-TestProgressListener::~TestProgressListener()
-{
-}
-
-void TestProgressListener::startTest( Test * test )
-{
-	stdCOut() << test->getName() << ":" << "\n";
-	stdCOut().flush();
-
-	m_lastTestFailed = false;
-	m_Tests++;
-}
-
-void TestProgressListener::addFailure( const TestFailure &failure )
-{
-	stdCOut() << (failure.isError() ? "error" : "assertion") << " : " << failure.failedTestName() << " : " << failure.sourceLine().lineNumber() << "\n";
-	stdCOut() << "Exception " << failure.thrownException()->message().details();
-
-	m_lastTestFailed = true;
-	if(failure.isError()) m_Failures++; else m_Assertions++;
-}
-
-void TestProgressListener::endTest( Test * test)
-{
-	stdCOut() << "Result (" << test->getName() << ")";
-	stdCOut().flush();
-
-	if ( !m_lastTestFailed )
-		stdCOut() <<	" : OK";
-	else
-		stdCOut() << " : Fail";
-	stdCOut() << "\n\n";
-}
-
-int TestProgressListener::getResult() const {
-	return m_Failures + m_Assertions;
-}
-
-void TestProgressListener::printResults() const {
-	stdCOut() << "Overal result: Tests: " << m_Tests << " Assertions: " << m_Assertions << " Failures: " << m_Failures << "\n";
-}
-
-CPPUNIT_NS_END
-
-int main(int argc, char* argv[]) {
-	try {
-		TCLAP::CmdLine cmd("Main test binary.", ' ', ALIB_VERSION_INFO);
-
-		TCLAP::MultiArg<std::string> testPathSegments("p", "path", "test path", false, "string" );
-		cmd.add( testPathSegments );
-
-		cmd.parse(argc, argv);
-
-		CppUnit::TestResult controller;
-
-		CppUnit::TestResultCollector result;
-		controller.addListener( &result );
-
-		CppUnit::TestProgressListener progressListener;
-		controller.addListener( &progressListener );
-
-		CppUnit::Test *suite = NULL;
-		std::string testPath = "";
-		if(testPathSegments.getValue().size() == 0) {
-			// Get the top level suite from the registry
-			suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
-		} else if(testPathSegments.getValue().size() == 1) {
-			suite = CppUnit::TestFactoryRegistry::getRegistry(testPathSegments.getValue()[0]).makeTest();
-		} else {
-			suite = CppUnit::TestFactoryRegistry::getRegistry(testPathSegments.getValue()[0]).makeTest();
-			bool first = true;
-			for(const std::string& path : testPathSegments.getValue()) {
-				if(first) {
-					first = false;
-					continue;
-				}
-				testPath += path + "/";
-			}
-			testPath.pop_back();
-		}
-
-		// Adds the test to the list of test to run
-		CppUnit::TextUi::TestRunner runner;
-		runner.addTest( suite );
-
-		// Change the default outputter to a compiler error format outputter
-		runner.setOutputter( new CppUnit::CompilerOutputter( &runner.result(), std::cerr ) );
-		// Run the tests.
-		runner.run( controller, testPath );
-
-		progressListener.printResults();
-
-		std::ofstream xmlFileResults("CppUnitTestResults.xml");
-		CppUnit::XmlOutputter xmlOut(&result, xmlFileResults);
-		xmlOut.write();
-
-		return progressListener.getResult();
-	} catch(const exception::CommonException& exception) {
-		std::cerr << exception.getCause() << std::endl;
-		return 1;
-	} catch(const TCLAP::ArgException& exception) {
-		std::cerr << exception.error() << std::endl;
-		return 2;
-	} catch (const std::exception& exception) {
-		std::cerr << "Exception caught: " << exception.what() << std::endl;
-		return 3;
-	} catch(...) {
-		std::cerr << "Unknown exception caught." << std::endl;
-		return 127;
-	}
-}
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
diff --git a/alib2algo/test-src/playTest.cpp b/alib2algo/test-src/playTest.cpp
deleted file mode 100644
index 9a53f84156..0000000000
--- a/alib2algo/test-src/playTest.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "playTest.h"
-
-#include <alib/iostream>
-#include <cstdlib>
-#include <ctime>
-
-#include "automaton/determinize/Determinize.h"
-#include "automaton/generate/RandomAutomatonFactory.h"
-#include "automaton/simplify/Minimize.h"
-#include "automaton/simplify/Normalize.h"
-#include "automaton/simplify/Trim.h"
-#include "automaton/simplify/EpsilonRemoverIncoming.h"
-
-#define TEST_ITERATIONS 100
-#define TEST_AUTOMATON_STATES_MAX 18
-#define TEST_AUTOMATON_DENSITY_MAX 2.5
-#define TEST_AUTOMATON_ALPHABET_MAX 4
-
-CPPUNIT_TEST_SUITE_REGISTRATION( playTest );
-
-void playTest::setUp()
-{
-    srand(time(NULL));
-}
-
-void playTest::tearDown(){}
-
-automaton::NFA < std::string, unsigned >  playTest::randomNFA(void) const
-{
-    return automaton::generate::RandomAutomatonFactory::generateNFA(
-            rand() % TEST_AUTOMATON_STATES_MAX + 1,
-            rand() % TEST_AUTOMATON_ALPHABET_MAX + 1,
-            true,
-            static_cast<double> (rand()) / (static_cast<double> (RAND_MAX/TEST_AUTOMATON_DENSITY_MAX))
-            );
-}
-
-automaton::DFA < DefaultSymbolType, unsigned > playTest::mDFA(const automaton::NFA < > & automaton) const
-{
-    automaton::NFA < >  nfa = automaton::simplify::EpsilonRemoverIncoming::remove(automaton);
-    nfa = automaton::simplify::Trim::trim(nfa);
-    automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa = automaton::determinize::Determinize::determinize(nfa);
-    dfa = automaton::simplify::Trim::trim(dfa);
-    dfa = automaton::simplify::Minimize::minimize(dfa);
-    automaton::DFA < DefaultSymbolType, unsigned > dfa2 = automaton::simplify::Normalize::normalize(dfa);
-    return dfa2;
-}
-
-/**
- * Test case 1:
- *  - covers: FA -> LRG, FA -> RRG, RRG <-> LRG, RRG -> FA, LRG -> FA
- *  a. FA -> RRG -> LRG -> FA
- *  b. FA -> LRG -> RRG -> FA
- */
-void playTest::testPlay1()
-{
-    for(int i = 0; i < TEST_ITERATIONS; i++)
-        this->case1a();
-    for(int i = 0; i < TEST_ITERATIONS; i++)
-        this->case1b();
-}
-
-void playTest::case1a(void) const
-{
-    /*
-    fa2rg::FAtoRRGConverter fa2rrg;
-    rg2rg::RightToLeftRegularGrammar rrg2lrg;
-    rg2fa::LRGtoFAConverter lrg2fa;
-
-    automaton::NFA < >  a1 = this->randomNFA();
-    automaton::NFA < >  a2 = lrg2fa.convert(rrg2lrg.convert(fa2rrg.convert(a1)));
-
-    CPPUNIT_ASSERT(this->mDFA(a1) == this->mDFA(a2));
-    */
-}
-
-void playTest::case1b(void) const
-{
-    /*
-    fa2rg::FAtoLRGConverter fa2lrg;
-    rg2rg::LeftToRightRegularGrammar lrg2rrg;
-    rg2fa::RRGtoFAConverter rrg2fa;
-
-    automaton::NFA < >  a1 = this->randomNFA();
-    automaton::NFA < >  a2 = rrg2fa.convert(lrg2rrg.convert(fa2lrg.convert(a1)));
-
-    CPPUNIT_ASSERT(this->mDFA(a1) == this->mDFA(a2));
-    */
-}
diff --git a/alib2algo/test-src/playTest.h b/alib2algo/test-src/playTest.h
deleted file mode 100644
index d7f12ed7d3..0000000000
--- a/alib2algo/test-src/playTest.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef PLAY_TEST_H_
-#define PLAY_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-#include <automaton/FSM/NFA.h>
-#include <automaton/FSM/DFA.h>
-#include <string>
-
-class playTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( playTest );
-  CPPUNIT_TEST( testPlay1 );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testPlay1();
-
-private:
-    automaton::NFA < std::string, unsigned >  randomNFA(void) const;
-    automaton::DFA < DefaultSymbolType, unsigned > mDFA(const automaton::NFA < > & automaton) const;
-
-    void case1a(void) const;
-    void case1b(void) const;
-};
-
-#endif  // PLAY_TEST_H_
diff --git a/alib2algo/test-src/regexp/RegExpTest.cpp b/alib2algo/test-src/regexp/RegExpTest.cpp
deleted file mode 100644
index 9ccade215d..0000000000
--- a/alib2algo/test-src/regexp/RegExpTest.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#include "RegExpTest.h"
-#include <alib/list>
-#include <alib/pair>
-
-#include "sax/SaxComposeInterface.h"
-#include "sax/SaxParseInterface.h"
-
-#include "regexp/unbounded/UnboundedRegExp.h"
-#include <regexp/RegExp.h>
-
-#include "regexp/glushkov/GlushkovFollow.h"
-#include "regexp/glushkov/GlushkovIndexate.h"
-#include "regexp/glushkov/GlushkovFirst.h"
-#include "regexp/glushkov/GlushkovLast.h"
-
-#include <factory/StringDataFactory.hpp>
-#include <regexp/string/UnboundedRegExp.h>
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( RegExpTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( RegExpTest );
-
-void RegExpTest::setUp ( ) {
-}
-
-void RegExpTest::tearDown ( ) {
-}
-
-void RegExpTest::testFirst ( ) {
-	{
-		std::string input = "#E* #0*";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-		regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
-
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > first = regexp::GlushkovFirst::first ( indexedRegExp );
-
-		CPPUNIT_ASSERT ( first.size ( ) == 0 );
-	}
-	{
-		std::string input = "#E* a";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-		regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
-
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > first = regexp::GlushkovFirst::first ( indexedRegExp );
-
-		CPPUNIT_ASSERT ( first.size ( ) == 1 );
-	}
-}
-
-void RegExpTest::testLast ( ) {
-	{
-		std::string input = "a+a";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-		regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
-
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > last = regexp::GlushkovLast::last ( indexedRegExp );
-
-		CPPUNIT_ASSERT ( last.size ( ) == 2 );
-	}
-	{
-		std::string input = "(a+a)b";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-		regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
-
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > last = regexp::GlushkovLast::last ( indexedRegExp );
-
-		std::cout << last << std::endl;
-		CPPUNIT_ASSERT ( last.size ( ) == 1 );
-	}
-}
-
-void RegExpTest::testFollow ( ) {
-	{
-		std::string input = "(a+a)b";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-		regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
-
-		auto symbolsIter = indexedRegExp.getAlphabet ( ).begin ( );
-
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow1 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow1.size ( ) == 1 );
-
-		symbolsIter++;
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow2 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow2.size ( ) == 1 );
-
-		symbolsIter++;
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow3 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow3.size ( ) == 0 );
-	}
-	{
-		std::string input = "a+a* (b+a)* c";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-		regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
-
-		auto symbolsIter = indexedRegExp.getAlphabet ( ).begin ( );
-
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow1 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow1.size ( ) == 0 );
-
-		symbolsIter++;
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow2 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow2.size ( ) == 4 );
-
-		symbolsIter++;
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow3 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow3.size ( ) == 3 );
-
-		symbolsIter++;
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow4 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow4.size ( ) == 3 );
-
-		symbolsIter++;
-		ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow5 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
-
-		CPPUNIT_ASSERT ( follow5.size ( ) == 0 );
-	}
-}
diff --git a/alib2algo/test-src/regexp/RegExpTest.h b/alib2algo/test-src/regexp/RegExpTest.h
deleted file mode 100644
index 05e38f8c20..0000000000
--- a/alib2algo/test-src/regexp/RegExpTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef REG_EXP_TEST_H_
-#define REG_EXP_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class RegExpTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( RegExpTest );
-  CPPUNIT_TEST( testFirst );
-  CPPUNIT_TEST( testLast );
-  CPPUNIT_TEST( testFollow );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testFirst();
-  void testLast();
-  void testFollow();
-};
-
-#endif  // REG_EXP_TEST_H_
diff --git a/alib2algo/test-src/regexp/convert/ToAutomatonTest.cpp b/alib2algo/test-src/regexp/convert/ToAutomatonTest.cpp
new file mode 100644
index 0000000000..09021e7f39
--- /dev/null
+++ b/alib2algo/test-src/regexp/convert/ToAutomatonTest.cpp
@@ -0,0 +1,81 @@
+#include <catch2/catch.hpp>
+
+#include <alib/list>
+#include <alib/pair>
+
+#include "regexp/convert/ToAutomatonDerivation.h"
+#include "regexp/convert/ToAutomatonGlushkov.h"
+#include "regexp/convert/ToAutomatonThompson.h"
+#include "automaton/convert/ToRegExpAlgebraic.h"
+#include "automaton/determinize/Determinize.h"
+#include "automaton/simplify/Minimize.h"
+#include "automaton/simplify/Normalize.h"
+#include "automaton/simplify/EpsilonRemoverOutgoing.h"
+
+#include "regexp/unbounded/UnboundedRegExp.h"
+
+#include "automaton/FSM/NFA.h"
+#include <factory/StringDataFactory.hpp>
+#include <regexp/string/UnboundedRegExp.h>
+
+
+TEST_CASE ( "RegExp to automaton", "[unit][algo][regexp][convert]" ) {
+	const std::string input  = "a+a* b*";
+
+	SECTION ( "Thompson" ) {
+		regexp::UnboundedRegExp < > regexp1 = factory::StringDataFactory::fromString (input);
+
+		automaton::EpsilonNFA < > enfa1 = regexp::convert::ToAutomatonThompson::convert(regexp1);
+
+		regexp::UnboundedRegExp < > regexp2 ( automaton::convert::ToRegExpAlgebraic::convert( enfa1) );
+
+		automaton::EpsilonNFA < > enfa2 = regexp::convert::ToAutomatonThompson::convert(regexp2);
+
+		automaton::MultiInitialStateNFA < > nfa1 = automaton::simplify::EpsilonRemoverOutgoing::remove(enfa1);
+		automaton::MultiInitialStateNFA < > nfa2 = automaton::simplify::EpsilonRemoverOutgoing::remove(enfa2);
+
+		automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa1 = automaton::determinize::Determinize::determinize(nfa1);
+		automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa2 = automaton::determinize::Determinize::determinize(nfa2);
+
+		automaton::DFA< DefaultSymbolType, unsigned > mdfa1 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa1));
+		automaton::DFA< DefaultSymbolType, unsigned > mdfa2 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa2));
+
+		CHECK( mdfa1 == mdfa2);
+	}
+
+	SECTION ( "Glushkov" ) {
+		regexp::UnboundedRegExp < > regexp1 = factory::StringDataFactory::fromString ( input );
+
+		automaton::NFA < DefaultSymbolType, ext::pair < DefaultSymbolType, unsigned > > nfa1 = regexp::convert::ToAutomatonGlushkov::convert ( regexp1 );
+
+		regexp::UnboundedRegExp < > regexp2 = automaton::convert::ToRegExpAlgebraic::convert ( nfa1 );
+
+		automaton::NFA < DefaultSymbolType, ext::pair < DefaultSymbolType, unsigned > > nfa2 = regexp::convert::ToAutomatonGlushkov::convert(regexp2);
+
+		automaton::DFA < DefaultSymbolType, ext::set < ext::pair < DefaultSymbolType, unsigned > > > dfa1 = automaton::determinize::Determinize::determinize(nfa1);
+		automaton::DFA < DefaultSymbolType, ext::set < ext::pair < DefaultSymbolType, unsigned > > > dfa2 = automaton::determinize::Determinize::determinize(nfa2);
+
+		automaton::DFA< DefaultSymbolType, unsigned > mdfa1 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa1));
+		automaton::DFA< DefaultSymbolType, unsigned > mdfa2 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa2));
+
+		CHECK( mdfa1 == mdfa2);
+	}
+
+	SECTION ( "Brzozowski" ) {
+		regexp::UnboundedRegExp < > regexp1 = factory::StringDataFactory::fromString (input);
+
+		automaton::DFA < DefaultSymbolType, unsigned > dfa1 = regexp::convert::ToAutomatonDerivation::convert(regexp1);
+
+		regexp::UnboundedRegExp < > regexp2( automaton::convert::ToRegExpAlgebraic::convert ( core::normalize < automaton::DFA < DefaultSymbolType, unsigned > >::eval ( automaton::DFA < DefaultSymbolType, unsigned > ( dfa1 ) ) ) );
+
+		automaton::DFA < DefaultSymbolType, unsigned > dfa2 = regexp::convert::ToAutomatonDerivation::convert(regexp2);
+
+		automaton::DFA < DefaultSymbolType, unsigned > mdfa1_2 = automaton::simplify::Minimize::minimize(dfa1);
+		automaton::DFA < DefaultSymbolType, unsigned > mdfa1_3 = automaton::simplify::Normalize::normalize(mdfa1_2);
+
+		automaton::DFA < DefaultSymbolType, unsigned > mdfa2_2 = automaton::simplify::Minimize::minimize(dfa2);
+		automaton::DFA < DefaultSymbolType, unsigned > mdfa2_3 = automaton::simplify::Normalize::normalize(mdfa2_2);
+
+		CHECK( mdfa1_3 == mdfa2_3);
+	}
+}
diff --git a/alib2algo/test-src/regexp/glushkov/GlushkovTest.cpp b/alib2algo/test-src/regexp/glushkov/GlushkovTest.cpp
new file mode 100644
index 0000000000..d114d59f4c
--- /dev/null
+++ b/alib2algo/test-src/regexp/glushkov/GlushkovTest.cpp
@@ -0,0 +1,117 @@
+#include <catch2/catch.hpp>
+#include <alib/list>
+#include <alib/pair>
+
+#include "sax/SaxComposeInterface.h"
+#include "sax/SaxParseInterface.h"
+
+#include "regexp/unbounded/UnboundedRegExp.h"
+#include <regexp/RegExp.h>
+
+#include "regexp/glushkov/GlushkovFollow.h"
+#include "regexp/glushkov/GlushkovIndexate.h"
+#include "regexp/glushkov/GlushkovFirst.h"
+#include "regexp/glushkov/GlushkovLast.h"
+
+#include <factory/StringDataFactory.hpp>
+#include <regexp/string/UnboundedRegExp.h>
+
+TEST_CASE ( "RegExp glushkov test", "[unit][algo][regexp][glushkov]" ) {
+	SECTION ( "First" ) {
+		{
+			std::string input = "#E* #0*";
+			regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
+			regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
+
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > first = regexp::GlushkovFirst::first ( indexedRegExp );
+
+			CHECK ( first.size ( ) == 0 );
+		}
+		{
+			std::string input = "#E* a";
+			regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
+			regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
+
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > first = regexp::GlushkovFirst::first ( indexedRegExp );
+
+			CHECK ( first.size ( ) == 1 );
+		}
+	}
+
+	SECTION ( "Last" ) {
+
+		{
+			std::string input = "a+a";
+			regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
+			regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
+
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > last = regexp::GlushkovLast::last ( indexedRegExp );
+
+			CHECK ( last.size ( ) == 2 );
+		}
+		{
+			std::string input = "(a+a)b";
+			regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
+			regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
+
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > last = regexp::GlushkovLast::last ( indexedRegExp );
+
+			CHECK ( last.size ( ) == 1 );
+		}
+	}
+
+	SECTION ( "Follow" ) {
+		{
+			std::string input = "(a+a)b";
+			regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
+			regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
+
+			auto symbolsIter = indexedRegExp.getAlphabet ( ).begin ( );
+
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow1 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow1.size ( ) == 1 );
+
+			symbolsIter++;
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow2 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow2.size ( ) == 1 );
+
+			symbolsIter++;
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow3 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow3.size ( ) == 0 );
+		}
+		{
+			std::string input = "a+a* (b+a)* c";
+			regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
+			regexp::UnboundedRegExp < ext::pair < DefaultSymbolType, unsigned > > indexedRegExp = regexp::GlushkovIndexate::index ( regexp );
+
+			auto symbolsIter = indexedRegExp.getAlphabet ( ).begin ( );
+
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow1 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow1.size ( ) == 0 );
+
+			symbolsIter++;
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow2 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow2.size ( ) == 4 );
+
+			symbolsIter++;
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow3 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow3.size ( ) == 3 );
+
+			symbolsIter++;
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow4 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow4.size ( ) == 3 );
+
+			symbolsIter++;
+			ext::set < regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > > follow5 = regexp::GlushkovFollow::follow ( indexedRegExp, regexp::UnboundedRegExpSymbol < ext::pair < DefaultSymbolType, unsigned > > ( * symbolsIter ) );
+
+			CHECK ( follow5.size ( ) == 0 );
+		}
+	}
+}
diff --git a/alib2algo/test-src/regexp/properties/RegExpEmptyTest.cpp b/alib2algo/test-src/regexp/properties/RegExpEmptyTest.cpp
deleted file mode 100644
index c741ea4511..0000000000
--- a/alib2algo/test-src/regexp/properties/RegExpEmptyTest.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "RegExpEmptyTest.h"
-
-#include "regexp/properties/RegExpEmpty.h"
-
-#include <regexp/RegExp.h>
-
-#include <factory/StringDataFactory.hpp>
-#include <regexp/string/UnboundedRegExp.h>
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RegExpEmptyTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION( RegExpEmptyTest );
-
-void RegExpEmptyTest::setUp() {
-}
-
-void RegExpEmptyTest::tearDown() {
-}
-
-void RegExpEmptyTest::testRegExpEmpty() {
-	{
-		std::string input = "(#E #0 ) + ( #0 a + (b ( #0 (a*) ) ) )";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(regexp::properties::RegExpEmpty::languageIsEmpty(re));
-	}
-	{
-		std::string input = "(#E + a ) + ( #0 a + (b ( #0 (a*) ) ) )";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(! regexp::properties::RegExpEmpty::languageIsEmpty(re));
-	}
-}
diff --git a/alib2algo/test-src/regexp/properties/RegExpEmptyTest.h b/alib2algo/test-src/regexp/properties/RegExpEmptyTest.h
deleted file mode 100644
index 3c651fcaa3..0000000000
--- a/alib2algo/test-src/regexp/properties/RegExpEmptyTest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef REGEXPEMPTY_TEST_H_
-#define REGEXPEMPTY_TEST_H_
-
-#include <alib/string>
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class RegExpEmptyTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( RegExpEmptyTest );
-	CPPUNIT_TEST( testRegExpEmpty );
-	CPPUNIT_TEST_SUITE_END();
-
-public:
-	void setUp();
-	void tearDown();
-
-	void testRegExpEmpty();
-};
-
-#endif /* REGEXPEMPTY_TEST_H_ */
diff --git a/alib2algo/test-src/regexp/properties/RegExpEpsilonTest.cpp b/alib2algo/test-src/regexp/properties/RegExpEpsilonTest.cpp
deleted file mode 100644
index 6809422d1a..0000000000
--- a/alib2algo/test-src/regexp/properties/RegExpEpsilonTest.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "RegExpEpsilonTest.h"
-
-#include "regexp/properties/RegExpEpsilon.h"
-
-#include <factory/StringDataFactory.hpp>
-#include <regexp/string/UnboundedRegExp.h>
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RegExpEpsilonTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION( RegExpEpsilonTest );
-
-void RegExpEpsilonTest::setUp() {
-}
-
-void RegExpEpsilonTest::tearDown() {
-}
-
-void RegExpEpsilonTest::testRegExpEpsilon() {
-	{
-		std::string input = "#E + ( (a #E) + a*)";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
-	}
-	{
-		std::string input = "( a* )( a* )";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
-	}
-	{
-		std::string input = "a + #0";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(! regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
-	}
-	{
-		std::string input = "#E + a #E + a*";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
-	}
-	{
-		std::string input = "a* a*";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
-	}
-	{
-		std::string input = "a s d #E + #E #0";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(! regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
-	}
-	{
-		std::string input = "a + #0";
-		regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
-
-		CPPUNIT_ASSERT(! regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
-	}
-}
diff --git a/alib2algo/test-src/regexp/properties/RegExpEpsilonTest.h b/alib2algo/test-src/regexp/properties/RegExpEpsilonTest.h
deleted file mode 100644
index 3d7c5ff416..0000000000
--- a/alib2algo/test-src/regexp/properties/RegExpEpsilonTest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef REGEXPEPSILON_TEST_H_
-#define REGEXPEPSILON_TEST_H_
-
-#include <alib/string>
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class RegExpEpsilonTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( RegExpEpsilonTest );
-  CPPUNIT_TEST( testRegExpEpsilon );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testRegExpEpsilon();
-};
-
-#endif /* REGEXPEPSILON_TEST_H_ */
diff --git a/alib2algo/test-src/regexp/properties/RegExpPropertiesTest.cpp b/alib2algo/test-src/regexp/properties/RegExpPropertiesTest.cpp
new file mode 100644
index 0000000000..eb5507828e
--- /dev/null
+++ b/alib2algo/test-src/regexp/properties/RegExpPropertiesTest.cpp
@@ -0,0 +1,69 @@
+#include <catch2/catch.hpp>
+
+#include "regexp/properties/RegExpEpsilon.h"
+#include "regexp/properties/RegExpEmpty.h"
+
+#include <factory/StringDataFactory.hpp>
+#include <regexp/string/UnboundedRegExp.h>
+
+TEST_CASE ( "RegExp properties", "[unit][algo][regexp][properties]" ) {
+	SECTION ( "Describes epsilon" ) {
+		{
+			std::string input = "#E + ( (a #E) + a*)";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
+		}
+		{
+			std::string input = "( a* )( a* )";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
+		}
+		{
+			std::string input = "a + #0";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(! regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
+		}
+		{
+			std::string input = "#E + a #E + a*";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
+		}
+		{
+			std::string input = "a* a*";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
+		}
+		{
+			std::string input = "a s d #E + #E #0";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(! regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
+		}
+		{
+			std::string input = "a + #0";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(! regexp::properties::RegExpEpsilon::languageContainsEpsilon(re));
+		}
+	}
+
+	SECTION ( "Describes empty language" ) {
+		{
+			std::string input = "(#E #0 ) + ( #0 a + (b ( #0 (a*) ) ) )";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(regexp::properties::RegExpEmpty::languageIsEmpty(re));
+		}
+		{
+			std::string input = "(#E + a ) + ( #0 a + (b ( #0 (a*) ) ) )";
+			regexp::UnboundedRegExp < > re = factory::StringDataFactory::fromString (input);
+
+			CHECK(! regexp::properties::RegExpEmpty::languageIsEmpty(re));
+		}
+	}
+}
diff --git a/alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.cpp b/alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.cpp
index e0c012b417..133b4bd059 100644
--- a/alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.cpp
+++ b/alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.cpp
@@ -1,5 +1,6 @@
-#include <alib/list>
-#include "RegExpOptimizeTest.h"
+#include <catch2/catch.hpp>
+
+#include <alib/map>
 
 #include "regexp/unbounded/UnboundedRegExp.h"
 
@@ -8,281 +9,125 @@
 #include <factory/StringDataFactory.hpp>
 #include <regexp/string/UnboundedRegExp.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RegExpOptimizeTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION( RegExpOptimizeTest );
-
-void RegExpOptimizeTest::setUp() {
-}
-
-void RegExpOptimizeTest::tearDown() {
-}
-
-void RegExpOptimizeTest::testOptimize() {
-	{
-		std::string input = "a+a";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "a";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
+TEST_CASE ( "RegExp Optimize", "[unit][algo][regexp][simplify]" ) {
+	SECTION ( "Test simple axioms" ) {
+		auto testcase = GENERATE (
+				std::make_pair ("a+a", "a" ),
+				std::make_pair ( "(a+a)b + (#0 b + (#0 a + (#0 b + a)))", "a + a b" ),
+				//std::make_pair ( "a z + a b* b z", "a b* z" ),
+				std::make_pair ( "a***", "a*" ),
+				std::make_pair ( "(a*+b*)*", "(a+b)*" ),
+				std::make_pair ( "(a*b*)*", "(a+b)*" ),
+				std::make_pair ( "#0*+a*", "a*" ),
+				std::make_pair ( "a+(a+a)", "a" )
+				// std::make_pair ( "(a+b*)(a+b*)*", "(a+b*)*" ), implemented but skipped because ( a + b* )* gets simplified to ( a + b )* FIXME
+				// std::make_pair ( "(x y)*x", "x(y x)*" ),
+				);
+
+		regexp::UnboundedRegExp < > orig = factory::StringDataFactory::fromString ( testcase.first );
+		regexp::UnboundedRegExp < > origOpt = regexp::simplify::RegExpOptimize::optimize ( orig );
+		regexp::UnboundedRegExp < > expected = factory::StringDataFactory::fromString ( testcase.second );
+
+		CAPTURE ( testcase.first, testcase.second );
+		CAPTURE ( orig, origOpt, expected );
+		CHECK ( origOpt == expected );
 	}
-	{
-		std::string input = "(a+a)b + (#0 b + (#0 a + (#0 b + a)))";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "a + a b";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
 
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
+	SECTION ( "Test optimize templated" ) {
+		regexp::UnboundedRegExpSymbol < char > a ( 'a' );
+		regexp::UnboundedRegExpSymbol < char > b ( 'b' );
+		regexp::UnboundedRegExpSymbol < char > z ( 'z' );
+
+		{
+			regexp::UnboundedRegExpAlternation < char > alt;
+			alt.appendElement ( a );
+			alt.appendElement ( a );
+
+			regexp::UnboundedRegExp < char > regexp ( regexp::UnboundedRegExpStructure < char > { alt } );
+			regexp::UnboundedRegExp < char > res = regexp::simplify::RegExpOptimize::optimize(regexp);
+			regexp::UnboundedRegExp < char > regexpRes( regexp::UnboundedRegExpStructure < char > { a } );
+
+			CAPTURE ( res, regexpRes );
+			CHECK ( regexpRes == res );
+		}
+		{
+			regexp::UnboundedRegExpAlternation < char > alt1;
+			alt1.appendElement ( a );
+			alt1.appendElement ( a );
+			regexp::UnboundedRegExpConcatenation < char > con1;
+			con1.appendElement ( alt1 );
+			con1.appendElement ( b );
+
+			regexp::UnboundedRegExpConcatenation < char > con2;
+			con2.appendElement ( regexp::UnboundedRegExpEmpty < char > { } );
+			con2.appendElement ( b );
+			regexp::UnboundedRegExpAlternation < char > alt2;
+			alt2.appendElement ( con2 );
+			alt2.appendElement ( a );
+
+			regexp::UnboundedRegExpConcatenation < char > con3;
+			con3.appendElement ( regexp::UnboundedRegExpEmpty < char > { } );
+			con3.appendElement ( a );
+			regexp::UnboundedRegExpAlternation < char > alt3;
+			alt3.appendElement ( con3 );
+			alt3.appendElement ( alt2 );
+
+			regexp::UnboundedRegExpConcatenation < char > con4;
+			con4.appendElement ( regexp::UnboundedRegExpEmpty < char > { } );
+			con4.appendElement ( b );
+			regexp::UnboundedRegExpAlternation < char > alt4;
+			alt4.appendElement ( con4 );
+			alt4.appendElement ( alt3 );
+
+			regexp::UnboundedRegExpAlternation < char > alt5;
+			alt5.appendElement ( con1 );
+			alt5.appendElement ( alt4 );
+
+			regexp::UnboundedRegExp < char > regexp ( regexp::UnboundedRegExpStructure < char > { alt5 } );
+
+			regexp::UnboundedRegExp < char > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
+
+			regexp::UnboundedRegExpConcatenation < char > con6;
+			con6.appendElement ( a );
+			con6.appendElement ( b );
+			regexp::UnboundedRegExpAlternation < char > alt6;
+			alt6.appendElement ( a );
+			alt6.appendElement ( con6 );
+
+			regexp::UnboundedRegExp < char > regexpRes( regexp::UnboundedRegExpStructure < char > { alt6 } );
+
+			CAPTURE ( regexp, res, regexpRes );
+			CHECK ( regexpRes == res );
+		}
+		{
+			regexp::UnboundedRegExpSymbol < char > symb { 'b' };
+			regexp::UnboundedRegExpIteration < char > iter { symb };
+
+			regexp::UnboundedRegExpConcatenation < char > con1;
+			con1.appendElement ( symb );
+			con1.appendElement ( iter );
+
+			regexp::UnboundedRegExpAlternation < char > alt1;
+			alt1.appendElement ( con1 );
+
+			regexp::UnboundedRegExpAlternation < char > alt2;
+
+			regexp::UnboundedRegExpConcatenation < char > con2;
+			con2.appendElement ( alt1 );
+			con2.appendElement ( alt2 );
+
+			regexp::UnboundedRegExpAlternation < char > alt3;
+
+			regexp::UnboundedRegExpAlternation < char > alt4;
+			alt4.appendElement ( alt3 );
+			alt4.appendElement ( con2 );
+
+			regexp::UnboundedRegExp < char > regexp( regexp::UnboundedRegExpStructure < char > { alt4 } );
+			regexp::UnboundedRegExp < char > res = regexp::simplify::RegExpOptimize::optimize(regexp);
+			regexp::UnboundedRegExp < char > regexpRes( regexp::UnboundedRegExpStructure < char > { } );
+
+			CAPTURE ( regexp, res, regexpRes );
+			CHECK ( regexpRes == res );
+		}
 	}
-	/*{
-		std::string input = "a z + a b* b z";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "a b* z";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}*/
-	{
-		std::string input = "a***";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "a*";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-	{
-		std::string input = "a***";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "a*";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-	{
-		std::string input = "(a*+b*)*";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "(a+b)*";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-	{
-		std::string input = "(a*b*)*";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "(a+b)*";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-	{
-		std::string input = "#0*+a*";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "a*";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-	{
-		std::string input = "a+(a+a)";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "a";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-/*	{ // implemented but skipped because ( a + b* )* gets simplified to ( a + b )* //FIXME
-		std::string input = "(a+b*)(a+b*)*";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "(a+b*)*";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}*/
-	/*{
-		std::string input = "(x y)*x";
-		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( input );
-
-		regexp::UnboundedRegExp < > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		std::string inputRes = "x(y x)*";
-		regexp::UnboundedRegExp < > regexpRes = factory::StringDataFactory::fromString ( inputRes );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}*/
-
-}
-
-void RegExpOptimizeTest::testOptimizeTemplated() {
-	regexp::UnboundedRegExpSymbol < char > a ( 'a' );
-	regexp::UnboundedRegExpSymbol < char > b ( 'b' );
-	regexp::UnboundedRegExpSymbol < char > z ( 'z' );
-
-	{
-		regexp::UnboundedRegExpAlternation < char > alt;
-		alt.appendElement ( a );
-		alt.appendElement ( a );
-
-		regexp::UnboundedRegExp < char > regexp ( regexp::UnboundedRegExpStructure < char > { alt } );
-
-		regexp::UnboundedRegExp < char > res = regexp::simplify::RegExpOptimize::optimize(regexp);
-
-		regexp::UnboundedRegExp < char > regexpRes( regexp::UnboundedRegExpStructure < char > { a } );
-
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-	{
-		regexp::UnboundedRegExpAlternation < char > alt1;
-		alt1.appendElement ( a );
-		alt1.appendElement ( a );
-		regexp::UnboundedRegExpConcatenation < char > con1;
-		con1.appendElement ( alt1 );
-		con1.appendElement ( b );
-
-		regexp::UnboundedRegExpConcatenation < char > con2;
-		con2.appendElement ( regexp::UnboundedRegExpEmpty < char > { } );
-		con2.appendElement ( b );
-		regexp::UnboundedRegExpAlternation < char > alt2;
-		alt2.appendElement ( con2 );
-		alt2.appendElement ( a );
-
-		regexp::UnboundedRegExpConcatenation < char > con3;
-		con3.appendElement ( regexp::UnboundedRegExpEmpty < char > { } );
-		con3.appendElement ( a );
-		regexp::UnboundedRegExpAlternation < char > alt3;
-		alt3.appendElement ( con3 );
-		alt3.appendElement ( alt2 );
-
-		regexp::UnboundedRegExpConcatenation < char > con4;
-		con4.appendElement ( regexp::UnboundedRegExpEmpty < char > { } );
-		con4.appendElement ( b );
-		regexp::UnboundedRegExpAlternation < char > alt4;
-		alt4.appendElement ( con4 );
-		alt4.appendElement ( alt3 );
-
-		regexp::UnboundedRegExpAlternation < char > alt5;
-		alt5.appendElement ( con1 );
-		alt5.appendElement ( alt4 );
-
-		regexp::UnboundedRegExp < char > regexp ( regexp::UnboundedRegExpStructure < char > { alt5 } );
-
-		regexp::UnboundedRegExp < char > res = regexp::simplify::RegExpOptimize::optimize ( regexp );
-
-		regexp::UnboundedRegExpConcatenation < char > con6;
-		con6.appendElement ( a );
-		con6.appendElement ( b );
-		regexp::UnboundedRegExpAlternation < char > alt6;
-		alt6.appendElement ( a );
-		alt6.appendElement ( con6 );
-
-		regexp::UnboundedRegExp < char > regexpRes( regexp::UnboundedRegExpStructure < char > { alt6 } );
-
-		std::cout << regexp << std::endl;
-		std::cout << res << std::endl;
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-	std::cout << std::endl;
-	{
-		regexp::UnboundedRegExpSymbol < char > symb { 'b' };
-		regexp::UnboundedRegExpIteration < char > iter { symb };
-
-		regexp::UnboundedRegExpConcatenation < char > con1;
-		con1.appendElement ( symb );
-		con1.appendElement ( iter );
-
-		regexp::UnboundedRegExpAlternation < char > alt1;
-		alt1.appendElement ( con1 );
-
-		regexp::UnboundedRegExpAlternation < char > alt2;
-
-		regexp::UnboundedRegExpConcatenation < char > con2;
-		con2.appendElement ( alt1 );
-		con2.appendElement ( alt2 );
-
-		regexp::UnboundedRegExpAlternation < char > alt3;
-
-		regexp::UnboundedRegExpAlternation < char > alt4;
-		alt4.appendElement ( alt3 );
-		alt4.appendElement ( con2 );
-
-		regexp::UnboundedRegExp < char > regexp( regexp::UnboundedRegExpStructure < char > { alt4 } );
-		std::cout << regexp << std::endl;
-
-		regexp::UnboundedRegExp < char > res = regexp::simplify::RegExpOptimize::optimize(regexp);
-		std::cout << res << std::endl;
-
-		regexp::UnboundedRegExp < char > regexpRes( regexp::UnboundedRegExpStructure < char > { } );
-		std::cout << regexpRes << std::endl;
-
-		CPPUNIT_ASSERT ( regexpRes == res );
-	}
-
 }
-
diff --git a/alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.h b/alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.h
deleted file mode 100644
index 64241080e0..0000000000
--- a/alib2algo/test-src/regexp/simplify/RegExpOptimizeTest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef REG_EXP_OPTIMIZE_TEST_H_
-#define REG_EXP_OPTIMIZE_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class RegExpOptimizeTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( RegExpOptimizeTest );
-  CPPUNIT_TEST( testOptimize );
-  CPPUNIT_TEST( testOptimizeTemplated );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testOptimize();
-  void testOptimizeTemplated();
-};
-
-#endif  // REG_EXP_OPTIMIZE_TEST_H_
diff --git a/alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp b/alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp
deleted file mode 100644
index 203de42432..0000000000
--- a/alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <alib/list>
-#include <alib/pair>
-#include "re2faTest.h"
-
-#include "regexp/convert/ToAutomatonDerivation.h"
-#include "regexp/convert/ToAutomatonGlushkov.h"
-#include "regexp/convert/ToAutomatonThompson.h"
-#include "automaton/convert/ToRegExpAlgebraic.h"
-#include "automaton/determinize/Determinize.h"
-#include "automaton/simplify/Minimize.h"
-#include "automaton/simplify/Normalize.h"
-#include "automaton/simplify/EpsilonRemoverOutgoing.h"
-
-#include "regexp/unbounded/UnboundedRegExp.h"
-
-#include "automaton/FSM/NFA.h"
-#include <factory/StringDataFactory.hpp>
-#include <regexp/string/UnboundedRegExp.h>
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( re2faTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION( re2faTest );
-
-void re2faTest::setUp() {
-}
-
-void re2faTest::tearDown() {
-}
-
-void re2faTest::testThompson() {
-	std::string input = "a+a* b*";
-	regexp::UnboundedRegExp < > regexp1 = factory::StringDataFactory::fromString (input);
-
-	automaton::EpsilonNFA < > enfa1 = regexp::convert::ToAutomatonThompson::convert(regexp1);
-
-	regexp::UnboundedRegExp < > regexp2 ( automaton::convert::ToRegExpAlgebraic::convert( enfa1) );
-
-	automaton::EpsilonNFA < > enfa2 = regexp::convert::ToAutomatonThompson::convert(regexp2);
-
-	automaton::MultiInitialStateNFA < > nfa1 = automaton::simplify::EpsilonRemoverOutgoing::remove(enfa1);
-	automaton::MultiInitialStateNFA < > nfa2 = automaton::simplify::EpsilonRemoverOutgoing::remove(enfa2);
-
-	automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa1 = automaton::determinize::Determinize::determinize(nfa1);
-	automaton::DFA < DefaultSymbolType, ext::set < DefaultStateType > > dfa2 = automaton::determinize::Determinize::determinize(nfa2);
-
-	automaton::DFA< DefaultSymbolType, unsigned > mdfa1 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa1));
-	automaton::DFA< DefaultSymbolType, unsigned > mdfa2 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa2));
-
-	CPPUNIT_ASSERT( mdfa1 == mdfa2);
-}
-
-void re2faTest::testGlushkov() {
-	std::string input = "a+a*b*";
-	regexp::UnboundedRegExp < > regexp1 = factory::StringDataFactory::fromString ( input );
-
-	automaton::NFA < DefaultSymbolType, ext::pair < DefaultSymbolType, unsigned > > nfa1 = regexp::convert::ToAutomatonGlushkov::convert ( regexp1 );
-
-	regexp::UnboundedRegExp < > regexp2 = automaton::convert::ToRegExpAlgebraic::convert ( nfa1 );
-
-	std::cout << regexp1 << std::endl;
-	std::cout << regexp2 << std::endl;
-
-	automaton::NFA < DefaultSymbolType, ext::pair < DefaultSymbolType, unsigned > > nfa2 = regexp::convert::ToAutomatonGlushkov::convert(regexp2);
-
-	automaton::DFA < DefaultSymbolType, ext::set < ext::pair < DefaultSymbolType, unsigned > > > dfa1 = automaton::determinize::Determinize::determinize(nfa1);
-	automaton::DFA < DefaultSymbolType, ext::set < ext::pair < DefaultSymbolType, unsigned > > > dfa2 = automaton::determinize::Determinize::determinize(nfa2);
-
-	automaton::DFA< DefaultSymbolType, unsigned > mdfa1 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa1));
-	automaton::DFA< DefaultSymbolType, unsigned > mdfa2 = automaton::simplify::Normalize::normalize(automaton::simplify::Minimize::minimize(dfa2));
-
-	std::cout << mdfa1 << std::endl;
-	std::cout << mdfa2 << std::endl;
-
-	CPPUNIT_ASSERT( mdfa1 == mdfa2);
-}
-
-void re2faTest::testBrzozowski() {
-	std::string input = "a+a* b*";
-	regexp::UnboundedRegExp < > regexp1 = factory::StringDataFactory::fromString (input);
-
-	automaton::DFA < DefaultSymbolType, unsigned > dfa1 = regexp::convert::ToAutomatonDerivation::convert(regexp1);
-
-	regexp::UnboundedRegExp < > regexp2( automaton::convert::ToRegExpAlgebraic::convert ( core::normalize < automaton::DFA < DefaultSymbolType, unsigned > >::eval ( automaton::DFA < DefaultSymbolType, unsigned > ( dfa1 ) ) ) );
-
-	automaton::DFA < DefaultSymbolType, unsigned > dfa2 = regexp::convert::ToAutomatonDerivation::convert(regexp2);
-
-	automaton::DFA < DefaultSymbolType, unsigned > mdfa1_2 = automaton::simplify::Minimize::minimize(dfa1);
-	automaton::DFA < DefaultSymbolType, unsigned > mdfa1_3 = automaton::simplify::Normalize::normalize(mdfa1_2);
-
-	automaton::DFA < DefaultSymbolType, unsigned > mdfa2_2 = automaton::simplify::Minimize::minimize(dfa2);
-	automaton::DFA < DefaultSymbolType, unsigned > mdfa2_3 = automaton::simplify::Normalize::normalize(mdfa2_2);
-
-	CPPUNIT_ASSERT( mdfa1_3 == mdfa2_3);
-}
diff --git a/alib2algo/test-src/regexp/toAutomaton/re2faTest.h b/alib2algo/test-src/regexp/toAutomaton/re2faTest.h
deleted file mode 100644
index 0f5454813d..0000000000
--- a/alib2algo/test-src/regexp/toAutomaton/re2faTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef RG2RG_TEST_H_
-#define RG2RG_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class re2faTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( re2faTest );
-  CPPUNIT_TEST( testThompson );
-  CPPUNIT_TEST( testGlushkov );
-  CPPUNIT_TEST( testBrzozowski );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testThompson();
-  void testGlushkov();
-  void testBrzozowski();
-};
-
-#endif  // RG2RG_TEST_H_
diff --git a/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp b/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp
index 7c1e0d6491..e42273a08f 100644
--- a/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp
+++ b/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.cpp
@@ -1,4 +1,4 @@
-#include "RegExpConcatenateTest.h"
+#include <catch2/catch.hpp>
 
 #include "regexp/transform/RegExpConcatenate.h"
 
@@ -8,60 +8,18 @@
 #include <factory/StringDataFactory.hpp>
 #include <regexp/string/UnboundedRegExp.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RegExpConcatenateTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION( RegExpConcatenateTest );
+TEST_CASE ( "RegExp Concatenate", "[unit][algo][regexp][transform]" ) {
+	SECTION ( "Test Concat" ) {
+		auto testcase = GENERATE (
+		std::make_tuple ( "(#E a b)", "(#E a c)", "(#E a b)(#E a c)" ),
+		std::make_tuple ( "(#E a b)", "(#0 #E )", "(#E a b)(#0 #E )" ),
+		std::make_tuple ( "(#0 #E )", "(#E a b)", "(#0 #E )(#E a b)" ) );
 
-void RegExpConcatenateTest::setUp() {
-}
-
-void RegExpConcatenateTest::tearDown() {
-}
-
-void RegExpConcatenateTest::testRegExpConcatenate() {
-	{
-		std::string input1 = "(#E a b)";
-		regexp::UnboundedRegExp < > re1 = factory::StringDataFactory::fromString (input1);
-
-		std::string input2 = "(#E a c)";
-		regexp::UnboundedRegExp < > re2 = factory::StringDataFactory::fromString (input2);
-
-		regexp::UnboundedRegExp < > re = regexp::RegExpConcatenate::concatenate(re1, re2);
-
-		std::string inputr = "(#E a b)(#E a c)";
-		regexp::UnboundedRegExp < > rer = factory::StringDataFactory::fromString (inputr);
-
-		CPPUNIT_ASSERT(re == rer);
-	}
-	{
-		std::string input1 = "(#E a b)";
-		regexp::UnboundedRegExp < > re1 = factory::StringDataFactory::fromString (input1);
-
-		regexp::UnboundedRegExp < > re2(regexp::FormalRegExp < > (regexp::FormalRegExpStructure < DefaultSymbolType > (regexp::FormalRegExpConcatenation < DefaultSymbolType > (regexp::FormalRegExpEmpty < DefaultSymbolType > {}, regexp::FormalRegExpEpsilon < DefaultSymbolType > {}))));
-
-		regexp::UnboundedRegExp < > re = regexp::RegExpConcatenate::concatenate(re1, re2);
-
-		std::string inputr = "(#E a b)(#0 #E )";
-		regexp::UnboundedRegExp < > rer = factory::StringDataFactory::fromString (inputr);
-
-		CPPUNIT_ASSERT(re == rer);
-	}
-	{
-		regexp::FormalRegExp < > re1 (regexp::FormalRegExpStructure < DefaultSymbolType > (regexp::FormalRegExpConcatenation < DefaultSymbolType > (regexp::FormalRegExpEmpty < DefaultSymbolType > {}, regexp::FormalRegExpEpsilon < DefaultSymbolType > {})));
-
-		std::string input2 = "(#E a b)";
-		regexp::UnboundedRegExp < > re2 = factory::StringDataFactory::fromString (input2);
-
-		regexp::FormalRegExp < > re = regexp::RegExpConcatenate::concatenate(re1, regexp::FormalRegExp < > ( re2 ) );
-
-		std::string inputr = "(#0 #E )(#E a b)";
-		regexp::UnboundedRegExp < > tmp = factory::StringDataFactory::fromString (inputr);
-		regexp::FormalRegExp < > rer = regexp::FormalRegExp < > ( tmp );
-
-		std::cout << tmp.getAlphabet() << std::endl;
-		std::cout << rer.getAlphabet() << std::endl;
+		regexp::UnboundedRegExp < > re1 = factory::StringDataFactory::fromString ( std::get < 0 > ( testcase ) );
+		regexp::UnboundedRegExp < > re2 = factory::StringDataFactory::fromString ( std::get < 1 > ( testcase ) );
+		regexp::UnboundedRegExp < > exp = factory::StringDataFactory::fromString ( std::get < 2 > ( testcase ) );
+		regexp::FormalRegExp < > re = regexp::RegExpConcatenate::concatenate( regexp::FormalRegExp < > ( re1 ), regexp::FormalRegExp < > ( re2 ) );
 
-		std::cout << re << std::endl;
-		std::cout << rer << std::endl;
-		CPPUNIT_ASSERT(re == rer);
+		CHECK(re == regexp::FormalRegExp < > ( exp ) );
 	}
 }
diff --git a/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.h b/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.h
deleted file mode 100644
index a48a88b911..0000000000
--- a/alib2algo/test-src/regexp/transform/RegExpConcatenateTest.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef REGEXP_CONCATENATE_TEST_H_
-#define REGEXP_CONCATENATE_TEST_H_
-
-#include <alib/string>
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class RegExpConcatenateTest : public CppUnit::TestFixture
-{
-	CPPUNIT_TEST_SUITE( RegExpConcatenateTest );
-	CPPUNIT_TEST( testRegExpConcatenate );
-	CPPUNIT_TEST_SUITE_END();
-
-public:
-	void setUp();
-	void tearDown();
-
-	void testRegExpConcatenate();
-};
-
-#endif /* REGEXP_CONCATENATE_TEST_H_ */
diff --git a/alib2algo/test-src/regexp/transform/RegExpDerivationTest.cpp b/alib2algo/test-src/regexp/transform/RegExpDerivationTest.cpp
index 44fe7fbca1..c16539c366 100644
--- a/alib2algo/test-src/regexp/transform/RegExpDerivationTest.cpp
+++ b/alib2algo/test-src/regexp/transform/RegExpDerivationTest.cpp
@@ -1,4 +1,4 @@
-#include "RegExpDerivationTest.h"
+#include <catch2/catch.hpp>
 
 #include "regexp/transform/RegExpDerivation.h"
 
@@ -11,40 +11,34 @@
 #include <string/string/LinearString.h>
 #include <string/xml/LinearString.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RegExpDerivationTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION( RegExpDerivationTest );
+TEST_CASE ( "Regexp Derivation", "[unit][algo][grammar][transform]" ) {
+	SECTION ( "Derivation" ) {
+		// https://edux.fit.cvut.cz/oppa/BI-AAG/cviceni/aag-cv04.pdf
+		auto testcase = GENERATE (
+				// Exc. 13
+				std::make_tuple ( "0 1 0 + 1 0 1 + 0*1 + 1*0", "0", "#E 1 0+#0 0 1+#E 0* 1+#0+#0 1* 0+#E"),
+				std::make_tuple ( "0 1 0 + 1 0 1 + 0*1 + 1*0", "0 0", "#0 1 0+#0 0+#0 0 1+(#0 0*+#E 0*) 1+#0+#0+#0 1* 0+#0"),
 
-void RegExpDerivationTest::setUp() {
-}
-
-void RegExpDerivationTest::tearDown() {
-}
-
-void RegExpDerivationTest::testRegExpDerivation() {
-    // https://edux.fit.cvut.cz/oppa/BI-AAG/cviceni/aag-cv04.pdf
+				// Exc. 14
+				std::make_tuple ( "(0 1*0 + 1 0*)*", "1", "(#0 1* 0+#E 0*) (0 1* 0+1 0*)*"),
+				std::make_tuple ( "(0 1*0 + 1 0*)*", "1 0", "(#0 1* 0+#0 0*+#E 0*) (0 1* 0+1 0*)*+(#E 1* 0+#0 0*) (0 1* 0+1 0*)*"),
 
-    // Exc. 13
-    this->ExecSingleTest("0 1 0 + 1 0 1 + 0*1 + 1*0", "0", "#E 1 0+#0 0 1+#E 0* 1+#0+#0 1* 0+#E");
-    this->ExecSingleTest("0 1 0 + 1 0 1 + 0*1 + 1*0", "0 0", "#0 1 0+#0 0+#0 0 1+(#0 0*+#E 0*) 1+#0+#0+#0 1* 0+#0");
-
-    // Exc. 14
-    this->ExecSingleTest("(0 1*0 + 1 0*)*", "1", "(#0 1* 0+#E 0*) (0 1* 0+1 0*)*");
-    this->ExecSingleTest("(0 1*0 + 1 0*)*", "1 0", "(#0 1* 0+#0 0*+#E 0*) (0 1* 0+1 0*)*+(#E 1* 0+#0 0*) (0 1* 0+1 0*)*");
-
-    // Exc. 15
-    this->ExecSingleTest("1 0*1*0", "1 0 0", "#0 0* 1* 0+(#0 0*+#E 0*) 1* 0+#0 1* 0+#E+#0 1* 0+#0");
-}
+				// Exc. 15
+				std::make_tuple ( "1 0*1*0", "1 0 0", "#0 0* 1* 0+(#0 0*+#E 0*) 1* 0+#0 1* 0+#E+#0 1* 0+#0")
+				);
 
-void RegExpDerivationTest::ExecSingleTest(std::string regexp_str, std::string string_str, std::string result) {
-    regexp::UnboundedRegExp < > regexp0 = factory::StringDataFactory::fromString (regexp_str);
-    ext::deque<sax::Token> tokens = factory::XmlDataFactory::toTokens(regexp0);
-    regexp::UnboundedRegExp < > regexp = factory::XmlDataFactory::fromTokens (std::move(tokens));
+		const std::string & regexp_str = std::get < 0 > ( testcase );
+		const std::string & string_str = std::get < 1 > ( testcase );
+		const std::string & result     = std::get < 2 > ( testcase );
 
-    string::LinearString < > string0 = factory::StringDataFactory::fromString ("\"" + string_str + "\"");
-    ext::deque<sax::Token> tokens2 = factory::XmlDataFactory::toTokens(string0);
-    string::LinearString < > string1 = factory::XmlDataFactory::fromTokens (std::move(tokens2));
+		regexp::UnboundedRegExp < > regexp0 = factory::StringDataFactory::fromString (regexp_str);
+		ext::deque<sax::Token> tokens = factory::XmlDataFactory::toTokens(regexp0);
+		regexp::UnboundedRegExp < > regexp = factory::XmlDataFactory::fromTokens (std::move(tokens));
 
-    std::cout << factory::StringDataFactory::toString(regexp::RegExpDerivation::derivation(regexp, string1)) << " == " << std::endl << result << std::endl << std::endl;
+		string::LinearString < > string0 = factory::StringDataFactory::fromString ("\"" + string_str + "\"");
+		ext::deque<sax::Token> tokens2 = factory::XmlDataFactory::toTokens(string0);
+		string::LinearString < > string1 = factory::XmlDataFactory::fromTokens (std::move(tokens2));
 
-    CPPUNIT_ASSERT(factory::StringDataFactory::toString(regexp::RegExpDerivation::derivation(regexp, string1)) == result);
+		CHECK(factory::StringDataFactory::toString(regexp::RegExpDerivation::derivation(regexp, string1)) == result);
+	}
 }
diff --git a/alib2algo/test-src/regexp/transform/RegExpDerivationTest.h b/alib2algo/test-src/regexp/transform/RegExpDerivationTest.h
deleted file mode 100644
index 79d4c9bcdf..0000000000
--- a/alib2algo/test-src/regexp/transform/RegExpDerivationTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef REGEXPDERIVATION_TEST_H_
-#define REGEXPDERIVATION_TEST_H_
-
-#include <alib/string>
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class RegExpDerivationTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( RegExpDerivationTest );
-  CPPUNIT_TEST( testRegExpDerivation );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testRegExpDerivation();
-
-  void ExecSingleTest(std::string, std::string, std::string);
-};
-
-#endif /* REGEXPDERIVATION_TEST_H_ */
diff --git a/alib2algo/test-src/regexp/transform/RegExpIntegralTest.cpp b/alib2algo/test-src/regexp/transform/RegExpIntegralTest.cpp
index 54c28f62f0..65e2a87dc7 100644
--- a/alib2algo/test-src/regexp/transform/RegExpIntegralTest.cpp
+++ b/alib2algo/test-src/regexp/transform/RegExpIntegralTest.cpp
@@ -1,4 +1,4 @@
-#include "RegExpIntegralTest.h"
+#include <catch2/catch.hpp>
 
 #include "regexp/transform/RegExpIntegral.h"
 
@@ -7,27 +7,19 @@
 
 #include <factory/StringDataFactory.hpp>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RegExpIntegralTest, "regexp" );
-CPPUNIT_TEST_SUITE_REGISTRATION( RegExpIntegralTest );
+TEST_CASE ( "Regexp Integral", "[unit][algo][grammar][transform]" ) {
+	SECTION ( "Integrals" ) {
+		// https://edux.fit.cvut.cz/oppa/BI-AAG/cviceni/aag-cv04.pdf
+		// Exc. 16
+		auto testcase = GENERATE ( std::make_tuple ( "0 1 0 + 1 0 1", "1", "1 0 1 0+1 1 0 1") );
 
-void RegExpIntegralTest::setUp() {
-}
-
-void RegExpIntegralTest::tearDown() {
-}
-
-void RegExpIntegralTest::testRegExpIntegral() {
-    // https://edux.fit.cvut.cz/oppa/BI-AAG/cviceni/aag-cv04.pdf
-
-    // Exc. 16
-    this->ExecSingleTest("0 1 0 + 1 0 1", "1", "1 0 1 0+1 1 0 1");
-}
-
-void RegExpIntegralTest::ExecSingleTest(std::string regexp_str, std::string string_str, std::string result) {
-    regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( regexp_str );
-    string::LinearString < > string = factory::StringDataFactory::fromString ( "\"" + string_str + "\"" );
+		const std::string & regexp_str = std::get < 0 > ( testcase );
+		const std::string & string_str = std::get < 1 > ( testcase );
+		const std::string & result     = std::get < 2 > ( testcase );
 
-    std::cout << factory::StringDataFactory::toString(regexp::RegExpIntegral::integral(regexp, string)) << " == " << result << std::endl;
+		regexp::UnboundedRegExp < > regexp = factory::StringDataFactory::fromString ( regexp_str );
+		string::LinearString < > string = factory::StringDataFactory::fromString ( "\"" + string_str + "\"" );
 
-    CPPUNIT_ASSERT(factory::StringDataFactory::toString(regexp::RegExpIntegral::integral(regexp, string)) == result);
+		CHECK(factory::StringDataFactory::toString(regexp::RegExpIntegral::integral(regexp, string)) == result);
+	}
 }
diff --git a/alib2algo/test-src/regexp/transform/RegExpIntegralTest.h b/alib2algo/test-src/regexp/transform/RegExpIntegralTest.h
deleted file mode 100644
index 9749d55503..0000000000
--- a/alib2algo/test-src/regexp/transform/RegExpIntegralTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef REGEXPINTEGRAL_TEST_H_
-#define REGEXPINTEGRAL_TEST_H_
-
-#include <alib/string>
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class RegExpIntegralTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( RegExpIntegralTest );
-  CPPUNIT_TEST( testRegExpIntegral );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testRegExpIntegral();
-
-  void ExecSingleTest(std::string, std::string, std::string);
-};
-
-#endif /* REGEXPINTEGRAL_TEST_H_ */
diff --git a/alib2algo/test-src/string/compare/compareTest.cpp b/alib2algo/test-src/string/compare/compareTest.cpp
index 409a4b87b8..06a20a2612 100644
--- a/alib2algo/test-src/string/compare/compareTest.cpp
+++ b/alib2algo/test-src/string/compare/compareTest.cpp
@@ -1,5 +1,4 @@
-#include <alib/list>
-#include "compareTest.h"
+#include <catch2/catch.hpp>
 
 #include "string/naive/ExactEqual.h"
 #include "string/naive/ExactCompare.h"
@@ -8,64 +7,57 @@
 #include "string/CyclicString.h"
 #include "string/Epsilon.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( compareTest, "string" );
-CPPUNIT_TEST_SUITE_REGISTRATION( compareTest );
 
-void compareTest::setUp() {
-}
+TEST_CASE ( "String Compare", "[unit][algo][string][compare]" ) {
+	SECTION ( "Cyclic String Equality" ) {
+		string::CyclicString < > str1("alfa");
+		string::CyclicString < > str2("aalf");
+		str2.extendAlphabet(str1.getAlphabet());
+		str1.extendAlphabet(str2.getAlphabet());
 
-void compareTest::tearDown() {
-}
+		CHECK(string::naive::ExactEqual::equals(str1, str2));
+	}
 
-void compareTest::testCyclicStringCompareBoolean() {
-	string::CyclicString < > str1("alfa");
-	string::CyclicString < > str2("aalf");
-	str2.extendAlphabet(str1.getAlphabet());
-	str1.extendAlphabet(str2.getAlphabet());
+	SECTION ( "Cyclic String integer pos" ) {
+		string::CyclicString < > str1("alfa");
+		string::CyclicString < > str2("aalf");
+		str2.extendAlphabet(str1.getAlphabet());
+		str1.extendAlphabet(str2.getAlphabet());
 
-	CPPUNIT_ASSERT(string::naive::ExactEqual::equals(str1, str2));
-}
+		CHECK(string::naive::ExactCompare::compare(str1, str2) == 0);
 
-void compareTest::testCyclicStringCompareInt() {
-	string::CyclicString < > str1("alfa");
-	string::CyclicString < > str2("aalf");
-	str2.extendAlphabet(str1.getAlphabet());
-	str1.extendAlphabet(str2.getAlphabet());
+		string::CyclicString < > str3("ccbcccb");
+		string::CyclicString < > str4("cbcccbc");
+		str2.extendAlphabet(str1.getAlphabet());
+		str1.extendAlphabet(str2.getAlphabet());
 
-	CPPUNIT_ASSERT(string::naive::ExactCompare::compare(str1, str2) == 0);
+		CHECK(string::naive::ExactCompare::compare(str3, str4) == 0);
+	}
 
-	string::CyclicString < > str3("ccbcccb");
-	string::CyclicString < > str4("cbcccbc");
-	str2.extendAlphabet(str1.getAlphabet());
-	str1.extendAlphabet(str2.getAlphabet());
+	SECTION ( "Compare Cyclic" ) {
+		string::CyclicString < > cyclic1({DefaultSymbolType(0), DefaultSymbolType(1), DefaultSymbolType(2)});
+		string::CyclicString < > cyclic2({DefaultSymbolType(1), DefaultSymbolType(2), DefaultSymbolType(0)});
+		string::CyclicString < > cyclic3({DefaultSymbolType(2), DefaultSymbolType(0), DefaultSymbolType(1)});
 
-	CPPUNIT_ASSERT(string::naive::ExactCompare::compare(str3, str4) == 0);
-}
+		string::CyclicString < > cyclic4({DefaultSymbolType(2), DefaultSymbolType(1), DefaultSymbolType(0)});
 
-void compareTest::testCompareCyclic() {
-	string::CyclicString < > cyclic1({DefaultSymbolType(0), DefaultSymbolType(1), DefaultSymbolType(2)});
-	string::CyclicString < > cyclic2({DefaultSymbolType(1), DefaultSymbolType(2), DefaultSymbolType(0)});
-	string::CyclicString < > cyclic3({DefaultSymbolType(2), DefaultSymbolType(0), DefaultSymbolType(1)});
+		string::CyclicString < > cyclic1n = string::simplify::NormalizeRotation::normalize(cyclic1);
+		string::CyclicString < > cyclic2n = string::simplify::NormalizeRotation::normalize(cyclic2);
+		string::CyclicString < > cyclic3n = string::simplify::NormalizeRotation::normalize(cyclic3);
+		string::CyclicString < > cyclic4n = string::simplify::NormalizeRotation::normalize(cyclic4);
 
-	string::CyclicString < > cyclic4({DefaultSymbolType(2), DefaultSymbolType(1), DefaultSymbolType(0)});
+		CHECK(cyclic1  == cyclic1n);
+		CHECK(cyclic1n == cyclic2n);
+		CHECK(cyclic1n == cyclic3n);
+		CHECK(cyclic2n == cyclic3n);
 
-	string::CyclicString < > cyclic1n = string::simplify::NormalizeRotation::normalize(cyclic1);
-	string::CyclicString < > cyclic2n = string::simplify::NormalizeRotation::normalize(cyclic2);
-	string::CyclicString < > cyclic3n = string::simplify::NormalizeRotation::normalize(cyclic3);
-	string::CyclicString < > cyclic4n = string::simplify::NormalizeRotation::normalize(cyclic4);
+		CHECK(cyclic4n != cyclic1n);
+		CHECK(cyclic4n != cyclic2n);
+		CHECK(cyclic4n != cyclic3n);
 
-	CPPUNIT_ASSERT(cyclic1  == cyclic1n);
-	CPPUNIT_ASSERT(cyclic1n == cyclic2n);
-	CPPUNIT_ASSERT(cyclic1n == cyclic3n);
-	CPPUNIT_ASSERT(cyclic2n == cyclic3n);
-
-	CPPUNIT_ASSERT(cyclic4n != cyclic1n);
-	CPPUNIT_ASSERT(cyclic4n != cyclic2n);
-	CPPUNIT_ASSERT(cyclic4n != cyclic3n);
-
-	string::CyclicString < > cyclic5({DefaultSymbolType(62), DefaultSymbolType(62), DefaultSymbolType(100), DefaultSymbolType(62)});
-	string::CyclicString < > cyclic5n = string::simplify::NormalizeRotation::normalize(cyclic5);
-	string::CyclicString < > cyclic5r({DefaultSymbolType(62), DefaultSymbolType(62), DefaultSymbolType(62), DefaultSymbolType(100)});
-	CPPUNIT_ASSERT(cyclic5n == cyclic5r);
+		string::CyclicString < > cyclic5({DefaultSymbolType(62), DefaultSymbolType(62), DefaultSymbolType(100), DefaultSymbolType(62)});
+		string::CyclicString < > cyclic5n = string::simplify::NormalizeRotation::normalize(cyclic5);
+		string::CyclicString < > cyclic5r({DefaultSymbolType(62), DefaultSymbolType(62), DefaultSymbolType(62), DefaultSymbolType(100)});
+		CHECK(cyclic5n == cyclic5r);
+	}
 }
-
diff --git a/alib2algo/test-src/string/compare/compareTest.h b/alib2algo/test-src/string/compare/compareTest.h
deleted file mode 100644
index 266e95e1d1..0000000000
--- a/alib2algo/test-src/string/compare/compareTest.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef COMPARE_TEST_H_
-#define COMPARE_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class compareTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( compareTest );
-  CPPUNIT_TEST( testCyclicStringCompareBoolean );
-  CPPUNIT_TEST( testCyclicStringCompareInt );
-  CPPUNIT_TEST( testCompareCyclic );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testCyclicStringCompareBoolean();
-  void testCyclicStringCompareInt();
-  void testCompareCyclic();
-};
-
-#endif  // COMPARE_TEST_H_
diff --git a/alib2algo/test-src/string/properties/borderArrayTest.cpp b/alib2algo/test-src/string/properties/borderArrayTest.cpp
index 42cb6f3e45..11c6ead408 100644
--- a/alib2algo/test-src/string/properties/borderArrayTest.cpp
+++ b/alib2algo/test-src/string/properties/borderArrayTest.cpp
@@ -1,21 +1,14 @@
-#include "borderArrayTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/properties/BorderArray.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( borderArrayTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION( borderArrayTest );
+TEST_CASE ( "Border Array", "[unit][algo][string][properties]" ) {
+	SECTION ( "Test" ) {
+		string::LinearString < char > string ( "alfalfaalf" );
+		ext::vector<unsigned> borderArray = string::properties::BorderArray::construct(string);
+		ext::vector<unsigned> expected {0, 0, 0, 0, 1, 2, 3, 1, 1, 2, 3};
 
-void borderArrayTest::setUp() {
-}
-
-void borderArrayTest::tearDown() {
-}
-
-void borderArrayTest::testBorderArray() {
-	string::LinearString < char > string ( "alfalfaalf" );
-	ext::vector<unsigned> borderArray = string::properties::BorderArray::construct(string);
-	ext::vector<unsigned> expected {0, 0, 0, 0, 1, 2, 3, 1, 1, 2, 3};
-
-	CPPUNIT_ASSERT(borderArray != expected);
+		CHECK(borderArray != expected);
+	}
 }
 
diff --git a/alib2algo/test-src/string/properties/borderArrayTest.h b/alib2algo/test-src/string/properties/borderArrayTest.h
deleted file mode 100644
index 6d5fcb293c..0000000000
--- a/alib2algo/test-src/string/properties/borderArrayTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef BORDER_ARRAY_TEST
-#define BORDER_ARRAY_TEST
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class borderArrayTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( borderArrayTest );
-  CPPUNIT_TEST( testBorderArray );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testBorderArray();
-};
-
-#endif  // BORDER_ARRAY_TEST
diff --git a/alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.cpp b/alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.cpp
index f90e719a40..ba9bc51c51 100644
--- a/alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.cpp
+++ b/alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.cpp
@@ -1,27 +1,20 @@
-#include "ArithmeticCompressionTest.h"
+#include <catch2/catch.hpp>
 
 #include <stringology/compression/ArithmeticCompression.h>
 #include <stringology/compression/ArithmeticDecompression.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ArithmeticCompressionTest, "compression" );
-CPPUNIT_TEST_SUITE_REGISTRATION( ArithmeticCompressionTest );
+TEST_CASE ( "Arithmetic Compression", "[unit][algo][stringology][compression]" ) {
+	SECTION ( "basics" ) {
+		ext::string rawInput ( "abbabbabaae123456789r0 8723 babababb  ab bapobababbbabaaabbafjfjdjlvldsuiueqwpomvdhgataewpvdihviasubababbba 5475 baaabba" );
+		string::LinearString < char > input ( rawInput );
 
-void ArithmeticCompressionTest::setUp() {
-}
-
-void ArithmeticCompressionTest::tearDown() {
-}
-
-void ArithmeticCompressionTest::basics() {
-	ext::string rawInput ( "abbabbabaae123456789r0 8723 babababb  ab bapobababbbabaaabbafjfjdjlvldsuiueqwpomvdhgataewpvdihviasubababbba 5475 baaabba" );
-	string::LinearString < char > input ( rawInput );
-
-	ext::vector < bool > compressed = stringology::compression::AdaptiveIntegerArithmeticCompression::compress ( input );
-	std::cout << "compressed = " << compressed << std::endl;
-	string::LinearString < char > output = stringology::compression::AdaptiveIntegerArithmeticDecompression::decompress ( compressed, input.getAlphabet ( ) );
+		ext::vector < bool > compressed = stringology::compression::AdaptiveIntegerArithmeticCompression::compress ( input );
+		INFO ( "compressed = " << compressed );
+		string::LinearString < char > output = stringology::compression::AdaptiveIntegerArithmeticDecompression::decompress ( compressed, input.getAlphabet ( ) );
 
-	std::cout << "original= " << input << std::endl << "decompressed = " << output << std::endl;
-	std::cout << "compressed size = " << compressed.size ( ) << std::endl << "original_size = " << input.getContent ( ).size ( ) * 8 << std::endl;
-	CPPUNIT_ASSERT ( input == output );
+		INFO ( "original= " << input << " decompressed = " << output );
+		INFO ( "compressed size = " << compressed.size ( ) << " original_size = " << input.getContent ( ).size ( ) * 8 );
+		CHECK( input == output );
+	}
 }
 
diff --git a/alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.h b/alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.h
deleted file mode 100644
index 13eecedb83..0000000000
--- a/alib2algo/test-src/stringology/compression/ArithmeticCompressionTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _ARITHMETIC_COMPRESSION_TEST_H_
-#define _ARITHMETIC_COMPRESSION_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class ArithmeticCompressionTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( ArithmeticCompressionTest );
-  CPPUNIT_TEST( basics );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void basics();
-};
-
-#endif  // _ARITHMETIC_COMPRESSION_TEST_H_
diff --git a/alib2algo/test-src/stringology/compression/LZ77Test.cpp b/alib2algo/test-src/stringology/compression/LZ77Test.cpp
index 7d0d124a9e..10fa4b9e43 100644
--- a/alib2algo/test-src/stringology/compression/LZ77Test.cpp
+++ b/alib2algo/test-src/stringology/compression/LZ77Test.cpp
@@ -1,4 +1,4 @@
-#include "LZ77Test.h"
+#include <catch2/catch.hpp>
 
 #include <string/String.h>
 #include <stringology/compression/LZ77Compression.h>
@@ -7,105 +7,35 @@
 #include <iostream>
 #include <tuple>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( LZ77Test, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( LZ77Test );
 
-void LZ77Test::setUp ( ) {
-}
-
-void LZ77Test::tearDown ( ) {
-}
-
-void LZ77Test::testLZ77_1 ( ) {
-	std::string testStr = "aabaacaaaaaababab";
-
-	string::LinearString < char > string = string::stringFrom ( testStr );
-	std::vector < std::tuple < unsigned, unsigned, char > > res = stringology::compression::LZ77Compression::compress ( string, 6, 4 );
+TEST_CASE ( "LZ77 Compression", "[unit][algo][stringology][compression]" ) {
+	SECTION ( "Compress and Decompress" ) {
+		auto testcase = GENERATE (
+				std::make_pair ( "aabaacaaaaaababab", std::vector < std::tuple < unsigned, unsigned, char > > { std::make_tuple(0, 0, 'a' ), std::make_tuple(1, 1, 'b' ), std::make_tuple(3, 2, 'c' ), std::make_tuple(3, 2, 'a' ), std::make_tuple(1, 3, 'b' ), std::make_tuple(2, 3, 'b' ) } ),
+				std::make_pair ( "aacaacabcabaaac", std::vector < std::tuple < unsigned, unsigned, char > > { std::make_tuple(0, 0, 'a' ), std::make_tuple(1, 1, 'c' ), std::make_tuple(3, 4, 'b' ), std::make_tuple(3, 3, 'a' ), std::make_tuple(1, 2, 'c' ) } ) );
 
-	std::vector < std::tuple < unsigned, unsigned, char > > expectedOutput;
+		string::LinearString < char > string = string::stringFrom ( testcase.first );
+		std::vector < std::tuple < unsigned, unsigned, char > > res = stringology::compression::LZ77Compression::compress ( string, 6, 4 );
+		const std::vector < std::tuple < unsigned, unsigned, char > > & expectedOutput = testcase.second;
 
-	expectedOutput.push_back(std::make_tuple(0, 0, 'a' ) );
-	expectedOutput.push_back(std::make_tuple(1, 1, 'b' ) );
-	expectedOutput.push_back(std::make_tuple(3, 2, 'c' ) );
-	expectedOutput.push_back(std::make_tuple(3, 2, 'a' ) );
-	expectedOutput.push_back(std::make_tuple(1, 3, 'b' ) );
-	expectedOutput.push_back(std::make_tuple(2, 3, 'b' ) );
-
-	for ( const std::tuple < unsigned, unsigned, char > & resItem : res )
-		std::cout << std::get < 0 > ( resItem ) << " " << std::get < 1 > ( resItem ) << " " << std::get < 2 > ( resItem ) << std::endl;
-
-	CPPUNIT_ASSERT ( res == expectedOutput );
-
-}
-
-void LZ77Test::testLZ77_2 ( ) {
-
-	std::string testStr = "aacaacabcabaaac";
-
-	string::LinearString < char > string = string::stringFrom ( testStr );
-	std::vector < std::tuple < unsigned, unsigned, char > > res = stringology::compression::LZ77Compression::compress ( string, 6, 4 );
-
-	std::vector < std::tuple < unsigned, unsigned, char > > expectedOutput;
-
-	expectedOutput.push_back(std::make_tuple(0, 0, 'a' ) );
-	expectedOutput.push_back(std::make_tuple(1, 1, 'c' ) );
-	expectedOutput.push_back(std::make_tuple(3, 4, 'b' ) );
-	expectedOutput.push_back(std::make_tuple(3, 3, 'a' ) );
-	expectedOutput.push_back(std::make_tuple(1, 2, 'c' ) );
-
-	for ( const std::tuple < unsigned, unsigned, char > & resItem : res )
-		std::cout << std::get < 0 > ( resItem ) << " " << std::get < 1 > ( resItem ) << " " << std::get < 2 > ( resItem ) << std::endl;
-
-	CPPUNIT_ASSERT ( res == expectedOutput );
-}
-
-void LZ77Test::testLZ77Decompress1 ( ) {
-
-	std::vector < std::tuple < unsigned, unsigned, char > > input;
-
-	input.push_back(std::make_tuple(0, 0, 'a' ) );
-	input.push_back(std::make_tuple(1, 1, 'b' ) );
-	input.push_back(std::make_tuple(3, 2, 'c' ) );
-	input.push_back(std::make_tuple(3, 2, 'a' ) );
-	input.push_back(std::make_tuple(1, 3, 'b' ) );
-	input.push_back(std::make_tuple(2, 3, 'b' ) );
-
-	string::LinearString < char > res = stringology::compression::LZ77Decompression::decompress ( input );
-
-	std::string string = "aabaacaaaaaababab";
-	string::LinearString < char > expectedString = string::stringFrom ( string );
-
-	CPPUNIT_ASSERT ( res == expectedString );
-
-}
-
-void LZ77Test::testLZ77Decompress2 ( ) {
-
-	std::vector < std::tuple < unsigned, unsigned, char > > input;
-
-	input.push_back(std::make_tuple(0, 0, 'a' ) );
-	input.push_back(std::make_tuple(1, 1, 'c' ) );
-	input.push_back(std::make_tuple(3, 4, 'b' ) );
-	input.push_back(std::make_tuple(3, 3, 'a' ) );
-	input.push_back(std::make_tuple(1, 2, 'c' ) );
-
-	string::LinearString < char > res = stringology::compression::LZ77Decompression::decompress ( input );
-
-	std::string string = "aacaacabcabaaac";
-	string::LinearString < char > expectedString = string::stringFrom ( string );
-
-	CPPUNIT_ASSERT ( res == expectedString );
-
-}
+		/* compress */
+		for ( const std::tuple < unsigned, unsigned, char > & resItem : res )
+			INFO ( std::get < 0 > ( resItem ) << " " << std::get < 1 > ( resItem ) << " " << std::get < 2 > ( resItem ) );
 
-void LZ77Test::testLZ77Decompress3 ( ) {
+		CHECK ( res == expectedOutput );
 
-	std::string string = "";
-	string::LinearString < char > input = string::stringFrom ( string );
+		/* decompress */
+		string::LinearString < char > decompressed = stringology::compression::LZ77Decompression::decompress ( res );
+		CHECK ( decompressed == string );
+	}
 
-	std::vector < std::tuple < unsigned, unsigned, char > > out = stringology::compression::LZ77Compression::compress ( input, 6, 4 );
+	SECTION ( "Decompress" ) {
+		std::string string = "";
+		string::LinearString < char > input = string::stringFrom ( string );
 
-	string::LinearString < char > res = stringology::compression::LZ77Decompression::decompress ( out );
+		std::vector < std::tuple < unsigned, unsigned, char > > out = stringology::compression::LZ77Compression::compress ( input, 6, 4 );
+		string::LinearString < char > res = stringology::compression::LZ77Decompression::decompress ( out );
 
-	CPPUNIT_ASSERT ( input == res );
+		CHECK ( input == res );
+	}
 }
diff --git a/alib2algo/test-src/stringology/compression/LZ77Test.h b/alib2algo/test-src/stringology/compression/LZ77Test.h
deleted file mode 100644
index 823c3036b7..0000000000
--- a/alib2algo/test-src/stringology/compression/LZ77Test.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef LZ77_TEST
-#define LZ77_TEST
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class LZ77Test : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE ( LZ77Test );
-	CPPUNIT_TEST ( testLZ77_1 );
-	CPPUNIT_TEST ( testLZ77_2 );
-	CPPUNIT_TEST ( testLZ77Decompress1 );
-	CPPUNIT_TEST ( testLZ77Decompress2 );
-	CPPUNIT_TEST ( testLZ77Decompress3 );
-	CPPUNIT_TEST_SUITE_END ( );
-
-public:
-	void setUp ( );
-	void tearDown ( );
-
-	void testLZ77_1 ( );
-	void testLZ77_2 ( );
-
-	void testLZ77Decompress1 ( );
-	void testLZ77Decompress2 ( );
-	void testLZ77Decompress3 ( );
-};
-
-#endif // LZ77_TEST
diff --git a/alib2algo/test-src/stringology/exact/stringMatchTest.cpp b/alib2algo/test-src/stringology/exact/stringMatchTest.cpp
index cc261c88c9..c06196cde1 100644
--- a/alib2algo/test-src/stringology/exact/stringMatchTest.cpp
+++ b/alib2algo/test-src/stringology/exact/stringMatchTest.cpp
@@ -1,22 +1,13 @@
-#include <alib/list>
-#include "stringMatchTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/exact/ExactFactorMatch.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( stringMatchTest, "string" );
-CPPUNIT_TEST_SUITE_REGISTRATION( stringMatchTest );
+TEST_CASE ( "Exact String Match", "[unit][algo][stringology][exact]" ) {
+	SECTION ( "Basic" ) {
+		string::LinearString < > linear1({DefaultSymbolType(0), DefaultSymbolType(1), DefaultSymbolType(2), DefaultSymbolType(3)});
+		string::LinearString < > linear2({DefaultSymbolType(1), DefaultSymbolType(2), DefaultSymbolType(3)});
 
-void stringMatchTest::setUp() {
+		CHECK ( stringology::exact::ExactFactorMatch::match ( linear1, linear2 ).count ( 1u ) );
+	}
 }
-
-void stringMatchTest::tearDown() {
-}
-
-void stringMatchTest::testStringMatch() {
-	string::LinearString < > linear1({DefaultSymbolType(0), DefaultSymbolType(1), DefaultSymbolType(2), DefaultSymbolType(3)});
-	string::LinearString < > linear2({DefaultSymbolType(1), DefaultSymbolType(2), DefaultSymbolType(3)});
-
-	CPPUNIT_ASSERT ( stringology::exact::ExactFactorMatch::match ( linear1, linear2 ).count ( 1u ) );
-}
-
diff --git a/alib2algo/test-src/stringology/exact/stringMatchTest.h b/alib2algo/test-src/stringology/exact/stringMatchTest.h
deleted file mode 100644
index 6af90ab70b..0000000000
--- a/alib2algo/test-src/stringology/exact/stringMatchTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef STRING_MATCH_TEST_H_
-#define STRING_MATCH_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class stringMatchTest : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE( stringMatchTest );
-  CPPUNIT_TEST( testStringMatch );
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-  void setUp();
-  void tearDown();
-
-  void testStringMatch();
-};
-
-#endif  // STRING_MATCH_TEST_H_
diff --git a/alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.cpp b/alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.cpp
index 1a76d9579e..8b809092fd 100644
--- a/alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.cpp
@@ -1,51 +1,41 @@
-#include "ExactSuffixAutomatonTest.h"
+#include <catch2/catch.hpp>
 
 #include "string/LinearString.h"
 #include "stringology/indexing/ExactSuffixAutomaton.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( ExactSuffixAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( ExactSuffixAutomatonTest );
+TEST_CASE ( "Exact Suffix Automaton", "[unit][algo][stringology][indexing]" ) {
+	SECTION ( "Test construction" ) {
 
-void ExactSuffixAutomatonTest::setUp ( ) {
-}
-
-void ExactSuffixAutomatonTest::tearDown ( ) {
-}
-
-void ExactSuffixAutomatonTest::testSuffixAutomatonConstruction ( ) {
+		string::LinearString < char > pattern ( "atatac" );
 
-	string::LinearString < char > pattern ( "atatac" );
+		indexes::stringology::SuffixAutomaton < char > suffixAutomaton = stringology::indexing::ExactSuffixAutomaton::construct ( pattern );
 
-	indexes::stringology::SuffixAutomaton < char > suffixAutomaton = stringology::indexing::ExactSuffixAutomaton::construct ( pattern );
+		automaton::DFA < char, unsigned > tmp ( 0 );
 
-	automaton::DFA < char, unsigned > tmp ( 0 );
+		tmp.setInputAlphabet ( pattern.getAlphabet ( ) );
 
-	tmp.setInputAlphabet ( pattern.getAlphabet ( ) );
+		for ( unsigned i = 1; i <= 6; ++i ) {
+			tmp.addState ( i );
+		}
 
-	for ( unsigned i = 1; i <= 6; ++i ) {
-		tmp.addState ( i );
-	}
-
-	tmp.addFinalState ( 0 );
-	tmp.addFinalState ( 6 );
+		tmp.addFinalState ( 0 );
+		tmp.addFinalState ( 6 );
 
-	tmp.addTransition ( 0, 'a', 1 );
-	tmp.addTransition ( 0, 't', 2 );
-	tmp.addTransition ( 0, 'c', 6 );
-	tmp.addTransition ( 1, 't', 2 );
-	tmp.addTransition ( 1, 'c', 6 );
-	tmp.addTransition ( 2, 'a', 3 );
-	tmp.addTransition ( 3, 't', 4 );
-	tmp.addTransition ( 3, 'c', 6 );
-	tmp.addTransition ( 4, 'a', 5 );
-	tmp.addTransition ( 5, 'c', 6 );
+		tmp.addTransition ( 0, 'a', 1 );
+		tmp.addTransition ( 0, 't', 2 );
+		tmp.addTransition ( 0, 'c', 6 );
+		tmp.addTransition ( 1, 't', 2 );
+		tmp.addTransition ( 1, 'c', 6 );
+		tmp.addTransition ( 2, 'a', 3 );
+		tmp.addTransition ( 3, 't', 4 );
+		tmp.addTransition ( 3, 'c', 6 );
+		tmp.addTransition ( 4, 'a', 5 );
+		tmp.addTransition ( 5, 'c', 6 );
 
-	indexes::stringology::SuffixAutomaton < char > refSuffixAutomaton ( std::move ( tmp ), 6 );
+		indexes::stringology::SuffixAutomaton < char > refSuffixAutomaton ( std::move ( tmp ), 6 );
 
-	std::cout << suffixAutomaton << std::endl;
-	std::cout << refSuffixAutomaton << std::endl;
+		CHECK ( suffixAutomaton == refSuffixAutomaton );
 
-	CPPUNIT_ASSERT ( suffixAutomaton == refSuffixAutomaton );
-
-	core::normalize < indexes::stringology::SuffixAutomaton < char > >::eval ( std::move ( refSuffixAutomaton ) );
+		core::normalize < indexes::stringology::SuffixAutomaton < char > >::eval ( std::move ( refSuffixAutomaton ) );
+	}
 }
diff --git a/alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.h b/alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.h
deleted file mode 100644
index eabe1ac832..0000000000
--- a/alib2algo/test-src/stringology/indexing/ExactSuffixAutomatonTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef EXACT_SUFFIX_AUTOMATON_TEST_H_
-#define EXACT_SUFFIX_AUTOMATON_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class ExactSuffixAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE ( ExactSuffixAutomatonTest );
-	CPPUNIT_TEST ( testSuffixAutomatonConstruction );
-	CPPUNIT_TEST_SUITE_END ( );
-
-public:
-	void setUp ( );
-	void tearDown ( );
-
-	void testSuffixAutomatonConstruction ( );
-
-};
-
-#endif // EXACT_SUFFIX_AUTOMATON_TEST_H_
diff --git a/alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.cpp b/alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.cpp
index 8a7c184ef3..0e440e9fcd 100644
--- a/alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.cpp
@@ -1,47 +1,40 @@
-#include "FactorOracleAutomatonTest.h"
+#include <catch2/catch.hpp>
 
 #include "string/LinearString.h"
 #include "stringology/indexing/ExactFactorOracleAutomaton.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( FactorOracleAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( FactorOracleAutomatonTest );
+TEST_CASE ( "Factor Oracle Automaton", "[unit][algo][stringology][indexing]" ) {
+	SECTION ( "Test construction" ) {
+		string::LinearString < char > pattern ( "atatac" );
 
-void FactorOracleAutomatonTest::setUp ( ) {
-}
-
-void FactorOracleAutomatonTest::tearDown ( ) {
-}
+		indexes::stringology::FactorOracleAutomaton < char > oracle = stringology::indexing::ExactFactorOracleAutomaton::construct ( pattern );
 
-void FactorOracleAutomatonTest::testFactorOracleConstruction ( ) {
-	string::LinearString < char > pattern ( "atatac" );
+		automaton::DFA < char, unsigned > tmp ( 0 );
 
-	indexes::stringology::FactorOracleAutomaton < char > oracle = stringology::indexing::ExactFactorOracleAutomaton::construct ( pattern );
+		tmp.addFinalState ( 0 );
 
-	automaton::DFA < char, unsigned > tmp ( 0 );
+		tmp.setInputAlphabet ( pattern.getAlphabet ( ) );
 
-	tmp.addFinalState ( 0 );
+		for ( int i = 1; i <= 6; ++i ) {
+			tmp.addState ( i );
+			tmp.addFinalState ( i );
+		}
 
-	tmp.setInputAlphabet ( pattern.getAlphabet ( ) );
+		tmp.addTransition ( 0, 'a', 1 );
+		tmp.addTransition ( 0, 't', 2 );
+		tmp.addTransition ( 0, 'c', 6 );
+		tmp.addTransition ( 1, 't', 2 );
+		tmp.addTransition ( 1, 'c', 6 );
+		tmp.addTransition ( 2, 'a', 3 );
+		tmp.addTransition ( 3, 't', 4 );
+		tmp.addTransition ( 3, 'c', 6 );
+		tmp.addTransition ( 4, 'a', 5 );
+		tmp.addTransition ( 5, 'c', 6 );
 
-	for ( int i = 1; i <= 6; ++i ) {
-		tmp.addState ( i );
-		tmp.addFinalState ( i );
-	}
+		indexes::stringology::FactorOracleAutomaton < char > refOracle ( std::move ( tmp ) );
 
-	tmp.addTransition ( 0, 'a', 1 );
-	tmp.addTransition ( 0, 't', 2 );
-	tmp.addTransition ( 0, 'c', 6 );
-	tmp.addTransition ( 1, 't', 2 );
-	tmp.addTransition ( 1, 'c', 6 );
-	tmp.addTransition ( 2, 'a', 3 );
-	tmp.addTransition ( 3, 't', 4 );
-	tmp.addTransition ( 3, 'c', 6 );
-	tmp.addTransition ( 4, 'a', 5 );
-	tmp.addTransition ( 5, 'c', 6 );
+		CHECK ( oracle == refOracle );
 
-	indexes::stringology::FactorOracleAutomaton < char > refOracle ( std::move ( tmp ) );
-
-	CPPUNIT_ASSERT ( oracle == refOracle );
-
-	core::normalize < indexes::stringology::FactorOracleAutomaton < char > >::eval ( std::move ( refOracle ) );
+		core::normalize < indexes::stringology::FactorOracleAutomaton < char > >::eval ( std::move ( refOracle ) );
+	}
 }
diff --git a/alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.h b/alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.h
deleted file mode 100644
index 3252d2be45..0000000000
--- a/alib2algo/test-src/stringology/indexing/FactorOracleAutomatonTest.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef FACTOR_ORACLE_AUTOMATON_TEST_HPP_
-#define FACTOR_ORACLE_AUTOMATON_TEST_HPP_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class FactorOracleAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE ( FactorOracleAutomatonTest );
-	CPPUNIT_TEST ( testFactorOracleConstruction );
-	CPPUNIT_TEST_SUITE_END ( );
-
-public:
-	void setUp ( );
-	void tearDown ( );
-
-	void testFactorOracleConstruction ( );
-};
-
-#endif // FACTOR_ORACLE_AUTOMATON_TEST_HPP_
diff --git a/alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.cpp b/alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.cpp
index e85af2b1f0..8fb8f7d8a6 100644
--- a/alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.cpp
+++ b/alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.cpp
@@ -1,4 +1,4 @@
-#include "BackwardNondeterministicDAWGMatchingTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/String.h>
 #include <stringology/matching/WideBNDMMatcherConstruction.h>
@@ -10,47 +10,39 @@
 #include <string/generate/RandomStringFactory.h>
 #include <string/generate/RandomSubstringFactory.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( BackwardNondeterministicDAWGMatchingTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( BackwardNondeterministicDAWGMatchingTest );
-
-void BackwardNondeterministicDAWGMatchingTest::setUp ( ) {
-}
-
-void BackwardNondeterministicDAWGMatchingTest::tearDown ( ) {
-}
-
-void BackwardNondeterministicDAWGMatchingTest::testBNDM ( ) {
-
-	ext::vector<std::string> subjects;
-	ext::vector<std::string> patterns;
-	ext::vector<ext::set<unsigned>> expectedOccs;
-
-	subjects.push_back("a"); patterns.push_back("a"); expectedOccs.push_back({0});
-	subjects.push_back("a"); patterns.push_back("b"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfa"); expectedOccs.push_back({0});
-	subjects.push_back("alfalfalfa"); patterns.push_back("blfalfalfa"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfb"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({0});
-	subjects.push_back("alfalfalfaalfalfalfaabfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); expectedOccs.push_back({0});
-	subjects.push_back("atggccttgcc"); patterns.push_back("gcc"); expectedOccs.push_back({3,8});
-	subjects.push_back("aaaaaaaaaa"); patterns.push_back("a"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8,9});
-
-	for(size_t i = 0; i < subjects.size(); ++i) {
-		indexes::stringology::BitParallelIndex < char > bndmPattern1 = stringology::matching::WideBNDMMatcherConstruction::construct ( string::LinearString < char > ( patterns[i] ) );
-		indexes::stringology::BitSetIndex < char > bndmPattern2 = stringology::matching::BNDMMatcherConstruction::construct ( string::LinearString < char > ( patterns[i] ) );
-		ext::set < unsigned > res1 = stringology::query::WideBNDMOccurrences::query ( bndmPattern1, string::LinearString < char > ( subjects[i] ) );
-		ext::set < unsigned > res2 = stringology::query::BNDMOccurrences::query ( bndmPattern2, string::LinearString < char > ( subjects[i] ) );
-		CPPUNIT_ASSERT ( res1 == expectedOccs[i] );
-		CPPUNIT_ASSERT ( res2 == expectedOccs[i] );
-		std::cout << subjects[i] << ' ' << patterns[i] << ' ' << res1 << std::endl;
+TEST_CASE ( "Backward Nondeterministic DAWG", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Simple" ) {
+		ext::vector<std::string> subjects;
+		ext::vector<std::string> patterns;
+		ext::vector<ext::set<unsigned>> expectedOccs;
+
+		subjects.push_back("a"); patterns.push_back("a"); expectedOccs.push_back({0});
+		subjects.push_back("a"); patterns.push_back("b"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfa"); expectedOccs.push_back({0});
+		subjects.push_back("alfalfalfa"); patterns.push_back("blfalfalfa"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfb"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({0});
+		subjects.push_back("alfalfalfaalfalfalfaabfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); expectedOccs.push_back({0});
+		subjects.push_back("atggccttgcc"); patterns.push_back("gcc"); expectedOccs.push_back({3,8});
+		subjects.push_back("aaaaaaaaaa"); patterns.push_back("a"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8,9});
+
+		for(size_t i = 0; i < subjects.size(); ++i) {
+			indexes::stringology::BitParallelIndex < char > bndmPattern1 = stringology::matching::WideBNDMMatcherConstruction::construct ( string::LinearString < char > ( patterns[i] ) );
+			indexes::stringology::BitSetIndex < char > bndmPattern2 = stringology::matching::BNDMMatcherConstruction::construct ( string::LinearString < char > ( patterns[i] ) );
+			ext::set < unsigned > res1 = stringology::query::WideBNDMOccurrences::query ( bndmPattern1, string::LinearString < char > ( subjects[i] ) );
+			ext::set < unsigned > res2 = stringology::query::BNDMOccurrences::query ( bndmPattern2, string::LinearString < char > ( subjects[i] ) );
+			CHECK ( res1 == expectedOccs[i] );
+			CHECK ( res2 == expectedOccs[i] );
+			INFO ( subjects[i] << ' ' << patterns[i] << ' ' << res1 );
+		}
+
+		auto longSubject = string::generate::RandomStringFactory::generateLinearString (64 * 64 * 64, 512, false, true);
+		auto longPattern = string::generate::RandomSubstringFactory::generateSubstring(64 * 32 * 32, longSubject );
+		indexes::stringology::BitSetIndex < std::string > pattern = stringology::matching::BNDMMatcherConstruction::construct ( longPattern );
+		ext::set < unsigned > res = stringology::query::BNDMOccurrences::query ( pattern, longSubject );
+		ext::set < unsigned > ref = stringology::exact::ExactFactorMatch::match ( longSubject, longPattern );
+		INFO ( "long: " << res );
+		CHECK ( res == ref);
 	}
-
-	auto longSubject = string::generate::RandomStringFactory::generateLinearString (64 * 64 * 64, 512, false, true);
-	auto longPattern = string::generate::RandomSubstringFactory::generateSubstring(64 * 32 * 32, longSubject );
-	indexes::stringology::BitSetIndex < std::string > pattern = stringology::matching::BNDMMatcherConstruction::construct ( longPattern );
-	ext::set < unsigned > res = stringology::query::BNDMOccurrences::query ( pattern, longSubject );
-	ext::set < unsigned > ref = stringology::exact::ExactFactorMatch::match ( longSubject, longPattern );
-	std::cout << "long: " << res << std::endl;
-	CPPUNIT_ASSERT ( res == ref);
 }
diff --git a/alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.h b/alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.h
deleted file mode 100644
index 9d50ac034b..0000000000
--- a/alib2algo/test-src/stringology/matching/BackwardNondeterministicDAWGMatchingTest.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef BACKWARD_NONDETERMINISTIC_DAWG_MATCHING_TEST_H_
-#define BACKWARD_NONDETERMINISTIC_DAWG_MATCHING_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class BackwardNondeterministicDAWGMatchingTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE ( BackwardNondeterministicDAWGMatchingTest );
-	CPPUNIT_TEST ( testBNDM );
-	CPPUNIT_TEST_SUITE_END ( );
-
-public:
-	void setUp ( );
-	void tearDown ( );
-
-	void testBNDM ( );
-};
-
-#endif // BACKWARD_NONDETERMINISTIC_DAWG_MATCHING_TEST_H_
diff --git a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.cpp b/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.cpp
index d7d3f42196..75cf2ef3b1 100644
--- a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.cpp
@@ -1,186 +1,180 @@
+#include <catch2/catch.hpp>
+
 #include <stringology/matching/GeneralizedLevenshteinMatchingAutomaton.h>
 #include <automaton/FSM/EpsilonNFA.h>
 #include <string/LinearString.h>
 #include <automaton/simplify/UnreachableStatesRemover.h>
 
-#include "GeneralizedLevenshteinMatchingAutomatonTest.h"
-
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( GeneralizedLevenshteinMatchingAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( GeneralizedLevenshteinMatchingAutomatonTest );
+TEST_CASE ( "Generalized Levenshtein Matching Automaton", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Test construction" ) {
+		ext::set<char> alphabet{'a', 'b', 'c', 'd'};
+		string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
+		auto resulting_automata = stringology::matching::GeneralizedLevenshteinMatchingAutomaton::construct(input_string, 2);
 
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-void GeneralizedLevenshteinMatchingAutomatonTest::testSimpleConstruction() {
-    ext::set<char> alphabet{'a', 'b', 'c', 'd'};
-    string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
-    auto resulting_automata = stringology::matching::GeneralizedLevenshteinMatchingAutomaton::construct(input_string, 2);
+		automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
 
-    typedef ext::pair<unsigned int, unsigned int> State;
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-    automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
-    res.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+		State r3 = ext::make_pair(5,1);
+		State r2 = ext::make_pair(5,0);
+		State r1 = ext::make_pair(4,0);
 
-    State q0 = ext::make_pair(0,0);
-    State q1 = ext::make_pair(1,0);
-    State q2 = ext::make_pair(2,0);
-    State q3 = ext::make_pair(3,0);
-    State q4 = ext::make_pair(1,1);
-    State q5 = ext::make_pair(2,1);
-    State q6 = ext::make_pair(3,1);
-    State q7 = ext::make_pair(2,2);
-    State q8 = ext::make_pair(3,2);
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
+		res.setFinalStates(ext::set<State> {q3, q6, q8});
 
-    State r3 = ext::make_pair(5,1);
-    State r2 = ext::make_pair(5,0);
-    State r1 = ext::make_pair(4,0);
+		res.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
 
-    res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
-    res.setFinalStates(ext::set<State> {q3, q6, q8});
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'b', q5);
 
-    res.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
+		res.addTransition(q2, 'c', q3);
+		res.addTransition(q5, 'c', q6);
+		res.addTransition(q7, 'c', q8);
 
-    res.addTransition(q1, 'b', q2);
-    res.addTransition(q4, 'b', q5);
+		res.addTransition(q0, 'a', q0); // loops in initial state
+		res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'c', q0);
+		res.addTransition(q0, 'd', q0);
 
-    res.addTransition(q2, 'c', q3);
-    res.addTransition(q5, 'c', q6);
-    res.addTransition(q7, 'c', q8);
+		res.addTransition(q0, 'b', q4); // diagonal transitions representing replace
+		res.addTransition(q0, 'c', q4);
+		res.addTransition(q0, 'd', q4);
 
-    res.addTransition(q0, 'a', q0); // loops in initial state
-    res.addTransition(q0, 'b', q0);
-    res.addTransition(q0, 'c', q0);
-    res.addTransition(q0, 'd', q0);
+		res.addTransition(q0, q4); // deletion
 
-    res.addTransition(q0, 'b', q4); // diagonal transitions representing replace
-    res.addTransition(q0, 'c', q4);
-    res.addTransition(q0, 'd', q4);
+		res.addTransition(q1, 'a', q5);
+		res.addTransition(q1, 'c', q5);
+		res.addTransition(q1, 'd', q5);
+		res.addTransition(q4, 'a', q7);
+		res.addTransition(q4, 'c', q7);
+		res.addTransition(q4, 'd', q7);
 
-    res.addTransition(q0, q4); // deletion
+		res.addTransition(q1, q5); // deletion
+		res.addTransition(q4, q7);
 
-    res.addTransition(q1, 'a', q5);
-    res.addTransition(q1, 'c', q5);
-    res.addTransition(q1, 'd', q5);
-    res.addTransition(q4, 'a', q7);
-    res.addTransition(q4, 'c', q7);
-    res.addTransition(q4, 'd', q7);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q2, 'b', q6);
+		res.addTransition(q2, 'd', q6);
+		res.addTransition(q5, 'a', q8);
+		res.addTransition(q5, 'b', q8);
+		res.addTransition(q5, 'd', q8);
 
-    res.addTransition(q1, q5); // deletion
-    res.addTransition(q4, q7);
+		res.addTransition(q2, q6); // deletion
+		res.addTransition(q5, q8);
 
-    res.addTransition(q2, 'a', q6);
-    res.addTransition(q2, 'b', q6);
-    res.addTransition(q2, 'd', q6);
-    res.addTransition(q5, 'a', q8);
-    res.addTransition(q5, 'b', q8);
-    res.addTransition(q5, 'd', q8);
+		res.addTransition(q1, 'a', q4); // insertions
+		res.addTransition(q1, 'b', q4);
+		res.addTransition(q1, 'c', q4);
+		res.addTransition(q1, 'd', q4);
 
-    res.addTransition(q2, q6); // deletion
-    res.addTransition(q5, q8);
+		res.addTransition(q2, 'a', q5);
+		res.addTransition(q2, 'b', q5);
+		res.addTransition(q2, 'c', q5);
+		res.addTransition(q2, 'd', q5);
 
-    res.addTransition(q1, 'a', q4); // insertions
-    res.addTransition(q1, 'b', q4);
-    res.addTransition(q1, 'c', q4);
-    res.addTransition(q1, 'd', q4);
+		res.addTransition(q5, 'a', q7);
+		res.addTransition(q5, 'b', q7);
+		res.addTransition(q5, 'c', q7);
+		res.addTransition(q5, 'd', q7);
 
-    res.addTransition(q2, 'a', q5);
-    res.addTransition(q2, 'b', q5);
-    res.addTransition(q2, 'c', q5);
-    res.addTransition(q2, 'd', q5);
+		res.addTransition(q0, 'b', r1); // transposition
+		res.addTransition(r1, 'a', q5);
 
-    res.addTransition(q5, 'a', q7);
-    res.addTransition(q5, 'b', q7);
-    res.addTransition(q5, 'c', q7);
-    res.addTransition(q5, 'd', q7);
+		res.addTransition(q1, 'c', r2);
+		res.addTransition(r2, 'b', q6);
 
-    res.addTransition(q0, 'b', r1); // transposition
-    res.addTransition(r1, 'a', q5);
+		res.addTransition(q4, 'c', r3);
+		res.addTransition(r3, 'b', q8);
 
-    res.addTransition(q1, 'c', r2);
-    res.addTransition(r2, 'b', q6);
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 
-    res.addTransition(q4, 'c', r3);
-    res.addTransition(r3, 'b', q8);
-
-    CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
-}
+	SECTION ( "Test Wildcard construction" ) {
+		ext::set<char> alphabet{'a', 'b', '@'};
+		string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
+		auto resulting_automata = stringology::matching::GeneralizedLevenshteinMatchingAutomaton::construct(input_string, 2);
 
-void GeneralizedLevenshteinMatchingAutomatonTest::testSimpleWildcardConstruction() {
-  ext::set<char> alphabet{'a', 'b', '@'};
-  string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
-  auto resulting_automata = stringology::matching::GeneralizedLevenshteinMatchingAutomaton::construct(input_string, 2);
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-  typedef ext::pair<unsigned int, unsigned int> State;
+		automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(alphabet);
 
-  automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
-  res.setInputAlphabet(alphabet);
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(2,2);
-  State q8 = ext::make_pair(3,2);
+		State r3 = ext::make_pair(5,1);
+		State r2 = ext::make_pair(5,0);
+		State r1 = ext::make_pair(4,0);
 
-  State r3 = ext::make_pair(5,1);
-  State r2 = ext::make_pair(5,0);
-  State r1 = ext::make_pair(4,0);
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
+		res.setFinalStates(ext::set<State> {q3, q6, q8});
 
-  res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
-  res.setFinalStates(ext::set<State> {q3, q6, q8});
+		res.addTransition(q0, 'a', q0); // initial loops
+		res.addTransition(q0, 'b', q0);
 
-  res.addTransition(q0, 'a', q0); // initial loops
-  res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'a', q1); // 3 simple matching automatas
 
-  res.addTransition(q0, 'a', q1); // 3 simple matching automatas
+		res.addTransition(q1, 'a', q2);
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'a', q5);
+		res.addTransition(q4, 'b', q5);
 
-  res.addTransition(q1, 'a', q2);
-  res.addTransition(q1, 'b', q2);
-  res.addTransition(q4, 'a', q5);
-  res.addTransition(q4, 'b', q5);
+		res.addTransition(q2, 'b', q3);
+		res.addTransition(q5, 'b', q6);
+		res.addTransition(q7, 'b', q8);
 
-  res.addTransition(q2, 'b', q3);
-  res.addTransition(q5, 'b', q6);
-  res.addTransition(q7, 'b', q8);
+		res.addTransition(q0, 'b', q4); // error transitions for replace
 
-  res.addTransition(q0, 'b', q4); // error transitions for replace
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q5, 'a', q8);
 
-  res.addTransition(q2, 'a', q6);
-  res.addTransition(q5, 'a', q8);
+		res.addTransition(q0, q4); // delete transition
+		res.addTransition(q1, q5);
+		res.addTransition(q2, q6);
 
-  res.addTransition(q0, q4); // delete transition
-  res.addTransition(q1, q5);
-  res.addTransition(q2, q6);
+		res.addTransition(q4, q7);
+		res.addTransition(q5, q8);
 
-  res.addTransition(q4, q7);
-  res.addTransition(q5, q8);
+		res.addTransition(q1, 'a', q4); // insert transitions
+		res.addTransition(q1, 'b', q4);
 
-  res.addTransition(q1, 'a', q4); // insert transitions
-  res.addTransition(q1, 'b', q4);
+		res.addTransition(q2, 'a', q5);
+		res.addTransition(q2, 'b', q5);
 
-  res.addTransition(q2, 'a', q5);
-  res.addTransition(q2, 'b', q5);
+		res.addTransition(q5, 'a', q7);
+		res.addTransition(q5, 'b', q7);
 
-  res.addTransition(q5, 'a', q7);
-  res.addTransition(q5, 'b', q7);
+		res.addTransition(q0, 'a', r1); // transpose states
+		res.addTransition(q0, 'b', r1);
+		res.addTransition(r1, 'a', q5);
 
-  res.addTransition(q0, 'a', r1); // transpose states
-  res.addTransition(q0, 'b', r1);
-  res.addTransition(r1, 'a', q5);
+		res.addTransition(q1, 'b', r2);
+		res.addTransition(r2, 'a', q6);
+		res.addTransition(r2, 'b', q6);
 
-  res.addTransition(q1, 'b', r2);
-  res.addTransition(r2, 'a', q6);
-  res.addTransition(r2, 'b', q6);
+		res.addTransition(q4, 'b', r3);
+		res.addTransition(r3, 'a', q8);
+		res.addTransition(r3, 'b', q8);
 
-  res.addTransition(q4, 'b', r3);
-  res.addTransition(r3, 'a', q8);
-  res.addTransition(r3, 'b', q8);
-
-  CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 }
-
-void GeneralizedLevenshteinMatchingAutomatonTest::setUp() { }
-
-void GeneralizedLevenshteinMatchingAutomatonTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.h b/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.h
deleted file mode 100644
index c09ed1d87f..0000000000
--- a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinMatchingAutomatonTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef HAMMING_MATCHING_AUTOMATA_TEST_H_
-#define HAMMING_MATCHING_AUTOMATA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GeneralizedLevenshteinMatchingAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(GeneralizedLevenshteinMatchingAutomatonTest);
-    CPPUNIT_TEST(testSimpleConstruction);
-		CPPUNIT_TEST(testSimpleWildcardConstruction);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimpleConstruction();
-		void testSimpleWildcardConstruction();
-};
-#endif //HAMMING_MATCHING_AUTOMATA_TEST_H_
diff --git a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.cpp b/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.cpp
index 01e2aa26ae..2491838f5a 100644
--- a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.cpp
@@ -1,223 +1,217 @@
+#include <catch2/catch.hpp>
+
 #include <stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomaton.h>
 #include <automaton/FSM/NFA.h>
 #include <string/LinearString.h>
 #include <automaton/simplify/UnreachableStatesRemover.h>
 
-#include "GeneralizedLevenshteinSequenceMatchingAutomatonTest.h"
-
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( GeneralizedLevenshteinSequenceMatchingAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( GeneralizedLevenshteinSequenceMatchingAutomatonTest );
-
-void GeneralizedLevenshteinSequenceMatchingAutomatonTest::testSimpleConstruction() {
-  ext::set<char> alphabet{'a', 'b', 'c', 'd'};
-  string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
-  auto resulting_automata = stringology::matching::GeneralizedLevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
-
-  typedef ext::pair<unsigned int, unsigned int> State;
+TEST_CASE ( "Generalized Levenshtein Sequence Matching Automaton", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Test construction" ) {
+		ext::set<char> alphabet{'a', 'b', 'c', 'd'};
+		string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
+		auto resulting_automata = stringology::matching::GeneralizedLevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
 
-  automaton::EpsilonNFA < char, void, State > test(ext::make_pair(0,0));
-  test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+		typedef ext::pair<unsigned int, unsigned int> State;
+
+		automaton::EpsilonNFA < char, void, State > test(ext::make_pair(0,0));
+		test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(2,2);
-  State q8 = ext::make_pair(3,2);
+		State r3 = ext::make_pair(5,1);
+		State r2 = ext::make_pair(5,0);
+		State r1 = ext::make_pair(4,0);
 
-  State r3 = ext::make_pair(5,1);
-  State r2 = ext::make_pair(5,0);
-  State r1 = ext::make_pair(4,0);
+		test.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
+		test.setFinalStates(ext::set<State> {q3, q6, q8});
 
-  test.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
-  test.setFinalStates(ext::set<State> {q3, q6, q8});
+		test.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
 
-  test.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
+		test.addTransition(q1, 'b', q2);
+		test.addTransition(q4, 'b', q5);
 
-  test.addTransition(q1, 'b', q2);
-  test.addTransition(q4, 'b', q5);
+		test.addTransition(q2, 'c', q3);
+		test.addTransition(q5, 'c', q6);
+		test.addTransition(q7, 'c', q8);
 
-  test.addTransition(q2, 'c', q3);
-  test.addTransition(q5, 'c', q6);
-  test.addTransition(q7, 'c', q8);
+		test.addTransition(q0, 'a', q0); // loops in initial state
+		test.addTransition(q0, 'b', q0);
+		test.addTransition(q0, 'c', q0);
+		test.addTransition(q0, 'd', q0);
 
-  test.addTransition(q0, 'a', q0); // loops in initial state
-  test.addTransition(q0, 'b', q0);
-  test.addTransition(q0, 'c', q0);
-  test.addTransition(q0, 'd', q0);
+		test.addTransition(q0, 'b', q4); // diagonal transitions reptestenting replace
+		test.addTransition(q0, 'c', q4);
+		test.addTransition(q0, 'd', q4);
+
+		test.addTransition(q0, q4); // deletion
+
+		test.addTransition(q1, 'a', q5);
+		test.addTransition(q1, 'c', q5);
+		test.addTransition(q1, 'd', q5);
+		test.addTransition(q4, 'a', q7);
+		test.addTransition(q4, 'c', q7);
+		test.addTransition(q4, 'd', q7);
+
+		test.addTransition(q1, q5); // deletion
+		test.addTransition(q4, q7);
 
-  test.addTransition(q0, 'b', q4); // diagonal transitions reptestenting replace
-  test.addTransition(q0, 'c', q4);
-  test.addTransition(q0, 'd', q4);
+		test.addTransition(q2, 'a', q6);
+		test.addTransition(q2, 'b', q6);
+		test.addTransition(q2, 'd', q6);
+		test.addTransition(q5, 'a', q8);
+		test.addTransition(q5, 'b', q8);
+		test.addTransition(q5, 'd', q8);
 
-  test.addTransition(q0, q4); // deletion
+		test.addTransition(q2, q6); // deletion
+		test.addTransition(q5, q8);
 
-  test.addTransition(q1, 'a', q5);
-  test.addTransition(q1, 'c', q5);
-  test.addTransition(q1, 'd', q5);
-  test.addTransition(q4, 'a', q7);
-  test.addTransition(q4, 'c', q7);
-  test.addTransition(q4, 'd', q7);
+		test.addTransition(q1, 'a', q4); // insertions
+		test.addTransition(q1, 'b', q4);
+		test.addTransition(q1, 'c', q4);
+		test.addTransition(q1, 'd', q4);
 
-  test.addTransition(q1, q5); // deletion
-  test.addTransition(q4, q7);
+		test.addTransition(q2, 'a', q5);
+		test.addTransition(q2, 'b', q5);
+		test.addTransition(q2, 'c', q5);
+		test.addTransition(q2, 'd', q5);
 
-  test.addTransition(q2, 'a', q6);
-  test.addTransition(q2, 'b', q6);
-  test.addTransition(q2, 'd', q6);
-  test.addTransition(q5, 'a', q8);
-  test.addTransition(q5, 'b', q8);
-  test.addTransition(q5, 'd', q8);
+		test.addTransition(q5, 'a', q7);
+		test.addTransition(q5, 'b', q7);
+		test.addTransition(q5, 'c', q7);
+		test.addTransition(q5, 'd', q7);
 
-  test.addTransition(q2, q6); // deletion
-  test.addTransition(q5, q8);
+		test.addTransition(q1, 'a', q1); // loops for sequence matching
+		test.addTransition(q1, 'c', q1);
+		test.addTransition(q1, 'd', q1);
 
-  test.addTransition(q1, 'a', q4); // insertions
-  test.addTransition(q1, 'b', q4);
-  test.addTransition(q1, 'c', q4);
-  test.addTransition(q1, 'd', q4);
+		test.addTransition(q2, 'a', q2);
+		test.addTransition(q2, 'b', q2);
+		test.addTransition(q2, 'd', q2);
 
-  test.addTransition(q2, 'a', q5);
-  test.addTransition(q2, 'b', q5);
-  test.addTransition(q2, 'c', q5);
-  test.addTransition(q2, 'd', q5);
+		test.addTransition(q4, 'a', q4);
+		test.addTransition(q4, 'c', q4);
+		test.addTransition(q4, 'd', q4);
 
-  test.addTransition(q5, 'a', q7);
-  test.addTransition(q5, 'b', q7);
-  test.addTransition(q5, 'c', q7);
-  test.addTransition(q5, 'd', q7);
+		test.addTransition(q5, 'a', q5);
+		test.addTransition(q5, 'b', q5);
+		test.addTransition(q5, 'd', q5);
 
-  test.addTransition(q1, 'a', q1); // loops for sequence matching
-  test.addTransition(q1, 'c', q1);
-  test.addTransition(q1, 'd', q1);
+		test.addTransition(q7, 'a', q7);
+		test.addTransition(q7, 'b', q7);
+		test.addTransition(q7, 'd', q7);
 
-  test.addTransition(q2, 'a', q2);
-  test.addTransition(q2, 'b', q2);
-  test.addTransition(q2, 'd', q2);
+		test.addTransition(q0, 'b', r1); // transposition
+		test.addTransition(r1, 'a', q5);
 
-  test.addTransition(q4, 'a', q4);
-  test.addTransition(q4, 'c', q4);
-  test.addTransition(q4, 'd', q4);
+		test.addTransition(q1, 'c', r2);
+		test.addTransition(r2, 'b', q6);
 
-  test.addTransition(q5, 'a', q5);
-  test.addTransition(q5, 'b', q5);
-  test.addTransition(q5, 'd', q5);
+		test.addTransition(q4, 'c', r3);
+		test.addTransition(r3, 'b', q8);
 
-  test.addTransition(q7, 'a', q7);
-  test.addTransition(q7, 'b', q7);
-  test.addTransition(q7, 'd', q7);
+		test.addTransition(r1, 'b', r1); // loops in tranposition states
+		test.addTransition(r1, 'c', r1);
+		test.addTransition(r1, 'd', r1);
 
-  test.addTransition(q0, 'b', r1); // transposition
-  test.addTransition(r1, 'a', q5);
+		test.addTransition(r2, 'a', r2);
+		test.addTransition(r2, 'c', r2);
+		test.addTransition(r2, 'd', r2);
 
-  test.addTransition(q1, 'c', r2);
-  test.addTransition(r2, 'b', q6);
-
-  test.addTransition(q4, 'c', r3);
-  test.addTransition(r3, 'b', q8);
-
-  test.addTransition(r1, 'b', r1); // loops in tranposition states
-  test.addTransition(r1, 'c', r1);
-  test.addTransition(r1, 'd', r1);
+		test.addTransition(r3, 'a', r3);
+		test.addTransition(r3, 'c', r3);
+		test.addTransition(r3, 'd', r3);
 
-  test.addTransition(r2, 'a', r2);
-  test.addTransition(r2, 'c', r2);
-  test.addTransition(r2, 'd', r2);
+		CHECK(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 
-  test.addTransition(r3, 'a', r3);
-  test.addTransition(r3, 'c', r3);
-  test.addTransition(r3, 'd', r3);
+	SECTION ( "Test Wildcard construction" ) {
+		ext::set<char> alphabet{'a', 'b', '@'};
+		string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
+		auto resulting_automata = stringology::matching::GeneralizedLevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
 
-  CPPUNIT_ASSERT(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
-}
-
-void GeneralizedLevenshteinSequenceMatchingAutomatonTest::testSimpleWildcardConstruction() {
-  ext::set<char> alphabet{'a', 'b', '@'};
-  string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
-  auto resulting_automata = stringology::matching::GeneralizedLevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
-
-  typedef ext::pair<unsigned int, unsigned int> State;
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-  automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
-  res.setInputAlphabet(alphabet);
+		automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(alphabet);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(2,2);
-  State q8 = ext::make_pair(3,2);
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-  State r3 = ext::make_pair(5,1);
-  State r2 = ext::make_pair(5,0);
-  State r1 = ext::make_pair(4,0);
+		State r3 = ext::make_pair(5,1);
+		State r2 = ext::make_pair(5,0);
+		State r1 = ext::make_pair(4,0);
 
-  res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
-  res.setFinalStates(ext::set<State> {q3, q6, q8});
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8, r1, r2, r3});
+		res.setFinalStates(ext::set<State> {q3, q6, q8});
 
-  res.addTransition(q0, 'a', q0); // initial loops
-  res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'a', q0); // initial loops
+		res.addTransition(q0, 'b', q0);
 
-  res.addTransition(q0, 'a', q1); // 3 simple matching automatas
+		res.addTransition(q0, 'a', q1); // 3 simple matching automatas
 
-  res.addTransition(q1, 'a', q2);
-  res.addTransition(q1, 'b', q2);
-  res.addTransition(q4, 'a', q5);
-  res.addTransition(q4, 'b', q5);
+		res.addTransition(q1, 'a', q2);
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'a', q5);
+		res.addTransition(q4, 'b', q5);
 
-  res.addTransition(q2, 'b', q3);
-  res.addTransition(q5, 'b', q6);
-  res.addTransition(q7, 'b', q8);
+		res.addTransition(q2, 'b', q3);
+		res.addTransition(q5, 'b', q6);
+		res.addTransition(q7, 'b', q8);
 
-  res.addTransition(q0, 'b', q4); // error transitions for replace
+		res.addTransition(q0, 'b', q4); // error transitions for replace
 
-  res.addTransition(q2, 'a', q6);
-  res.addTransition(q5, 'a', q8);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q5, 'a', q8);
 
-  res.addTransition(q0, q4); // delete transition
-  res.addTransition(q1, q5);
-  res.addTransition(q2, q6);
+		res.addTransition(q0, q4); // delete transition
+		res.addTransition(q1, q5);
+		res.addTransition(q2, q6);
 
-  res.addTransition(q4, q7);
-  res.addTransition(q5, q8);
+		res.addTransition(q4, q7);
+		res.addTransition(q5, q8);
 
-  res.addTransition(q1, 'a', q4);
-  res.addTransition(q1, 'b', q4);
+		res.addTransition(q1, 'a', q4);
+		res.addTransition(q1, 'b', q4);
 
-  res.addTransition(q2, 'a', q5);
-  res.addTransition(q2, 'b', q5);
+		res.addTransition(q2, 'a', q5);
+		res.addTransition(q2, 'b', q5);
 
-  res.addTransition(q5, 'a', q7);
-  res.addTransition(q5, 'b', q7);
+		res.addTransition(q5, 'a', q7);
+		res.addTransition(q5, 'b', q7);
 
-  res.addTransition(q2, 'a', q2); // sequence matching loops
-  res.addTransition(q5, 'a', q5);
-  res.addTransition(q7, 'a', q7);
+		res.addTransition(q2, 'a', q2); // sequence matching loops
+		res.addTransition(q5, 'a', q5);
+		res.addTransition(q7, 'a', q7);
 
-  res.addTransition(r1, 'b', r1);
+		res.addTransition(r1, 'b', r1);
 
-  res.addTransition(q0, 'a', r1); // transpose states
-  res.addTransition(q0, 'b', r1);
-  res.addTransition(r1, 'a', q5);
+		res.addTransition(q0, 'a', r1); // transpose states
+		res.addTransition(q0, 'b', r1);
+		res.addTransition(r1, 'a', q5);
 
-  res.addTransition(q1, 'b', r2);
-  res.addTransition(r2, 'a', q6);
-  res.addTransition(r2, 'b', q6);
+		res.addTransition(q1, 'b', r2);
+		res.addTransition(r2, 'a', q6);
+		res.addTransition(r2, 'b', q6);
 
-  res.addTransition(q4, 'b', r3);
-  res.addTransition(r3, 'a', q8);
-  res.addTransition(r3, 'b', q8);
+		res.addTransition(q4, 'b', r3);
+		res.addTransition(r3, 'a', q8);
+		res.addTransition(r3, 'b', q8);
 
-  CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 }
-
-void GeneralizedLevenshteinSequenceMatchingAutomatonTest::setUp() { }
-
-void GeneralizedLevenshteinSequenceMatchingAutomatonTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.h b/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.h
deleted file mode 100644
index c58d1d44d3..0000000000
--- a/alib2algo/test-src/stringology/matching/GeneralizedLevenshteinSequenceMatchingAutomatonTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef GENERALIZED_LEVENSHTEIN_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-#define GENERALIZED_LEVENSHTEIN_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GeneralizedLevenshteinSequenceMatchingAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(GeneralizedLevenshteinSequenceMatchingAutomatonTest);
-    CPPUNIT_TEST(testSimpleConstruction);
-		CPPUNIT_TEST(testSimpleWildcardConstruction);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimpleConstruction();
-		void testSimpleWildcardConstruction();
-};
-#endif //GENERALIZED_LEVENSHTEIN_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
diff --git a/alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.cpp b/alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.cpp
index 52b05b9223..a7da2fccc9 100644
--- a/alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.cpp
@@ -1,118 +1,111 @@
+#include <catch2/catch.hpp>
+
 #include <stringology/matching/HammingMatchingAutomaton.h>
 #include <automaton/FSM/NFA.h>
 #include <string/LinearString.h>
 #include <string/WildcardLinearString.h>
 #include <automaton/simplify/UnreachableStatesRemover.h>
 
-#include "HammingMatchingAutomatonTest.h"
-
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( HammingMatchingAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( HammingMatchingAutomatonTest );
-
-void HammingMatchingAutomatonTest::testSimpleConstruction() {
-    ext::set<char> alphabet{'a', 'b', 'c', 'd'};
-    string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
-    auto resulting_automata = stringology::matching::HammingMatchingAutomaton::construct(input_string, 2);
+TEST_CASE ( "Hamming Matching Automaton", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Test construction" ) {
+		ext::set<char> alphabet{'a', 'b', 'c', 'd'};
+		string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
+		auto resulting_automata = stringology::matching::HammingMatchingAutomaton::construct(input_string, 2);
 
-    typedef ext::pair<unsigned int, unsigned int> State;
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-    automaton::NFA < char, State > res(ext::make_pair(0,0));
-    res.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+		automaton::NFA < char, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
 
-    State q0 = ext::make_pair(0,0);
-    State q1 = ext::make_pair(1,0);
-    State q2 = ext::make_pair(2,0);
-    State q3 = ext::make_pair(3,0);
-    State q4 = ext::make_pair(1,1);
-    State q5 = ext::make_pair(2,1);
-    State q6 = ext::make_pair(3,1);
-    State q7 = ext::make_pair(2,2);
-    State q8 = ext::make_pair(3,2);
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-    res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
-    res.setFinalStates(ext::set<State> {q3, q6, q8});
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
+		res.setFinalStates(ext::set<State> {q3, q6, q8});
 
-    res.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
+		res.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
 
-    res.addTransition(q1, 'b', q2);
-    res.addTransition(q4, 'b', q5);
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'b', q5);
 
-    res.addTransition(q2, 'c', q3);
-    res.addTransition(q5, 'c', q6);
-    res.addTransition(q7, 'c', q8);
+		res.addTransition(q2, 'c', q3);
+		res.addTransition(q5, 'c', q6);
+		res.addTransition(q7, 'c', q8);
 
-    res.addTransition(q0, 'a', q0); // loops in initial state
-    res.addTransition(q0, 'b', q0);
-    res.addTransition(q0, 'c', q0);
-    res.addTransition(q0, 'd', q0);
+		res.addTransition(q0, 'a', q0); // loops in initial state
+		res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'c', q0);
+		res.addTransition(q0, 'd', q0);
 
-    res.addTransition(q0, 'b', q4); // diagonal transitions representing replace
-    res.addTransition(q0, 'c', q4);
-    res.addTransition(q0, 'd', q4);
+		res.addTransition(q0, 'b', q4); // diagonal transitions representing replace
+		res.addTransition(q0, 'c', q4);
+		res.addTransition(q0, 'd', q4);
 
-    res.addTransition(q1, 'a', q5);
-    res.addTransition(q1, 'c', q5);
-    res.addTransition(q1, 'd', q5);
-    res.addTransition(q4, 'a', q7);
-    res.addTransition(q4, 'c', q7);
-    res.addTransition(q4, 'd', q7);
+		res.addTransition(q1, 'a', q5);
+		res.addTransition(q1, 'c', q5);
+		res.addTransition(q1, 'd', q5);
+		res.addTransition(q4, 'a', q7);
+		res.addTransition(q4, 'c', q7);
+		res.addTransition(q4, 'd', q7);
 
-    res.addTransition(q2, 'a', q6);
-    res.addTransition(q2, 'b', q6);
-    res.addTransition(q2, 'd', q6);
-    res.addTransition(q5, 'a', q8);
-    res.addTransition(q5, 'b', q8);
-    res.addTransition(q5, 'd', q8);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q2, 'b', q6);
+		res.addTransition(q2, 'd', q6);
+		res.addTransition(q5, 'a', q8);
+		res.addTransition(q5, 'b', q8);
+		res.addTransition(q5, 'd', q8);
 
-    CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
-}
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 
 
-void HammingMatchingAutomatonTest::testSimpleWildcardConstruction() {
-  ext::set<char> alphabet{'a', 'b', '@'};
-  string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
-  auto resulting_automata = stringology::matching::HammingMatchingAutomaton::construct(input_string, 2);
+	SECTION ( "Test wildcard construction" ) {
+		ext::set<char> alphabet{'a', 'b', '@'};
+		string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
+		auto resulting_automata = stringology::matching::HammingMatchingAutomaton::construct(input_string, 2);
 
-  typedef ext::pair<unsigned int, unsigned int> State;
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-  automaton::NFA < char, State > res(ext::make_pair(0,0));
-  res.setInputAlphabet(alphabet);
+		automaton::NFA < char, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(alphabet);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(3,2);
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(3,2);
 
-  res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7});
-  res.setFinalStates(ext::set<State> {q3, q6, q7});
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7});
+		res.setFinalStates(ext::set<State> {q3, q6, q7});
 
-  res.addTransition(q0, 'a', q0); // initial loops
-  res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'a', q0); // initial loops
+		res.addTransition(q0, 'b', q0);
 
-  res.addTransition(q0, 'a', q1); // 3 simple matching automatas (thrid is not connected)
+		res.addTransition(q0, 'a', q1); // 3 simple matching automatas (thrid is not connected)
 
-  res.addTransition(q1, 'a', q2);
-  res.addTransition(q1, 'b', q2);
-  res.addTransition(q4, 'a', q5);
-  res.addTransition(q4, 'b', q5);
+		res.addTransition(q1, 'a', q2);
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'a', q5);
+		res.addTransition(q4, 'b', q5);
 
-  res.addTransition(q2, 'b', q3);
-  res.addTransition(q5, 'b', q6);
+		res.addTransition(q2, 'b', q3);
+		res.addTransition(q5, 'b', q6);
 
-  res.addTransition(q0, 'b', q4); // error transitions
+		res.addTransition(q0, 'b', q4); // error transitions
 
-  res.addTransition(q2, 'a', q6);
-  res.addTransition(q5, 'a', q7);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q5, 'a', q7);
 
-  CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 }
-
-
-void HammingMatchingAutomatonTest::setUp() { }
-
-void HammingMatchingAutomatonTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.h b/alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.h
deleted file mode 100644
index caff8e0d7d..0000000000
--- a/alib2algo/test-src/stringology/matching/HammingMatchingAutomatonTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef HAMMING_MATCHING_AUTOMATA_TEST_H_
-#define HAMMING_MATCHING_AUTOMATA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class HammingMatchingAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(HammingMatchingAutomatonTest);
-    CPPUNIT_TEST(testSimpleConstruction);
-		CPPUNIT_TEST(testSimpleWildcardConstruction);		
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimpleConstruction();
-		void testSimpleWildcardConstruction();
-};
-#endif //HAMMING_MATCHING_AUTOMATA_TEST_H_
diff --git a/alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.cpp b/alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.cpp
index 239b5fa1ca..d171a0688f 100644
--- a/alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.cpp
@@ -1,138 +1,132 @@
+#include <catch2/catch.hpp>
+
 #include <stringology/matching/HammingSequenceMatchingAutomaton.h>
 #include <automaton/FSM/NFA.h>
 #include <string/LinearString.h>
 #include <automaton/simplify/UnreachableStatesRemover.h>
 
-#include "HammingSequenceMatchingAutomatonTest.h"
-
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( HammingSequenceMatchingAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( HammingSequenceMatchingAutomatonTest );
-
-void HammingSequenceMatchingAutomatonTest::testSimpleConstruction() {
-  ext::set<char> alphabet{'a', 'b', 'c', 'd'};
-  string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
-  auto resulting_automata = stringology::matching::HammingSequenceMatchingAutomaton::construct(input_string, 2);
-
-  typedef ext::pair<unsigned int, unsigned int> State;
+TEST_CASE ( "Hamming Sequence Matching Automaton", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Test construction" ) {
+		ext::set<char> alphabet{'a', 'b', 'c', 'd'};
+		string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
+		auto resulting_automata = stringology::matching::HammingSequenceMatchingAutomaton::construct(input_string, 2);
 
-  automaton::NFA < char, State > test(ext::make_pair(0,0));
-  test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+		typedef ext::pair<unsigned int, unsigned int> State;
+
+		automaton::NFA < char, State > test(ext::make_pair(0,0));
+		test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(2,2);
-  State q8 = ext::make_pair(3,2);
+		test.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
+		test.setFinalStates(ext::set<State> {q3, q6, q8});
 
-  test.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
-  test.setFinalStates(ext::set<State> {q3, q6, q8});
+		test.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
 
-  test.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
+		test.addTransition(q1, 'b', q2);
+		test.addTransition(q4, 'b', q5);
 
-  test.addTransition(q1, 'b', q2);
-  test.addTransition(q4, 'b', q5);
+		test.addTransition(q2, 'c', q3);
+		test.addTransition(q5, 'c', q6);
+		test.addTransition(q7, 'c', q8);
 
-  test.addTransition(q2, 'c', q3);
-  test.addTransition(q5, 'c', q6);
-  test.addTransition(q7, 'c', q8);
+		test.addTransition(q0, 'a', q0); // loops in initial state
+		test.addTransition(q0, 'b', q0);
+		test.addTransition(q0, 'c', q0);
+		test.addTransition(q0, 'd', q0);
 
-  test.addTransition(q0, 'a', q0); // loops in initial state
-  test.addTransition(q0, 'b', q0);
-  test.addTransition(q0, 'c', q0);
-  test.addTransition(q0, 'd', q0);
+		test.addTransition(q0, 'b', q4); // diagonal transitions representing replace
+		test.addTransition(q0, 'c', q4);
+		test.addTransition(q0, 'd', q4);
 
-  test.addTransition(q0, 'b', q4); // diagonal transitions representing replace
-  test.addTransition(q0, 'c', q4);
-  test.addTransition(q0, 'd', q4);
+		test.addTransition(q1, 'a', q5);
+		test.addTransition(q1, 'c', q5);
+		test.addTransition(q1, 'd', q5);
+		test.addTransition(q4, 'a', q7);
+		test.addTransition(q4, 'c', q7);
+		test.addTransition(q4, 'd', q7);
 
-  test.addTransition(q1, 'a', q5);
-  test.addTransition(q1, 'c', q5);
-  test.addTransition(q1, 'd', q5);
-  test.addTransition(q4, 'a', q7);
-  test.addTransition(q4, 'c', q7);
-  test.addTransition(q4, 'd', q7);
+		test.addTransition(q2, 'a', q6);
+		test.addTransition(q2, 'b', q6);
+		test.addTransition(q2, 'd', q6);
+		test.addTransition(q5, 'd', q8);
+		test.addTransition(q5, 'a', q8);
+		test.addTransition(q5, 'b', q8);
 
-  test.addTransition(q2, 'a', q6);
-  test.addTransition(q2, 'b', q6);
-  test.addTransition(q2, 'd', q6);
-  test.addTransition(q5, 'd', q8);
-  test.addTransition(q5, 'a', q8);
-  test.addTransition(q5, 'b', q8);
+		test.addTransition(q1, 'a', q1); // loops for sequence matching
+		test.addTransition(q1, 'c', q1);
+		test.addTransition(q1, 'd', q1);
 
-  test.addTransition(q1, 'a', q1); // loops for sequence matching
-  test.addTransition(q1, 'c', q1);
-  test.addTransition(q1, 'd', q1);
+		test.addTransition(q2, 'a', q2);
+		test.addTransition(q2, 'b', q2);
+		test.addTransition(q2, 'd', q2);
 
-  test.addTransition(q2, 'a', q2);
-  test.addTransition(q2, 'b', q2);
-  test.addTransition(q2, 'd', q2);
+		test.addTransition(q4, 'a', q4);
+		test.addTransition(q4, 'c', q4);
+		test.addTransition(q4, 'd', q4);
 
-  test.addTransition(q4, 'a', q4);
-  test.addTransition(q4, 'c', q4);
-  test.addTransition(q4, 'd', q4);
+		test.addTransition(q5, 'a', q5);
+		test.addTransition(q5, 'b', q5);
+		test.addTransition(q5, 'd', q5);
 
-  test.addTransition(q5, 'a', q5);
-  test.addTransition(q5, 'b', q5);
-  test.addTransition(q5, 'd', q5);
+		test.addTransition(q7, 'a', q7);
+		test.addTransition(q7, 'b', q7);
+		test.addTransition(q7, 'd', q7);
 
-  test.addTransition(q7, 'a', q7);
-  test.addTransition(q7, 'b', q7);
-  test.addTransition(q7, 'd', q7);
+		CHECK(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 
-  CPPUNIT_ASSERT(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
-}
-
-void HammingSequenceMatchingAutomatonTest::testSimpleWildcardConstruction() {
-  ext::set<char> alphabet{'a', 'b', '@'};
-  string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
-  auto resulting_automata = stringology::matching::HammingSequenceMatchingAutomaton::construct(input_string, 2);
-
-  typedef ext::pair<unsigned int, unsigned int> State;
+	SECTION ( "Test wildcard construction" ) {
+		ext::set<char> alphabet{'a', 'b', '@'};
+		string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
+		auto resulting_automata = stringology::matching::HammingSequenceMatchingAutomaton::construct(input_string, 2);
 
-  automaton::NFA < char, State > res(ext::make_pair(0,0));
-  res.setInputAlphabet(alphabet);
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(3,2);
+		automaton::NFA < char, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(alphabet);
 
-  res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7});
-  res.setFinalStates(ext::set<State> {q3, q6, q7});
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(3,2);
 
-  res.addTransition(q0, 'a', q0); // initial loops
-  res.addTransition(q0, 'b', q0);
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7});
+		res.setFinalStates(ext::set<State> {q3, q6, q7});
+
+		res.addTransition(q0, 'a', q0); // initial loops
+		res.addTransition(q0, 'b', q0);
 
-  res.addTransition(q0, 'a', q1); // 3 simple matching automatas (thrid is not connected)
+		res.addTransition(q0, 'a', q1); // 3 simple matching automatas (thrid is not connected)
 
-  res.addTransition(q1, 'a', q2);
-  res.addTransition(q1, 'b', q2);
-  res.addTransition(q4, 'a', q5);
-  res.addTransition(q4, 'b', q5);
+		res.addTransition(q1, 'a', q2);
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'a', q5);
+		res.addTransition(q4, 'b', q5);
 
-  res.addTransition(q2, 'b', q3);
-  res.addTransition(q5, 'b', q6);
+		res.addTransition(q2, 'b', q3);
+		res.addTransition(q5, 'b', q6);
 
-  res.addTransition(q0, 'b', q4); // error transitions
+		res.addTransition(q0, 'b', q4); // error transitions
 
-  res.addTransition(q2, 'a', q6);
-  res.addTransition(q5, 'a', q7);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q5, 'a', q7);
 
-  res.addTransition(q2, 'a', q2); // loops for sequence matching
-  res.addTransition(q5, 'a', q5);
+		res.addTransition(q2, 'a', q2); // loops for sequence matching
+		res.addTransition(q5, 'a', q5);
 
-  CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 }
-
-void HammingSequenceMatchingAutomatonTest::setUp() { }
-
-void HammingSequenceMatchingAutomatonTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.h b/alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.h
deleted file mode 100644
index c33a109a6c..0000000000
--- a/alib2algo/test-src/stringology/matching/HammingSequenceMatchingAutomatonTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef HAMMING_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-#define HAMMING_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class HammingSequenceMatchingAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(HammingSequenceMatchingAutomatonTest);
-    CPPUNIT_TEST(testSimpleConstruction);
-		CPPUNIT_TEST(testSimpleWildcardConstruction);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimpleConstruction();
-		void testSimpleWildcardConstruction();
-};
-#endif //HAMMING_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
diff --git a/alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.cpp b/alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.cpp
index 4b5726e0d3..c08bc687ca 100644
--- a/alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.cpp
@@ -1,157 +1,151 @@
+#include <catch2/catch.hpp>
+
 #include <stringology/matching/LevenshteinMatchingAutomaton.h>
 #include <automaton/FSM/EpsilonNFA.h>
 #include <string/LinearString.h>
 #include <automaton/simplify/UnreachableStatesRemover.h>
 
-#include "LevenshteinMatchingAutomatonTest.h"
-
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( LevenshteinMatchingAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( LevenshteinMatchingAutomatonTest );
-
 
-void LevenshteinMatchingAutomatonTest::testSimpleConstruction() {
-    ext::set<char> alphabet{'a', 'b', 'c', 'd'};
-    string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
-    auto resulting_automata = stringology::matching::LevenshteinMatchingAutomaton::construct(input_string, 2);
+TEST_CASE ( "Levenshtein Matching Automaton", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Test construction" ) {
+		ext::set<char> alphabet{'a', 'b', 'c', 'd'};
+		string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
+		auto resulting_automata = stringology::matching::LevenshteinMatchingAutomaton::construct(input_string, 2);
+
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-    typedef ext::pair<unsigned int, unsigned int> State;
+		automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
 
-    automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
-    res.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-    State q0 = ext::make_pair(0,0);
-    State q1 = ext::make_pair(1,0);
-    State q2 = ext::make_pair(2,0);
-    State q3 = ext::make_pair(3,0);
-    State q4 = ext::make_pair(1,1);
-    State q5 = ext::make_pair(2,1);
-    State q6 = ext::make_pair(3,1);
-    State q7 = ext::make_pair(2,2);
-    State q8 = ext::make_pair(3,2);
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
+		res.setFinalStates(ext::set<State> {q3, q6, q8});
 
-    res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
-    res.setFinalStates(ext::set<State> {q3, q6, q8});
+		res.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
 
-    res.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'b', q5);
 
-    res.addTransition(q1, 'b', q2);
-    res.addTransition(q4, 'b', q5);
+		res.addTransition(q2, 'c', q3);
+		res.addTransition(q5, 'c', q6);
+		res.addTransition(q7, 'c', q8);
 
-    res.addTransition(q2, 'c', q3);
-    res.addTransition(q5, 'c', q6);
-    res.addTransition(q7, 'c', q8);
+		res.addTransition(q0, 'a', q0); // loops in initial state
+		res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'c', q0);
+		res.addTransition(q0, 'd', q0);
 
-    res.addTransition(q0, 'a', q0); // loops in initial state
-    res.addTransition(q0, 'b', q0);
-    res.addTransition(q0, 'c', q0);
-    res.addTransition(q0, 'd', q0);
+		res.addTransition(q0, 'b', q4); // diagonal transitions representing replace
+		res.addTransition(q0, 'c', q4);
+		res.addTransition(q0, 'd', q4);
 
-    res.addTransition(q0, 'b', q4); // diagonal transitions representing replace
-    res.addTransition(q0, 'c', q4);
-    res.addTransition(q0, 'd', q4);
+		res.addTransition(q0, q4); // deletion
 
-    res.addTransition(q0, q4); // deletion
+		res.addTransition(q1, 'a', q5);
+		res.addTransition(q1, 'c', q5);
+		res.addTransition(q1, 'd', q5);
+		res.addTransition(q4, 'a', q7);
+		res.addTransition(q4, 'c', q7);
+		res.addTransition(q4, 'd', q7);
 
-    res.addTransition(q1, 'a', q5);
-    res.addTransition(q1, 'c', q5);
-    res.addTransition(q1, 'd', q5);
-    res.addTransition(q4, 'a', q7);
-    res.addTransition(q4, 'c', q7);
-    res.addTransition(q4, 'd', q7);
+		res.addTransition(q1, q5); // deletion
+		res.addTransition(q4, q7);
 
-    res.addTransition(q1, q5); // deletion
-    res.addTransition(q4, q7);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q2, 'b', q6);
+		res.addTransition(q2, 'd', q6);
+		res.addTransition(q5, 'a', q8);
+		res.addTransition(q5, 'b', q8);
+		res.addTransition(q5, 'd', q8);
 
-    res.addTransition(q2, 'a', q6);
-    res.addTransition(q2, 'b', q6);
-    res.addTransition(q2, 'd', q6);
-    res.addTransition(q5, 'a', q8);
-    res.addTransition(q5, 'b', q8);
-    res.addTransition(q5, 'd', q8);
+		res.addTransition(q2, q6); // deletion
+		res.addTransition(q5, q8);
 
-    res.addTransition(q2, q6); // deletion
-    res.addTransition(q5, q8);
+		res.addTransition(q1, 'a', q4); // insertions
+		res.addTransition(q1, 'b', q4);
+		res.addTransition(q1, 'c', q4);
+		res.addTransition(q1, 'd', q4);
 
-    res.addTransition(q1, 'a', q4); // insertions
-    res.addTransition(q1, 'b', q4);
-    res.addTransition(q1, 'c', q4);
-    res.addTransition(q1, 'd', q4);
+		res.addTransition(q2, 'a', q5);
+		res.addTransition(q2, 'b', q5);
+		res.addTransition(q2, 'c', q5);
+		res.addTransition(q2, 'd', q5);
 
-    res.addTransition(q2, 'a', q5);
-    res.addTransition(q2, 'b', q5);
-    res.addTransition(q2, 'c', q5);
-    res.addTransition(q2, 'd', q5);
+		res.addTransition(q5, 'a', q7);
+		res.addTransition(q5, 'b', q7);
+		res.addTransition(q5, 'c', q7);
+		res.addTransition(q5, 'd', q7);
 
-    res.addTransition(q5, 'a', q7);
-    res.addTransition(q5, 'b', q7);
-    res.addTransition(q5, 'c', q7);
-    res.addTransition(q5, 'd', q7);
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 
-    CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
-}
-
-void LevenshteinMatchingAutomatonTest::testSimpleWildcardConstruction() {
-  ext::set<char> alphabet{'a', 'b', '@'};
-  string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
-  auto resulting_automata = stringology::matching::LevenshteinMatchingAutomaton::construct(input_string, 2);
+	SECTION ( "Test wildcard construction" ) {
+		ext::set<char> alphabet{'a', 'b', '@'};
+		string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
+		auto resulting_automata = stringology::matching::LevenshteinMatchingAutomaton::construct(input_string, 2);
 
-  typedef ext::pair<unsigned int, unsigned int> State;
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-  automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
-  res.setInputAlphabet(alphabet);
+		automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(alphabet);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(2,2);
-  State q8 = ext::make_pair(3,2);
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-  res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
-  res.setFinalStates(ext::set<State> {q3, q6, q8});
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
+		res.setFinalStates(ext::set<State> {q3, q6, q8});
 
-  res.addTransition(q0, 'a', q0); // initial loops
-  res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'a', q0); // initial loops
+		res.addTransition(q0, 'b', q0);
 
-  res.addTransition(q0, 'a', q1); // 3 simple matching automatas
+		res.addTransition(q0, 'a', q1); // 3 simple matching automatas
 
-  res.addTransition(q1, 'a', q2);
-  res.addTransition(q1, 'b', q2);
-  res.addTransition(q4, 'a', q5);
-  res.addTransition(q4, 'b', q5);
+		res.addTransition(q1, 'a', q2);
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'a', q5);
+		res.addTransition(q4, 'b', q5);
 
-  res.addTransition(q2, 'b', q3);
-  res.addTransition(q5, 'b', q6);
-  res.addTransition(q7, 'b', q8);
+		res.addTransition(q2, 'b', q3);
+		res.addTransition(q5, 'b', q6);
+		res.addTransition(q7, 'b', q8);
 
-  res.addTransition(q0, 'b', q4); // error transitions for replace
+		res.addTransition(q0, 'b', q4); // error transitions for replace
 
-  res.addTransition(q2, 'a', q6);
-  res.addTransition(q5, 'a', q8);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q5, 'a', q8);
 
-  res.addTransition(q0, q4); // delete transition
-  res.addTransition(q1, q5);
-  res.addTransition(q2, q6);
+		res.addTransition(q0, q4); // delete transition
+		res.addTransition(q1, q5);
+		res.addTransition(q2, q6);
 
-  res.addTransition(q4, q7);
-  res.addTransition(q5, q8);
+		res.addTransition(q4, q7);
+		res.addTransition(q5, q8);
 
-  res.addTransition(q1, 'a', q4);
-  res.addTransition(q1, 'b', q4);
+		res.addTransition(q1, 'a', q4);
+		res.addTransition(q1, 'b', q4);
 
-  res.addTransition(q2, 'a', q5);
-  res.addTransition(q2, 'b', q5);
+		res.addTransition(q2, 'a', q5);
+		res.addTransition(q2, 'b', q5);
 
-  res.addTransition(q5, 'a', q7);
-  res.addTransition(q5, 'b', q7);
+		res.addTransition(q5, 'a', q7);
+		res.addTransition(q5, 'b', q7);
 
-  CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 }
-
-void LevenshteinMatchingAutomatonTest::setUp() { }
-
-void LevenshteinMatchingAutomatonTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.h b/alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.h
deleted file mode 100644
index 6ec3013fa8..0000000000
--- a/alib2algo/test-src/stringology/matching/LevenshteinMatchingAutomatonTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef HAMMING_MATCHING_AUTOMATA_TEST_H_
-#define HAMMING_MATCHING_AUTOMATA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class LevenshteinMatchingAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(LevenshteinMatchingAutomatonTest);
-    CPPUNIT_TEST(testSimpleConstruction);
-		CPPUNIT_TEST(testSimpleWildcardConstruction);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimpleConstruction();
-		void testSimpleWildcardConstruction();
-};
-#endif //HAMMING_MATCHING_AUTOMATA_TEST_H_
diff --git a/alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.cpp b/alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.cpp
index 88bdb69167..282bd2fca4 100644
--- a/alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.cpp
@@ -1,181 +1,176 @@
+#include <catch2/catch.hpp>
+
 #include <stringology/matching/LevenshteinSequenceMatchingAutomaton.h>
 #include <automaton/FSM/NFA.h>
 #include <string/LinearString.h>
 #include <automaton/simplify/UnreachableStatesRemover.h>
 
-#include "LevenshteinSequenceMatchingAutomatonTest.h"
-
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( LevenshteinSequenceMatchingAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( LevenshteinSequenceMatchingAutomatonTest );
+TEST_CASE ( "Levenshtein Sequence Matching Automaton", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Test construction" ) {
+		ext::set<char> alphabet{'a', 'b', 'c', 'd'};
+		string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
+		auto resulting_automata = stringology::matching::LevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
 
-void LevenshteinSequenceMatchingAutomatonTest::testSimpleConstruction() {
-  ext::set<char> alphabet{'a', 'b', 'c', 'd'};
-  string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
-  auto resulting_automata = stringology::matching::LevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-  typedef ext::pair<unsigned int, unsigned int> State;
+		automaton::EpsilonNFA < char, void, State > test(ext::make_pair(0,0));
+		test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
 
-  automaton::EpsilonNFA < char, void, State > test(ext::make_pair(0,0));
-  test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(2,2);
-  State q8 = ext::make_pair(3,2);
+		test.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
+		test.setFinalStates(ext::set<State> {q3, q6, q8});
 
-  test.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
-  test.setFinalStates(ext::set<State> {q3, q6, q8});
+		test.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
 
-  test.addTransition(q0, 'a', q1); // vertical transitions (exact matching automata)
+		test.addTransition(q1, 'b', q2);
+		test.addTransition(q4, 'b', q5);
 
-  test.addTransition(q1, 'b', q2);
-  test.addTransition(q4, 'b', q5);
+		test.addTransition(q2, 'c', q3);
+		test.addTransition(q5, 'c', q6);
+		test.addTransition(q7, 'c', q8);
 
-  test.addTransition(q2, 'c', q3);
-  test.addTransition(q5, 'c', q6);
-  test.addTransition(q7, 'c', q8);
+		test.addTransition(q0, 'a', q0); // loops in initial state
+		test.addTransition(q0, 'b', q0);
+		test.addTransition(q0, 'c', q0);
+		test.addTransition(q0, 'd', q0);
 
-  test.addTransition(q0, 'a', q0); // loops in initial state
-  test.addTransition(q0, 'b', q0);
-  test.addTransition(q0, 'c', q0);
-  test.addTransition(q0, 'd', q0);
+		test.addTransition(q0, 'b', q4); // diagonal transitions reptestenting replace
+		test.addTransition(q0, 'c', q4);
+		test.addTransition(q0, 'd', q4);
 
-  test.addTransition(q0, 'b', q4); // diagonal transitions reptestenting replace
-  test.addTransition(q0, 'c', q4);
-  test.addTransition(q0, 'd', q4);
+		test.addTransition(q0, q4); // deletion
 
-  test.addTransition(q0, q4); // deletion
+		test.addTransition(q1, 'a', q5);
+		test.addTransition(q1, 'c', q5);
+		test.addTransition(q1, 'd', q5);
+		test.addTransition(q4, 'a', q7);
+		test.addTransition(q4, 'c', q7);
+		test.addTransition(q4, 'd', q7);
 
-  test.addTransition(q1, 'a', q5);
-  test.addTransition(q1, 'c', q5);
-  test.addTransition(q1, 'd', q5);
-  test.addTransition(q4, 'a', q7);
-  test.addTransition(q4, 'c', q7);
-  test.addTransition(q4, 'd', q7);
+		test.addTransition(q1, q5); // deletion
+		test.addTransition(q4, q7);
 
-  test.addTransition(q1, q5); // deletion
-  test.addTransition(q4, q7);
+		test.addTransition(q2, 'a', q6);
+		test.addTransition(q2, 'b', q6);
+		test.addTransition(q2, 'd', q6);
+		test.addTransition(q5, 'a', q8);
+		test.addTransition(q5, 'b', q8);
+		test.addTransition(q5, 'd', q8);
 
-  test.addTransition(q2, 'a', q6);
-  test.addTransition(q2, 'b', q6);
-  test.addTransition(q2, 'd', q6);
-  test.addTransition(q5, 'a', q8);
-  test.addTransition(q5, 'b', q8);
-  test.addTransition(q5, 'd', q8);
+		test.addTransition(q2, q6); // deletion
+		test.addTransition(q5, q8);
 
-  test.addTransition(q2, q6); // deletion
-  test.addTransition(q5, q8);
+		test.addTransition(q1, 'a', q4); // insertions
+		test.addTransition(q1, 'b', q4);
+		test.addTransition(q1, 'c', q4);
+		test.addTransition(q1, 'd', q4);
 
-  test.addTransition(q1, 'a', q4); // insertions
-  test.addTransition(q1, 'b', q4);
-  test.addTransition(q1, 'c', q4);
-  test.addTransition(q1, 'd', q4);
+		test.addTransition(q2, 'a', q5);
+		test.addTransition(q2, 'b', q5);
+		test.addTransition(q2, 'c', q5);
+		test.addTransition(q2, 'd', q5);
 
-  test.addTransition(q2, 'a', q5);
-  test.addTransition(q2, 'b', q5);
-  test.addTransition(q2, 'c', q5);
-  test.addTransition(q2, 'd', q5);
+		test.addTransition(q5, 'a', q7);
+		test.addTransition(q5, 'c', q7);
+		test.addTransition(q5, 'b', q7);
+		test.addTransition(q5, 'd', q7);
 
-  test.addTransition(q5, 'a', q7);
-  test.addTransition(q5, 'c', q7);
-  test.addTransition(q5, 'b', q7);
-  test.addTransition(q5, 'd', q7);
+		test.addTransition(q1, 'a', q1); // loops for sequence matching
+		test.addTransition(q1, 'c', q1);
+		test.addTransition(q1, 'd', q1);
 
-  test.addTransition(q1, 'a', q1); // loops for sequence matching
-  test.addTransition(q1, 'c', q1);
-  test.addTransition(q1, 'd', q1);
+		test.addTransition(q2, 'a', q2);
+		test.addTransition(q2, 'b', q2);
+		test.addTransition(q2, 'd', q2);
 
-  test.addTransition(q2, 'a', q2);
-  test.addTransition(q2, 'b', q2);
-  test.addTransition(q2, 'd', q2);
+		test.addTransition(q4, 'a', q4);
+		test.addTransition(q4, 'c', q4);
+		test.addTransition(q4, 'd', q4);
 
-  test.addTransition(q4, 'a', q4);
-  test.addTransition(q4, 'c', q4);
-  test.addTransition(q4, 'd', q4);
+		test.addTransition(q5, 'a', q5);
+		test.addTransition(q5, 'b', q5);
+		test.addTransition(q5, 'd', q5);
 
-  test.addTransition(q5, 'a', q5);
-  test.addTransition(q5, 'b', q5);
-  test.addTransition(q5, 'd', q5);
+		test.addTransition(q7, 'a', q7);
+		test.addTransition(q7, 'b', q7);
+		test.addTransition(q7, 'd', q7);
 
-  test.addTransition(q7, 'a', q7);
-  test.addTransition(q7, 'b', q7);
-  test.addTransition(q7, 'd', q7);
-
-  CPPUNIT_ASSERT(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
-}
+		CHECK(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 
 
-void LevenshteinSequenceMatchingAutomatonTest::testSimpleWildcardConstruction() {
-  ext::set<char> alphabet{'a', 'b', '@'};
-  string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
-  auto resulting_automata = stringology::matching::LevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
+	SECTION ( "Test wildcard construction" ) {
+		ext::set<char> alphabet{'a', 'b', '@'};
+		string::WildcardLinearString <char> input_string(alphabet, ext::vector<char>{'a', '@', 'b'}, '@');
+		auto resulting_automata = stringology::matching::LevenshteinSequenceMatchingAutomaton::construct(input_string, 2);
 
-  typedef ext::pair<unsigned int, unsigned int> State;
+		typedef ext::pair<unsigned int, unsigned int> State;
 
-  automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
-  res.setInputAlphabet(alphabet);
+		automaton::EpsilonNFA < char, void, State > res(ext::make_pair(0,0));
+		res.setInputAlphabet(alphabet);
 
-  State q0 = ext::make_pair(0,0);
-  State q1 = ext::make_pair(1,0);
-  State q2 = ext::make_pair(2,0);
-  State q3 = ext::make_pair(3,0);
-  State q4 = ext::make_pair(1,1);
-  State q5 = ext::make_pair(2,1);
-  State q6 = ext::make_pair(3,1);
-  State q7 = ext::make_pair(2,2);
-  State q8 = ext::make_pair(3,2);
+		State q0 = ext::make_pair(0,0);
+		State q1 = ext::make_pair(1,0);
+		State q2 = ext::make_pair(2,0);
+		State q3 = ext::make_pair(3,0);
+		State q4 = ext::make_pair(1,1);
+		State q5 = ext::make_pair(2,1);
+		State q6 = ext::make_pair(3,1);
+		State q7 = ext::make_pair(2,2);
+		State q8 = ext::make_pair(3,2);
 
-  res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
-  res.setFinalStates(ext::set<State> {q3, q6, q8});
+		res.setStates(ext::set<State> {q0, q1, q2, q3, q4, q5, q6, q7, q8});
+		res.setFinalStates(ext::set<State> {q3, q6, q8});
 
-  res.addTransition(q0, 'a', q0); // initial loops
-  res.addTransition(q0, 'b', q0);
+		res.addTransition(q0, 'a', q0); // initial loops
+		res.addTransition(q0, 'b', q0);
 
-  res.addTransition(q0, 'a', q1); // 3 simple matching automatas
+		res.addTransition(q0, 'a', q1); // 3 simple matching automatas
 
-  res.addTransition(q1, 'a', q2);
-  res.addTransition(q1, 'b', q2);
-  res.addTransition(q4, 'a', q5);
-  res.addTransition(q4, 'b', q5);
+		res.addTransition(q1, 'a', q2);
+		res.addTransition(q1, 'b', q2);
+		res.addTransition(q4, 'a', q5);
+		res.addTransition(q4, 'b', q5);
 
-  res.addTransition(q2, 'b', q3);
-  res.addTransition(q5, 'b', q6);
-  res.addTransition(q7, 'b', q8);
+		res.addTransition(q2, 'b', q3);
+		res.addTransition(q5, 'b', q6);
+		res.addTransition(q7, 'b', q8);
 
-  res.addTransition(q0, 'b', q4); // error transitions for replace
+		res.addTransition(q0, 'b', q4); // error transitions for replace
 
-  res.addTransition(q2, 'a', q6);
-  res.addTransition(q5, 'a', q8);
+		res.addTransition(q2, 'a', q6);
+		res.addTransition(q5, 'a', q8);
 
-  res.addTransition(q0, q4); // delete transition
-  res.addTransition(q1, q5);
-  res.addTransition(q2, q6);
+		res.addTransition(q0, q4); // delete transition
+		res.addTransition(q1, q5);
+		res.addTransition(q2, q6);
 
-  res.addTransition(q4, q7);
-  res.addTransition(q5, q8);
+		res.addTransition(q4, q7);
+		res.addTransition(q5, q8);
 
-  res.addTransition(q1, 'a', q4);
-  res.addTransition(q1, 'b', q4);
+		res.addTransition(q1, 'a', q4);
+		res.addTransition(q1, 'b', q4);
 
-  res.addTransition(q2, 'a', q5);
-  res.addTransition(q2, 'b', q5);
+		res.addTransition(q2, 'a', q5);
+		res.addTransition(q2, 'b', q5);
 
-  res.addTransition(q5, 'a', q7);
-  res.addTransition(q5, 'b', q7);
+		res.addTransition(q5, 'a', q7);
+		res.addTransition(q5, 'b', q7);
 
-  res.addTransition(q2, 'a', q2); // sequence matching loops
-  res.addTransition(q5, 'a', q5);
-  res.addTransition(q7, 'a', q7);
+		res.addTransition(q2, 'a', q2); // sequence matching loops
+		res.addTransition(q5, 'a', q5);
+		res.addTransition(q7, 'a', q7);
 
-  CPPUNIT_ASSERT(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+		CHECK(res == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 }
-
-void LevenshteinSequenceMatchingAutomatonTest::setUp() { }
-
-void LevenshteinSequenceMatchingAutomatonTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.h b/alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.h
deleted file mode 100644
index a08b8c64ab..0000000000
--- a/alib2algo/test-src/stringology/matching/LevenshteinSequenceMatchingAutomatonTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef LEVENSHTEIN_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-#define LEVENSHTEIN_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class LevenshteinSequenceMatchingAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(LevenshteinSequenceMatchingAutomatonTest);
-    CPPUNIT_TEST(testSimpleConstruction);
-		CPPUNIT_TEST(testSimpleWildcardConstruction);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimpleConstruction();
-		void testSimpleWildcardConstruction();
-};
-#endif //LEVENSHTEIN_SEQUENCE_MATCHING_AUTOMATA_TEST_H_
diff --git a/alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.cpp b/alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.cpp
index 4b02890103..4de746ad66 100644
--- a/alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.cpp
+++ b/alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.cpp
@@ -1,46 +1,40 @@
+#include <catch2/catch.hpp>
+
 #include <stringology/matching/SequenceMatchingAutomaton.h>
 #include <automaton/FSM/NFA.h>
 #include <string/LinearString.h>
 #include <automaton/simplify/UnreachableStatesRemover.h>
 
-#include "SequenceMatchingAutomatonTest.h"
-
-
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( SequenceMatchingAutomatonTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( SequenceMatchingAutomatonTest );
+TEST_CASE ( "Sequence Matching Automaton", "[unit][algo][stringology][matching]" ) {
+	SECTION ( "Test construction" ) {
+		ext::set<char> alphabet{'a', 'b', 'c', 'd'};
+		string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
+		auto resulting_automata = stringology::matching::SequenceMatchingAutomaton::construct(input_string);
 
-void SequenceMatchingAutomatonTest::testSimpleConstruction() {
-    ext::set<char> alphabet{'a', 'b', 'c', 'd'};
-    string::LinearString <char> input_string(alphabet, ext::vector<char>{'a', 'b', 'c'});
-    auto resulting_automata = stringology::matching::SequenceMatchingAutomaton::construct(input_string);
+		automaton::NFA <char, unsigned int> test(0);
+		test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
+		test.setStates(ext::set<unsigned int> {0, 1, 2, 3});
+		test.addFinalState(3);
 
-    automaton::NFA <char, unsigned int> test(0);
-    test.setInputAlphabet(ext::set<char>{'a', 'b', 'c', 'd'});
-    test.setStates(ext::set<unsigned int> {0, 1, 2, 3});
-    test.addFinalState(3);
+		test.addTransition(0, 'a', 0); // initial loop over whole alphabet
+		test.addTransition(0, 'b', 0);
+		test.addTransition(0, 'c', 0);
+		test.addTransition(0, 'd', 0);
 
-    test.addTransition(0, 'a', 0); // initial loop over whole alphabet
-    test.addTransition(0, 'b', 0);
-    test.addTransition(0, 'c', 0);
-    test.addTransition(0, 'd', 0);
+		test.addTransition(0, 'a', 1); // part of a sequence
 
-    test.addTransition(0, 'a', 1); // part of a sequence
+		test.addTransition(1, 'a', 1);
+		test.addTransition(1, 'c', 1);
+		test.addTransition(1, 'd', 1);
 
-    test.addTransition(1, 'a', 1);
-    test.addTransition(1, 'c', 1);
-    test.addTransition(1, 'd', 1);
+		test.addTransition(1, 'b', 2); // part of a sequence
 
-    test.addTransition(1, 'b', 2); // part of a sequence
+		test.addTransition(2, 'a', 2);
+		test.addTransition(2, 'b', 2);
+		test.addTransition(2, 'd', 2);
 
-    test.addTransition(2, 'a', 2);
-    test.addTransition(2, 'b', 2);
-    test.addTransition(2, 'd', 2);
+		test.addTransition(2, 'c', 3); // part of a sequence
 
-    test.addTransition(2, 'c', 3); // part of a sequence
-
-    CPPUNIT_ASSERT(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+		CHECK(test == automaton::simplify::UnreachableStatesRemover::remove(resulting_automata));
+	}
 }
-
-void SequenceMatchingAutomatonTest::setUp() { }
-
-void SequenceMatchingAutomatonTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.h b/alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.h
deleted file mode 100644
index cb49f2c1af..0000000000
--- a/alib2algo/test-src/stringology/matching/SequenceMatchingAutomatonTest.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-#define SEQUENCE_MATCHING_AUTOMATA_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class SequenceMatchingAutomatonTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(SequenceMatchingAutomatonTest);
-        CPPUNIT_TEST(testSimpleConstruction);
-    CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimpleConstruction();
-};
-#endif //SEQUENCE_MATCHING_AUTOMATA_TEST_H_
diff --git a/alib2algo/test-src/stringology/query/DAWGMatcherTest.cpp b/alib2algo/test-src/stringology/query/DAWGMatcherTest.cpp
index 7d7e5c66e1..9864ec987e 100644
--- a/alib2algo/test-src/stringology/query/DAWGMatcherTest.cpp
+++ b/alib2algo/test-src/stringology/query/DAWGMatcherTest.cpp
@@ -1,4 +1,4 @@
-#include "DAWGMatcherTest.h"
+#include <catch2/catch.hpp>
 
 #include "string/LinearString.h"
 #include "stringology/matching/DAWGMatcherConstruction.h"
@@ -8,48 +8,40 @@
 #include "string/generate/RandomStringFactory.h"
 #include "string/generate/RandomSubstringFactory.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( DAWGMatcherTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( DAWGMatcherTest );
-
-void DAWGMatcherTest::setUp ( ) {
-}
-
-void DAWGMatcherTest::tearDown ( ) {
-}
-
-void DAWGMatcherTest::testBackwardDAWGMatching ( ) {
-	ext::vector<std::string> subjects;
-	ext::vector<std::string> patterns;
-	ext::vector<ext::set<unsigned>> expectedOccs;
-
-	subjects.push_back("a"); patterns.push_back("a"); expectedOccs.push_back({0});
-	subjects.push_back("a"); patterns.push_back("b"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfa"); expectedOccs.push_back({0});
-	subjects.push_back("alfalfalfa"); patterns.push_back("blfalfalfa"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfb"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({0});
-	subjects.push_back("alfalfalfaalfalfalfaabfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); expectedOccs.push_back({0});
-	subjects.push_back("atggccttgcc"); patterns.push_back("gcc"); expectedOccs.push_back({3,8});
-	subjects.push_back("aaaaaaaaaa"); patterns.push_back("a"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8,9});
-	subjects.push_back("aaaaaaaaaa"); patterns.push_back("aa"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8});
-
-
-	for(size_t i = 0; i < subjects.size(); ++i) {
-		string::LinearString < > subject ( subjects[i] );
-		string::LinearString < > pattern ( patterns[i] );
-		indexes::stringology::SuffixAutomaton < > suffixAutomaton = stringology::matching::DAWGMatcherConstruction::construct ( pattern );
-		ext::set < unsigned > res = stringology::query::BackwardDAWGMatching::match ( subject, suffixAutomaton );
-		std::cout << subjects[i] << ' ' << patterns[i] << ' ' << res << std::endl;
-		CPPUNIT_ASSERT ( res == expectedOccs[i] );
+TEST_CASE ( "DAWG Matcher", "[unit][algo][stringology][query]" ) {
+	SECTION ( "Test Backward DAWG Matching" ) {
+		ext::vector<std::string> subjects;
+		ext::vector<std::string> patterns;
+		ext::vector<ext::set<unsigned>> expectedOccs;
+
+		subjects.push_back("a"); patterns.push_back("a"); expectedOccs.push_back({0});
+		subjects.push_back("a"); patterns.push_back("b"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfa"); expectedOccs.push_back({0});
+		subjects.push_back("alfalfalfa"); patterns.push_back("blfalfalfa"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfb"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({0});
+		subjects.push_back("alfalfalfaalfalfalfaabfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); expectedOccs.push_back({0});
+		subjects.push_back("atggccttgcc"); patterns.push_back("gcc"); expectedOccs.push_back({3,8});
+		subjects.push_back("aaaaaaaaaa"); patterns.push_back("a"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8,9});
+		subjects.push_back("aaaaaaaaaa"); patterns.push_back("aa"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8});
+
+
+		for(size_t i = 0; i < subjects.size(); ++i) {
+			string::LinearString < > subject ( subjects[i] );
+			string::LinearString < > pattern ( patterns[i] );
+			indexes::stringology::SuffixAutomaton < > suffixAutomaton = stringology::matching::DAWGMatcherConstruction::construct ( pattern );
+			ext::set < unsigned > res = stringology::query::BackwardDAWGMatching::match ( subject, suffixAutomaton );
+			INFO ( subjects[i] << ' ' << patterns[i] << ' ' << res );
+			CHECK ( res == expectedOccs[i] );
+		}
+
+		auto longSubject = string::generate::RandomStringFactory::generateLinearString (64 * 64, 512, false, true);
+		auto longPattern = string::generate::RandomSubstringFactory::generateSubstring(64 * 5, longSubject );
+		indexes::stringology::SuffixAutomaton < std::string > suffixAutomaton = stringology::matching::DAWGMatcherConstruction::construct ( longPattern );
+		ext::set < unsigned > res = stringology::query::BackwardDAWGMatching::match ( longSubject, suffixAutomaton );
+		ext::set < unsigned > resRef = stringology::exact::ExactFactorMatch::match ( longSubject, longPattern );
+		INFO ( "long: " << res );
+		CHECK ( res == resRef);
 	}
-
-	auto longSubject = string::generate::RandomStringFactory::generateLinearString (64 * 64, 512, false, true);
-	auto longPattern = string::generate::RandomSubstringFactory::generateSubstring(64 * 5, longSubject );
-	indexes::stringology::SuffixAutomaton < std::string > suffixAutomaton = stringology::matching::DAWGMatcherConstruction::construct ( longPattern );
-	ext::set < unsigned > res = stringology::query::BackwardDAWGMatching::match ( longSubject, suffixAutomaton );
-	ext::set < unsigned > resRef = stringology::exact::ExactFactorMatch::match ( longSubject, longPattern );
-	std::cout << "long: " << res << std::endl;
-	CPPUNIT_ASSERT ( res == resRef);
 }
-
diff --git a/alib2algo/test-src/stringology/query/DAWGMatcherTest.h b/alib2algo/test-src/stringology/query/DAWGMatcherTest.h
deleted file mode 100644
index 8241e3e7fc..0000000000
--- a/alib2algo/test-src/stringology/query/DAWGMatcherTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef SUFFIX_AUTOMATON_TEST_HPP_
-#define SUFFIX_AUTOMATON_TEST_HPP_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class DAWGMatcherTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE ( DAWGMatcherTest );
-	CPPUNIT_TEST ( testBackwardDAWGMatching );
-	CPPUNIT_TEST_SUITE_END ( );
-
-public:
-	void setUp ( );
-	void tearDown ( );
-
-	void testBackwardDAWGMatching ( );
-
-};
-
-#endif // SUFFIX_AUTOMATON_TEST_HPP_
diff --git a/alib2algo/test-src/stringology/query/OracleMatcherTest.cpp b/alib2algo/test-src/stringology/query/OracleMatcherTest.cpp
index a7f3515c08..144d27ebaf 100644
--- a/alib2algo/test-src/stringology/query/OracleMatcherTest.cpp
+++ b/alib2algo/test-src/stringology/query/OracleMatcherTest.cpp
@@ -1,4 +1,4 @@
-#include "OracleMatcherTest.h"
+#include <catch2/catch.hpp>
 
 #include "string/LinearString.h"
 #include "stringology/matching/OracleMatcherConstruction.h"
@@ -8,46 +8,39 @@
 #include "string/generate/RandomStringFactory.h"
 #include "string/generate/RandomSubstringFactory.h"
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( OracleMatcherTest, "stringology" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( OracleMatcherTest );
-
-void OracleMatcherTest::setUp ( ) {
-}
-
-void OracleMatcherTest::tearDown ( ) {
-}
-
-void OracleMatcherTest::testBackwardOracleMatching ( ) {
-	ext::vector<std::string> subjects;
-	ext::vector<std::string> patterns;
-	ext::vector<ext::set<unsigned>> expectedOccs;
-
-	subjects.push_back("a"); patterns.push_back("a"); expectedOccs.push_back({0});
-	subjects.push_back("a"); patterns.push_back("b"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfa"); expectedOccs.push_back({0});
-	subjects.push_back("alfalfalfa"); patterns.push_back("blfalfalfa"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfb"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({0});
-	subjects.push_back("alfalfalfaalfalfalfaabfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({});
-	subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); expectedOccs.push_back({0});
-	subjects.push_back("atggccttgcc"); patterns.push_back("gcc"); expectedOccs.push_back({3,8});
-	subjects.push_back("aaaaaaaaaa"); patterns.push_back("a"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8,9});
-
-
-	for(size_t i = 0; i < subjects.size(); ++i) {
-		string::LinearString < > subject ( subjects[i] );
-		string::LinearString < > pattern ( patterns[i] );
-		automaton::DFA < DefaultSymbolType, unsigned > oracleAutomaton = stringology::matching::OracleMatcherConstruction::construct ( pattern );
-		ext::set < unsigned > res = stringology::query::BackwardOracleMatching::match ( subject, oracleAutomaton );
-		std::cout << subjects[i] << ' ' << patterns[i] << ' ' << res << std::endl;
-		CPPUNIT_ASSERT ( res == expectedOccs[i] );
+TEST_CASE ( "Oracle Matcher", "[unit][algo][stringology][query]" ) {
+	SECTION ( "Test Backward Oracle Matching" ) {
+		ext::vector<std::string> subjects;
+		ext::vector<std::string> patterns;
+		ext::vector<ext::set<unsigned>> expectedOccs;
+
+		subjects.push_back("a"); patterns.push_back("a"); expectedOccs.push_back({0});
+		subjects.push_back("a"); patterns.push_back("b"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfa"); expectedOccs.push_back({0});
+		subjects.push_back("alfalfalfa"); patterns.push_back("blfalfalfa"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfa"); patterns.push_back("alfalfalfb"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({0});
+		subjects.push_back("alfalfalfaalfalfalfaabfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfa"); expectedOccs.push_back({});
+		subjects.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); patterns.push_back("alfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfalfalfaalfaa"); expectedOccs.push_back({0});
+		subjects.push_back("atggccttgcc"); patterns.push_back("gcc"); expectedOccs.push_back({3,8});
+		subjects.push_back("aaaaaaaaaa"); patterns.push_back("a"); expectedOccs.push_back({0,1,2,3,4,5,6,7,8,9});
+
+
+		for(size_t i = 0; i < subjects.size(); ++i) {
+			string::LinearString < > subject ( subjects[i] );
+			string::LinearString < > pattern ( patterns[i] );
+			automaton::DFA < DefaultSymbolType, unsigned > oracleAutomaton = stringology::matching::OracleMatcherConstruction::construct ( pattern );
+			ext::set < unsigned > res = stringology::query::BackwardOracleMatching::match ( subject, oracleAutomaton );
+			INFO ( subjects[i] << ' ' << patterns[i] << ' ' << res );
+			CHECK ( res == expectedOccs[i] );
+		}
+
+		auto longSubject = string::generate::RandomStringFactory::generateLinearString (64 * 64, 512, false, true);
+		auto longPattern = string::generate::RandomSubstringFactory::generateSubstring(64 * 5, longSubject );
+		automaton::DFA < std::string, unsigned > oracleAutomaton = stringology::matching::OracleMatcherConstruction::construct ( longPattern );
+		ext::set < unsigned > res = stringology::query::BackwardOracleMatching::match ( longSubject, oracleAutomaton );
+		ext::set < unsigned > resRef = stringology::exact::ExactFactorMatch::match ( longSubject, longPattern );
+		INFO ( "long: " << res );
+		CHECK ( res == resRef);
 	}
-
-	auto longSubject = string::generate::RandomStringFactory::generateLinearString (64 * 64, 512, false, true);
-	auto longPattern = string::generate::RandomSubstringFactory::generateSubstring(64 * 5, longSubject );
-	automaton::DFA < std::string, unsigned > oracleAutomaton = stringology::matching::OracleMatcherConstruction::construct ( longPattern );
-	ext::set < unsigned > res = stringology::query::BackwardOracleMatching::match ( longSubject, oracleAutomaton );
-	ext::set < unsigned > resRef = stringology::exact::ExactFactorMatch::match ( longSubject, longPattern );
-	std::cout << "long: " << res << std::endl;
-	CPPUNIT_ASSERT ( res == resRef);
 }
diff --git a/alib2algo/test-src/stringology/query/OracleMatcherTest.h b/alib2algo/test-src/stringology/query/OracleMatcherTest.h
deleted file mode 100644
index 886fc99358..0000000000
--- a/alib2algo/test-src/stringology/query/OracleMatcherTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef ORACLE_MATCHER_TEST_H_
-#define ORACLE_MATCHER_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class OracleMatcherTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE ( OracleMatcherTest );
-	CPPUNIT_TEST ( testBackwardOracleMatching );
-	CPPUNIT_TEST_SUITE_END ( );
-
-public:
-	void setUp ( );
-	void tearDown ( );
-
-	void testFactorOracleConstruction ( );
-	void testBackwardOracleMatching ( );
-};
-
-#endif // ORACLE_MATCHER_TEST_H_
diff --git a/alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.cpp b/alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.cpp
index 46ca18d388..2772a3268f 100644
--- a/alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.cpp
+++ b/alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.cpp
@@ -1,20 +1,15 @@
-#include "ExactBitParalelismTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/simulations/ExactBitParalelism.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( ExactBitParalelismTest, "bit paralelism" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( ExactBitParalelismTest );
+TEST_CASE ( "Exact Bit Parallelism", "[unit][algo][stringology][simulations]" ) {
+	SECTION ( "Simple" ) {
+		auto text = string::LinearString<>("adcabcaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
 
-void ExactBitParalelismTest::testSimple() {
-  auto text = string::LinearString<>("adcabcaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
+		ext::set<unsigned int> expected_result = {15};
 
-  ext::set<unsigned int> expected_result = {15};
-
-  CPPUNIT_ASSERT(expected_result == stringology::simulations::ExactBitParalelism::search(text, pattern));
+		CHECK(expected_result == stringology::simulations::ExactBitParalelism::search(text, pattern));
+	}
 }
-
-void ExactBitParalelismTest::setUp() { }
-
-void ExactBitParalelismTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.h b/alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.h
deleted file mode 100644
index 43c1d62322..0000000000
--- a/alib2algo/test-src/stringology/simulations/ExactBitParalelismTest.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef EXACT_BIT_PARALELISM_TEST_H_
-#define EXACT_BIT_PARALELISM_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class ExactBitParalelismTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(ExactBitParalelismTest);
-        CPPUNIT_TEST(testSimple);
-    CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimple();
-};
-#endif // EXACT_BIT_PARALELISM_TEST_H_
diff --git a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.cpp b/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.cpp
index be20ec6d25..bf1ed79560 100644
--- a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.cpp
+++ b/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.cpp
@@ -1,20 +1,15 @@
-#include "GeneralizedLevenshteinBitParalelismTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/simulations/GeneralizedLevenshteinBitParalelism.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( GeneralizedLevenshteinBitParalelismTest, "bit paralelism" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( GeneralizedLevenshteinBitParalelismTest );
+TEST_CASE ( "Generalized Levenshtein Bit Parallelism", "[unit][algo][stringology][simulations]" ) {
+	SECTION ( "Simple" ) {
+		auto text = string::LinearString<>("adbcbaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
 
-void GeneralizedLevenshteinBitParalelismTest::testSimple() {
-  auto text = string::LinearString<>("adbcbaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::set<unsigned int> expected_result = {3, 4, 5, 6, 7, 9, 11, 12, 13, 14};
-  auto result = stringology::simulations::GeneralizedLevenshteinBitParalelism::search(text, pattern, 3);
-  CPPUNIT_ASSERT(expected_result == result);
+		ext::set<unsigned int> expected_result = {3, 4, 5, 6, 7, 9, 11, 12, 13, 14};
+		auto result = stringology::simulations::GeneralizedLevenshteinBitParalelism::search(text, pattern, 3);
+		CHECK (expected_result == result);
+	}
 }
-
-void GeneralizedLevenshteinBitParalelismTest::setUp() { }
-
-void GeneralizedLevenshteinBitParalelismTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.h b/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.h
deleted file mode 100644
index 3bcfe69d2d..0000000000
--- a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinBitParalelismTest.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef GENERALIZED_LEVENSHTEIN_BIT_PARALELISM_TEST_H_
-#define GENERALIZED_LEVENSHTEIN_BIT_PARALELISM_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GeneralizedLevenshteinBitParalelismTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(GeneralizedLevenshteinBitParalelismTest);
-        CPPUNIT_TEST(testSimple);
-    CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimple();
-};
-#endif // GENERALIZED_LEVENSHTEIN_BIT_PARALELISM_TEST_H_
diff --git a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.cpp b/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.cpp
index 9602ac5f9c..b8520bcff4 100644
--- a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.cpp
+++ b/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.cpp
@@ -1,38 +1,33 @@
-#include "GeneralizedLevenshteinDynamicProgrammingTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/simulations/GeneralizedLevenshteinDynamicProgramming.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( GeneralizedLevenshteinDynamicProgrammingTest, "dynamic programming" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( GeneralizedLevenshteinDynamicProgrammingTest );
-
-void GeneralizedLevenshteinDynamicProgrammingTest::testTableConstruction() {
-  auto text = string::LinearString<>("adbcbaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::vector<ext::vector<unsigned int>> expected_result = {
-    ext::vector<unsigned int>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}),
-    ext::vector<unsigned int>({1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0}),
-    ext::vector<unsigned int>({2, 1, 0, 1, 2, 2, 1, 1, 1, 1, 0, 1, 2, 2, 1}),
-    ext::vector<unsigned int>({3, 2, 1, 0, 1, 2, 2, 2, 1, 2, 1, 0, 1, 2, 2}),
-    ext::vector<unsigned int>({4, 3, 2, 1, 1, 1, 2, 3, 2, 2, 2, 1, 0, 1, 2}),
-    ext::vector<unsigned int>({5, 4, 3, 2, 1, 1, 2, 3, 3, 3, 3, 2, 1, 0, 1}),
-    ext::vector<unsigned int>({6, 5, 4, 3, 2, 2, 1, 2, 4, 3, 4, 3, 2, 1, 0}),
-  };
-
-  CPPUNIT_ASSERT(expected_result == stringology::simulations::GeneralizedLevenshteinDynamicProgramming::compute_table(text, pattern));
+TEST_CASE ( "Generalized Levenshtein Dynamic Programming", "[unit][algo][stringology][simulations]" ) {
+	SECTION ( "Table" ) {
+		auto text = string::LinearString<>("adbcbaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
+
+		ext::vector<ext::vector<unsigned int>> expected_result = {
+			ext::vector<unsigned int>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}),
+			ext::vector<unsigned int>({1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0}),
+			ext::vector<unsigned int>({2, 1, 0, 1, 2, 2, 1, 1, 1, 1, 0, 1, 2, 2, 1}),
+			ext::vector<unsigned int>({3, 2, 1, 0, 1, 2, 2, 2, 1, 2, 1, 0, 1, 2, 2}),
+			ext::vector<unsigned int>({4, 3, 2, 1, 1, 1, 2, 3, 2, 2, 2, 1, 0, 1, 2}),
+			ext::vector<unsigned int>({5, 4, 3, 2, 1, 1, 2, 3, 3, 3, 3, 2, 1, 0, 1}),
+			ext::vector<unsigned int>({6, 5, 4, 3, 2, 2, 1, 2, 4, 3, 4, 3, 2, 1, 0}),
+		};
+
+		CHECK(expected_result == stringology::simulations::GeneralizedLevenshteinDynamicProgramming::compute_table(text, pattern));
+	}
+
+	SECTION ( "Occurences" ) {
+		auto text = string::LinearString<>("adbcbaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
+
+		ext::set<unsigned int> expected_result = {3, 4, 5, 6, 7, 9, 11, 12, 13, 14};
+		auto result = stringology::simulations::GeneralizedLevenshteinDynamicProgramming::search(text, pattern, 3);
+
+		CHECK(expected_result == result);
+	}
 }
-
-void GeneralizedLevenshteinDynamicProgrammingTest::testSearch() {
-  auto text = string::LinearString<>("adbcbaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::set<unsigned int> expected_result = {3, 4, 5, 6, 7, 9, 11, 12, 13, 14};
-  auto result = stringology::simulations::GeneralizedLevenshteinDynamicProgramming::search(text, pattern, 3);
-
-  CPPUNIT_ASSERT(expected_result == result);
-}
-
-void GeneralizedLevenshteinDynamicProgrammingTest::setUp() { }
-
-void GeneralizedLevenshteinDynamicProgrammingTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.h b/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.h
deleted file mode 100644
index 3c044661d4..0000000000
--- a/alib2algo/test-src/stringology/simulations/GeneralizedLevenshteinDynamicProgrammingTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef GENERALIZED_LEVENSHTEIN_DYNAMIC_PROGRAMMING_TEST_H_
-#define GENERALIZED_LEVENSHTEIN_DYNAMIC_PROGRAMMING_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class GeneralizedLevenshteinDynamicProgrammingTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(GeneralizedLevenshteinDynamicProgrammingTest);
-    CPPUNIT_TEST(testTableConstruction);
-		CPPUNIT_TEST(testSearch);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testTableConstruction();
-		void testSearch();
-};
-#endif // LEVENSHTEIN_DYNAMIC_PROGRAMMING_TEST_H_
diff --git a/alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.cpp b/alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.cpp
index 60d14f2eb1..7f785986a7 100644
--- a/alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.cpp
+++ b/alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.cpp
@@ -1,20 +1,15 @@
-#include "HammingBitParalelismTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/simulations/HammingBitParalelism.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( HammingBitParalelismTest, "bit paralelism" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( HammingBitParalelismTest );
+TEST_CASE ( "Hamming Bit Parallelism", "[unit][algo][stringology][simulations]" ) {
+	SECTION ( "Simple" ) {
+		auto text = string::LinearString<>("adcabcaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
 
-void HammingBitParalelismTest::testSimple() {
-  auto text = string::LinearString<>("adcabcaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::set<unsigned int> expected_result = {7,15};
-  auto result = stringology::simulations::HammingBitParalelism::search(text, pattern, 3);
-  CPPUNIT_ASSERT(expected_result == result);
+		ext::set<unsigned int> expected_result = {7,15};
+		auto result = stringology::simulations::HammingBitParalelism::search(text, pattern, 3);
+		CHECK(expected_result == result);
+	}
 }
-
-void HammingBitParalelismTest::setUp() { }
-
-void HammingBitParalelismTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.h b/alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.h
deleted file mode 100644
index 540acf16b4..0000000000
--- a/alib2algo/test-src/stringology/simulations/HammingBitParalelismTest.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef HAMMING_BIT_PARALELISM_TEST_H_
-#define HAMMING_BIT_PARALELISM_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class HammingBitParalelismTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(HammingBitParalelismTest);
-        CPPUNIT_TEST(testSimple);
-    CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimple();
-};
-#endif // HAMMING_BIT_PARALELISM_TEST_H_
diff --git a/alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.cpp b/alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.cpp
index e6f2281f9c..97dbca5b44 100644
--- a/alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.cpp
+++ b/alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.cpp
@@ -1,39 +1,33 @@
-#include "HammingDynamicProgrammingTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/simulations/HammingDynamicProgramming.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( HammingDynamicProgrammingTest, "dynamic programming" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( HammingDynamicProgrammingTest );
-
-void HammingDynamicProgrammingTest::testTableConstruction() {
-  auto text = string::LinearString<>("adcabcaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::vector<ext::vector<unsigned int>> expected_result = {
-    ext::vector<unsigned int>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}),
-    ext::vector<unsigned int>({4, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0}),
-    ext::vector<unsigned int>({4, 5, 0, 2, 2, 1, 2, 2, 1, 1, 2, 0, 2, 2, 2, 2}),
-    ext::vector<unsigned int>({4, 5, 6, 1, 3, 2, 2, 3, 3, 1, 2, 3, 0, 2, 3, 3}),
-    ext::vector<unsigned int>({4, 5, 6, 7, 2, 3, 3, 3, 4, 3, 2, 3, 3, 0, 3, 4}),
-    ext::vector<unsigned int>({4, 5, 6, 6, 8, 3, 3, 4, 4, 5, 4, 3, 4, 4, 0, 4}),
-    ext::vector<unsigned int>({4, 4, 6, 7, 6, 9, 4, 3, 4, 5, 5, 5, 4, 5, 5, 0}),
-  };
-
-  CPPUNIT_ASSERT(expected_result == stringology::simulations::HammingDynamicProgramming::compute_table(text, pattern, 3));
-}
-
-void HammingDynamicProgrammingTest::testSearching() {
-  auto text = string::LinearString<>("patternpettannbalastpettern");
-  auto pattern = string::LinearString<>("pattern");
-
-  auto expected_result = ext::set<unsigned int>({7, 14, 27});
-  auto result = stringology::simulations::HammingDynamicProgramming::search(text, pattern, 3);
-
-  CPPUNIT_ASSERT(expected_result == result);
+TEST_CASE ( "Hamming Dynamic Programming", "[unit][algo][stringology][simulations]" ) {
+	SECTION ( "Table" ) {
+		auto text = string::LinearString<>("adcabcaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
+
+		ext::vector<ext::vector<unsigned int>> expected_result = {
+			ext::vector<unsigned int>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}),
+			ext::vector<unsigned int>({4, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0}),
+			ext::vector<unsigned int>({4, 5, 0, 2, 2, 1, 2, 2, 1, 1, 2, 0, 2, 2, 2, 2}),
+			ext::vector<unsigned int>({4, 5, 6, 1, 3, 2, 2, 3, 3, 1, 2, 3, 0, 2, 3, 3}),
+			ext::vector<unsigned int>({4, 5, 6, 7, 2, 3, 3, 3, 4, 3, 2, 3, 3, 0, 3, 4}),
+			ext::vector<unsigned int>({4, 5, 6, 6, 8, 3, 3, 4, 4, 5, 4, 3, 4, 4, 0, 4}),
+			ext::vector<unsigned int>({4, 4, 6, 7, 6, 9, 4, 3, 4, 5, 5, 5, 4, 5, 5, 0}),
+		};
+
+		CHECK(expected_result == stringology::simulations::HammingDynamicProgramming::compute_table(text, pattern, 3));
+	}
+
+	SECTION ( "Occurences" ) {
+		auto text = string::LinearString<>("patternpettannbalastpettern");
+		auto pattern = string::LinearString<>("pattern");
+
+		auto expected_result = ext::set<unsigned int>({7, 14, 27});
+		auto result = stringology::simulations::HammingDynamicProgramming::search(text, pattern, 3);
+
+		CHECK(expected_result == result);
+	}
 }
-
-
-void HammingDynamicProgrammingTest::setUp() { }
-
-void HammingDynamicProgrammingTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.h b/alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.h
deleted file mode 100644
index 87ce0f0e4b..0000000000
--- a/alib2algo/test-src/stringology/simulations/HammingDynamicProgrammingTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef HAMMING_DYNAMIC_PROGRAMMING_TEST_H_
-#define HAMMING_DYNAMIC_PROGRAMMING_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class HammingDynamicProgrammingTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(HammingDynamicProgrammingTest);
-    CPPUNIT_TEST(testTableConstruction);
-		CPPUNIT_TEST(testSearching);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testTableConstruction();
-		void testSearching();
-};
-#endif // HAMMING_DYNAMIC_PROGRAMMING_TEST_H_
diff --git a/alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.cpp b/alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.cpp
index 06db363b49..f2e774b9ae 100644
--- a/alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.cpp
+++ b/alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.cpp
@@ -1,20 +1,15 @@
-#include "LevenshteinBitParalelismTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/simulations/LevenshteinBitParalelism.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( LevenshteinBitParalelismTest, "bit paralelism" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( LevenshteinBitParalelismTest );
+TEST_CASE ( "Levenshtein Bit Parallelism", "[unit][algo][stringology][simulations]" ) {
+	SECTION ( "Simple" ) {
+		auto text = string::LinearString<>("adcabcaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
 
-void LevenshteinBitParalelismTest::testSimple() {
-  auto text = string::LinearString<>("adcabcaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::set<unsigned int> expected_result = {3, 4, 6, 7, 8, 10, 12, 13, 14, 15};
-  auto result = stringology::simulations::LevenshteinBitParalelism::search(text, pattern, 3);
-  CPPUNIT_ASSERT(expected_result == result);
+		ext::set<unsigned int> expected_result = {3, 4, 6, 7, 8, 10, 12, 13, 14, 15};
+		auto result = stringology::simulations::LevenshteinBitParalelism::search(text, pattern, 3);
+		CHECK(expected_result == result);
+	}
 }
-
-void LevenshteinBitParalelismTest::setUp() { }
-
-void LevenshteinBitParalelismTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.h b/alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.h
deleted file mode 100644
index 89ad3fde39..0000000000
--- a/alib2algo/test-src/stringology/simulations/LevenshteinBitParalelismTest.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef LEVENSHTEIN_BIT_PARALELISM_TEST_H_
-#define LEVENSHTEIN_BIT_PARALELISM_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class LevenshteinBitParalelismTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(LevenshteinBitParalelismTest);
-        CPPUNIT_TEST(testSimple);
-    CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testSimple();
-};
-#endif // LEVENSHTEIN_BIT_PARALELISM_TEST_H_
diff --git a/alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.cpp b/alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.cpp
index df2a3454a3..4a6de855ea 100644
--- a/alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.cpp
+++ b/alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.cpp
@@ -1,37 +1,33 @@
-#include "LevenshteinDynamicProgrammingTest.h"
+#include <catch2/catch.hpp>
 
 #include <string/LinearString.h>
 #include <stringology/simulations/LevenshteinDynamicProgramming.h>
 
-CPPUNIT_TEST_SUITE_NAMED_REGISTRATION ( LevenshteinDynamicProgrammingTest, "dynamic programming" );
-CPPUNIT_TEST_SUITE_REGISTRATION ( LevenshteinDynamicProgrammingTest );
-
-void LevenshteinDynamicProgrammingTest::testTableConstruction() {
-  auto text = string::LinearString<>("adcabcaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::vector<ext::vector<unsigned int>> expected_result = {
-    ext::vector<unsigned int>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}),
-    ext::vector<unsigned int>({1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0}),
-    ext::vector<unsigned int>({2, 1, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 2, 2, 1}),
-    ext::vector<unsigned int>({3, 2, 1, 1, 2, 1, 2, 2, 2, 1, 2, 1, 0, 1, 2, 2}),
-    ext::vector<unsigned int>({4, 3, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 1, 0, 1, 2}),
-    ext::vector<unsigned int>({5, 4, 3, 2, 3, 3, 2, 3, 4, 3, 3, 3, 2, 1, 0, 1}),
-    ext::vector<unsigned int>({6, 5, 4, 3, 2, 4, 3, 2, 3, 4, 3, 4, 3, 2, 1, 0}),
-  };
-
-  CPPUNIT_ASSERT(expected_result == stringology::simulations::LevenshteinDynamicProgramming::compute_table(text, pattern));
-}
-
-void LevenshteinDynamicProgrammingTest::testSearch() {
-  auto text = string::LinearString<>("adcabcaabadbbca");
-  auto pattern = string::LinearString<>("adbbca");
-
-  ext::set<unsigned int> expected_result = {3, 4, 6, 7, 8, 10, 12, 13, 14, 15};
-  auto result = stringology::simulations::LevenshteinDynamicProgramming::search(text, pattern, 3);
-  CPPUNIT_ASSERT(expected_result == result);
+TEST_CASE ( "Levenshtein Dynamic Programming", "[unit][algo][stringology][simulations]" ) {
+	SECTION ( "Table" ) {
+
+		auto text = string::LinearString<>("adcabcaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
+
+		ext::vector<ext::vector<unsigned int>> expected_result = {
+			ext::vector<unsigned int>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}),
+			ext::vector<unsigned int>({1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0}),
+			ext::vector<unsigned int>({2, 1, 0, 1, 1, 1, 2, 1, 1, 1, 1, 0, 1, 2, 2, 1}),
+			ext::vector<unsigned int>({3, 2, 1, 1, 2, 1, 2, 2, 2, 1, 2, 1, 0, 1, 2, 2}),
+			ext::vector<unsigned int>({4, 3, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 1, 0, 1, 2}),
+			ext::vector<unsigned int>({5, 4, 3, 2, 3, 3, 2, 3, 4, 3, 3, 3, 2, 1, 0, 1}),
+			ext::vector<unsigned int>({6, 5, 4, 3, 2, 4, 3, 2, 3, 4, 3, 4, 3, 2, 1, 0}),
+		};
+
+		CHECK(expected_result == stringology::simulations::LevenshteinDynamicProgramming::compute_table(text, pattern));
+	}
+
+	SECTION ( "Occurences" ) {
+		auto text = string::LinearString<>("adcabcaabadbbca");
+		auto pattern = string::LinearString<>("adbbca");
+
+		ext::set<unsigned int> expected_result = {3, 4, 6, 7, 8, 10, 12, 13, 14, 15};
+		auto result = stringology::simulations::LevenshteinDynamicProgramming::search(text, pattern, 3);
+		CHECK(expected_result == result);
+	}
 }
-
-void LevenshteinDynamicProgrammingTest::setUp() { }
-
-void LevenshteinDynamicProgrammingTest::tearDown() { }
diff --git a/alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.h b/alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.h
deleted file mode 100644
index 2658bbafa6..0000000000
--- a/alib2algo/test-src/stringology/simulations/LevenshteinDynamicProgrammingTest.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef LEVENSHTEIN_DYNAMIC_PROGRAMMING_TEST_H_
-#define LEVENSHTEIN_DYNAMIC_PROGRAMMING_TEST_H_
-
-#include <cppunit/extensions/HelperMacros.h>
-
-class LevenshteinDynamicProgrammingTest : public CppUnit::TestFixture {
-	CPPUNIT_TEST_SUITE(LevenshteinDynamicProgrammingTest);
-    CPPUNIT_TEST(testTableConstruction);
-		CPPUNIT_TEST(testSearch);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-    void setUp ( );
-    void tearDown ( );
-
-    void testTableConstruction();
-		void testSearch();
-};
-#endif // LEVENSHTEIN_DYNAMIC_PROGRAMMING_TEST_H_
-- 
GitLab