Using reserve() efficiently

Without the reserve()
first test would get allocated 5 bytes, then " world" would allocate 6 bytes, the combination then would get 11 bytes allocated, both temporary. This then does not fit into the original test allocation, and even though the combination String will be destroyed, i think a new String will be allocated to hold these 11 bytes, and the unused space which will be a block of 5 + 6 + 11 bytes should be freed and can be used by any new object that fits into that. Fragmentation can go wild when global objects get expanded beyond their previously allocated size while there is no space for them to expand.
btw

String test = "           ";
test = "";

comes down to the same as

String test = "";
test.reserve(11);
String test;            // No memory allocated
test.reserve(50);       // 50 bytes allocated on the heap
test = "Hello";         // first 5 bytes used (plus trailing null)
test = test + " world"; // "world" dynamically allocated in a String, result of the sum allocated in a new dynamic String, then copied into test, then released 
String test;            // No memory allocated
test = "Hello";         // 6 bytes allocated)
test = test + " world"; // "world" dynamically allocated in a String, result of the sum allocated in a new dynamic String, then test is expanded to meet the new size and temp string copied into test, then all temporary get released 

This is the trick. Use MyString.concate( "blah blah");

That defeats/by passes the created buffer of String.reserve.

That is not true. If you use concat, you only use 1 temporary String, which then gets concatenated to 'test' and stored in it's place. Instead of using the '+' where there are 2 temporary Strings and then a whole new String gets created to store the result unless the allocated space for the target String is sufficiently big to store the result, which is what you do by using reserve() .
Consider though this scenario

String test = "Hello";
// test.reserve(20);
String another = "Oh dear";
test.concat(" world");

now while you use concat(). you will still fragment the heap because the allocated space for the concatenated String is simply to small (unless you un-comment the reserve() )
while

String test = "Hello";
test.reserve(20);
String another = "Oh dear";
test = test + "world";

does not fragment the heap, though does require more heap space available for the process.
All of this is of course assuming that nothing gets optimized by the compiler.
By using concat() there are several scenarios where you can prevent fragmentation without using reserve() and reduce temporary memory requirements.

If you know the size to use with reserve, then why not use a char array and avoid String entirely?

A char array can not be the return argument of a function. Some libraries, mainly the ones written for ESP's, have functions that return a String. Using the String class while aware of it's complications can be more straightforward to code.

Also, with an ESP32, as long as there is no code in loop() the OS will do memory cleanups.