You're doing just the right thing with logging the bus data. That piece tends to be a bit easier than loading bus data in Simulink.
With any of the loading blocks, including From File and Inport blocks, you need to tell the block what kind of data to expect. Because buses are flexible, in order to load bus data, you need to have a specification for what the loading block should expect to find in the bus you're loading.
Luckily, there are some helper functions to make creating this bus object easy, when you want to load bus data that was logged from another model. You can use the Simulink.Bus.createObject function to create a Simulink.Bus specification for the bus you log in test_bus_load.
busInfo = Simulink.Bus.createObject('test_bus_save','test_bus_save/Bus Creator');
The return is a structure array (scalar, in this case, because we only passed in one block name) with a field for the block handle (block) and the name of the Simulink.Bus object specification (busName). The default name used when you do not name the bus signal in the model is slBus1, and if you name the bus signal, the Simulink.Bus specification created using this function takes the same name.
You can save this Simulink.Bus specification to a file and load the specification into the base workspace using a model callback for the model that loads the bus. Whatever strategy you use, the model loading the bus data needs access to the corresponding Simulink.Bus object.
When you specify the Output data type for the From File block, use the name of the Simulink.Bus object, not the name of the variable containing the structure of bus data. In this case, you would enter Bus: slBus1.
If you look into the bus object created with the Simulink.Bus.createObject function, you'll see it contains Simulink.BusElement objects that specify properties for each bus element, including the name and data type.
I hope this helps!