albertaloop / T_SWE_2022_2023

Software for AlbertaLoop's first-generation pod.
MIT License
3 stars 0 forks source link

GUI Backend - Test Command Classes #10

Closed Iyury1 closed 2 years ago

Iyury1 commented 2 years ago

Background

In the GUI backend, the Command, MWindowWrapper, Logic, and HealthCheckReq classes together implement the "Command pattern".

Command pattern overview: https://refactoring.guru/design-patterns/command

The entity's involved to implement the command pattern are the Client, Invoker, Command, and Receiver.

The Client will call the functions belonging to the Invoker: setCommand(command), and executeCommand(). The function setCommand(command) sets a variable "command" to the value passed by the function call parameter. The function executeCommand() calls the execute() function of the command previously set.

Each Command class must contain an execute() method called by the Invoker, and a reference the Receiver for that command. The Command's execute() function will call functions belonging to its Receiver.

In our GUI backend, the class MWindowWrapper will serve as both the Client and the Invoker. When command buttons are pressed in the UI, a function attached to that button within MWindowWrapper will call the setCommand() and executeCommand() functions also within MWindowWrapper. The receiver for a command must also be set when the command's constructor is called. MWindowWrapper will contain references to the receiver classes Logic and HealthCheckReq, which will be stored in a list "receivers[]" at index 0 and 1 respectively.

EX:

Attaching a function to a UI button: self.launchBtn.clicked.connect(self.launchBtn_clicked)

Launch button function definition: def launchBtn_clicked(self): self.setCommand(Launch(self.receivers[0])) self.executeCommand()

Definitions for setCommand() and executeCommand(): def setCommand(self, command): self.command = command def executeCommand(self): self.command.execute()

Task Summary

The first thing we want to do is move all command classes into a single file "Commands.py", including the Command super class. This will save space in our project.

Since we already have created Command classes, each with its own message and execute function, we want to test these Command classes interacting with the other entities of the "command pattern".

On a new branch from GUI/main, create a python file "command_test.py". Inside this new files, create a "MockInvoker" class and a "MockReceiver" class. MockInvoker should have variables "command" and "receiver", and functions "setCommand(command)" and "executeCommand()". MockReceiver should have a function "printMessage(message)". Modify each execute() function of the commands to call receiver.printMessage(self.message).

Inside "if name == "main": " of command_test.py, instantiate the MockInvoker and MockReceiver functions by calling their constructors.

mockInvoker = MockInvoker() mockReceiver = MockReceiver()

Then for each Command class, instantiate the command by calling the constructor for that command and providing the MockReceiver class as a parameter to the constructor. The Command classes may have to be modified to hold the receiver as a variable. Then call the Invoker functions setCommand(command) and executeCommand().

estop = Estop(mockReceiver) mockInvoker.setCommand(estop) mockInvoker.executeCommand()

Do this for each command. When you run "command_test.py", the message belonging to each command should be printed to the console.

Acceptance Criteria