Unit Testing - Integration Testing of Multiple Components (not Dummy)

I am interested in testing the integration of the component I have written (a battery) with the Generic Symmetric ESS component as I have been seeing some issues around starting the battery in this setup.

I have previously written some unit tests for my battery using the ComponentTest class which allows one to instantiate a component and add references to dummy components where needed such as ModbusBridge. Like this:

new ComponentTest(new MyBatteryImpl()) //
				.addReference("cm", new DummyConfigurationAdmin()) //
				.addReference("componentManager", new DummyComponentManager(clock)) //
				.addReference("setModbus", new DummyModbusBridge(MODBUS_ID)) //
				.activate(MyConfig.create() //
						.setId(BATTERY_ID) //
						.setModbusId(MODBUS_ID) //
						.setModbusUnitId(1) //
						.setStartStop(StartStopConfig.START) //
						.build())
				.next(new TestCase("Check State Machine = UNDEFINED to begin")
						.input(STATUS_CHANNEL, MyBattery.Status.SLEEP) // Ensure that it is in a sleep mode to begin with, so it will need to be woken up
						.output(STATE_MACHINE, StateMachine.State.UNDEFINED))

This works fine, but I have a couple of issues:

  1. I would like to call a method on the MyBatteryImpl class as part of a test case. Specifically I would like to call the setStartStop method to simulate the Generic ESS calling this method to start the battery. I know that I can use the input method of the TestCase to set specific channel value, but how can I call an actual method on the unit under test?
  2. I would like to write a test involving an ’ EssGenericManagedSymmetric’ and ‘MyBattery’ (with a dummy battery inverter). Is this possible, and are there any examples available where this is done? I can’t find any examples of tests where there are two ‘real’ components under test - as opposed to a single real component under test and references to only dummy components.

Hope my questions make sense - any help greatly appreciated.

Thanks,
Thomas

Update

I have an answer to question 1, which is quite simple. It is just to declare the battery (or SUT) as a variable which is passed to the test case. Code looks like the below:

// Define the battery as a variable
MyBattery sut = new MyBattery();

// Set up the test	
ComponentTest test = new ComponentTest(sut) //
			.addReference("cm", new DummyConfigurationAdmin()) //
			.addReference("componentManager", new DummyComponentManager(clock)) //
			.addReference("setModbus", new DummyModbusBridge(MODBUS_ID)) //
			.activate(MyConfig.create() //
					.setId(BATTERY_ID) //
					.setModbusId(MODBUS_ID) //
					.setModbusUnitId(1) //
					.setStartStop(StartStopConfig.AUTO) //
					.build())
			.next(new TestCase("Start in UNDEFINED state. The StartStop is UNDEFINED to begin with")
					.input(STATUS_CHANNEL, Status.IDLE)
					.output(STATE_MACHINE, StateMachine.State.UNDEFINED)
					.output(START_STOP, StartStop.UNDEFINED))


// Call method on the battery
sut.setStartStop(StartStop.START);

// Continue the test
test.next(new TestCase("Check that nothing has changed (yet)")
					.output(STATE_MACHINE, StateMachine.State.UNDEFINED)
					.output(START_STOP, StartStop.UNDEFINED))

I still am not sure how it is possible to define a test involving a Generic ESS and MyBattery.

Hi Thomas,

I am begineer of OpenEMS. I am also interested in implementing of new Battery. Could you tell me where you modified the code and how did you implement it?

Thank you very much in advance.

Best regards,
EEM

Hi EEMChula,

Sure I can provide some information. Can you let me know a little more about the battery you want to implement in OpenEMS? What connectivity does the battery provide (e.g modbus)? Do you have a Modbus specification for the battery?

In general it is necessary to create a new device in OpenEMS This guide ( Implementing a device :: Open Energy Management System (openems.github.io)) is a good starting point. The main programming task is to implement the communication with the device, which for me involved defining all the Modbus registers used by the battery and mapping these to OpenEMS channels.

I found it very useful to thoroughly read the code for existing battery implementations in OpenEMS - e.g for the Fenecon Home and Commercial batteries - and I used this as the basis for the device that I wrote.

Happy to share more information and my code if you can provide a little more info on your situation :slight_smile:

Hi thomas,

Thank you very much for your response. I followed this guide(Implementing a device :: Open Energy Management System) to implement new Meter. I haven’t tried yet for a new battery. I will try, and follow your above suggestions and update you.

Thanks again.

hello Thomas,

I also am having troubles defining a battery.
My biggest problem is that the battery communicates with an RS485 cable to the inverter (Sinexcel PWS2-30P-EX). how did you resolve this problem? i have a working modbus-tcp connection with the inverter but this doesn’t give me an ESS.ID so i cant implement any controller. Do you have an idea how to specify this in code?

Thanks in advance!

With kind regards,

Sven

Hi Sven,

I have some ideas, but I have a couple of questions before I can say which approach might be best…

  1. Is your inverter already supported by OpenEMS? Or is it necessary to define a new device for this?
  2. Does the modbus TCP connection with your inverter report values such as State of Charge, Battery voltage, temperature etc? (I.e the battery parameters which are defined in the Battery Nature within OpenEMS).

Thomas

Hello Thomas,

Thankyou for your quick response.

  1. The Sinexcel inverter seems supported (i see other people with this inverter also on the forum but they all dont have a actual battery connected). The state of the inverter is also correctly reported in openems UI (so when it has an error you see a red exclamation mark in the top and when there is no error it turns green). I However get no dashboard data shown or any data visible in UI or Edge.
  2. Yes the Battery gives all BMS information to the Sinexcell inverter and sinexcell inverter listens to this (so max charge current is only 9 amps the sinexcell will not go past that). These values i dont get visible in Edge or UI.

Sven

Just for reference, there is also a separate thread about the Sinexcel + Battery problem → Sinexcel inverter with battery - #2 by stefan.feilmeier


Back to the original topic:

Hi @thomas.

Generally we avoid hard-wired connection between multiple OSGi bundles to avoid spaghetti code. But of course you can to that for your specific use-case. Here is a (old but simple) example of a JUnit test that activates two Components → https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.bosch.bpts5hybrid/test/io/openems/edge/bosch/bpts5hybrid/pv/BoschBpts5HybridPvTest.java

If anyway you hard-wire your Battery with Generic-ESS, you can simply rely on Generic-Ess to call the setStartStop method. Just like as it is done in the Generic-ESS Junit test → https://github.com/OpenEMS/openems/blob/develop/io.openems.edge.ess.generic/test/io/openems/edge/ess/generic/symmetric/EssGenericManagedSymmetricImplTest.java#L47-L73

By the way, just a small note: if you want to keep the ‘fluent’ coding style in JUnit tests, there are fluent-helpers to call a method in a cycle-event, e.g.

Regards,
Stefan