Mocks¶
Test mocks: they fake objects for testing.
Added in version 7.0.
- class sopel.tests.mocks.MockIRCBackend(bot: AbstractBot)¶
Fake IRC connection backend for testing purpose.
- Parameters:
bot (
sopel.bot.Sopel) – a Sopel instance
This backend doesn’t require an actual connection. Instead, it stores every message sent in the
message_sentlist.You can use the
rawlist()function to compare the messages easily, and theclear_message_sent()method to clear previous messages.Assuming you have a properly configured
bot(i.e., an instance ofSopelwith this fakebackend), you can access its sent messages like this:>>> from sopel.tests import rawlist >>> bot.backend.irc_send(b'PRIVMSG #channel :Hi!\r\n') >>> bot.backend.message_sent == rawlist('PRIVMSG #channel :Hi!') True >>> bot.backend.clear_message_sent() [b'PRIVMSG #channel :Hi!\r\n'] >>> bot.backend.message_sent []
See also
The
parent classcontains all the methods that can be used on this test backend.See also
The
BotFactoryautomatically uses this fake backend when creating an instance ofSopel. As a result, it should be the preferred method of creating a test instance of Sopel with this fake connection backend.- clear_message_sent() list[bytes]¶
Clear and return previous messages sent.
- Returns:
a copy of the cleared messages sent
- Return type:
Added in version 7.1.
- irc_send(data: bytes) None¶
Store
dataintomessage_sent.
- message_sent: list[bytes]¶
List of raw messages sent by the bot.
This list will be populated each time the
irc_send()method is used: it will contain the raw IRC lines the bot wanted to send.You can clear this list with the
clear_message_sent()method, or use therawlist()function to compare it.
- on_irc_error(pretrigger: PreTrigger) None¶
Action to perform when the server sends an error event.
- Parameters:
pretrigger – PreTrigger object with the error event
On IRC error, if
bot.hasquitis set, the backend should close the connection so the bot can quit or reconnect as required.
- run_forever() NoReturn¶
Run the backend forever (blocking call).
This method is responsible for initiating the connection to the server, and it must call
bot.on_connectonce connected, orbot.on_closeif it fails to connect.Upon successful connection, it must run forever, listening to the server and allowing the bot to use
send_command()in a thread-safe way.
- class sopel.tests.mocks.MockIRCServer(bot: Sopel, join_threads: bool = True)¶
Fake IRC Server that can send messages to a test bot.
- Parameters:
bot – test bot instance to send messages to
join_threads – whether message functions should join running threads before returning (default:
True)
This mock object helps developers when they want to simulate an IRC server sending messages to the
bot(e.g., using itsmessage()method or its more specific methods).Changed in version 7.1: The
join_threadsparameter has been added.See also
The
IRCFactoryfactory can be used to create such a mock object, either directly or by usingpytestand theircfactory()fixture.Important
This fake IRC server does not generate any network activity, and it does not react to anything the
botmay send, as it is not an actual IRC server implementation.Important
Sending messages to the bot may result in running threads: the bot uses threads to run triggers in parallel. This fake IRC server tries to join these threads after sending messages to the bot.
To provide for those rarer test cases where this behavior is not desirable, it can be controlled in two ways:
set
join_threadstoTrue(the default) to automatically join threads after sending messagesuse the
blockingoptional argument of each method to overridejoin_threads
Plugin authors should be wary of turning auto-join off, as this may result in unpredictable behaviors and flaky tests.
- bot: Sopel¶
The bot instance used by the server to send messages.
Note
The bot instance should use a
MockIRCBackendfor testing.
- channel_joined( ) None¶
Send events as if the bot just joined a channel.
- Parameters:
channel – channel to send message for
users – list (or tuple) of nicknames that will be present in the
RPL_NAMREPLYeventblocking – whether to block until all triggered threads have finished (optional)
This will send 2 messages to the bot:
a
RPL_NAMREPLYevent (353), giving information aboutuserspresent inchannela
RPL_ENDOFNAMESevent (366) for completion
Use this to emulate when the bot joins a channel, and the server replies with the list of connected users:
factory.channel_joined('#test', ['Owner', '@ChanServ'])
In this example, the bot will know that there are 2 other users present in
#test: “Owner” (a regular user) and “ChanServ” (which is a channel operator). Note that the bot itself will be added to the list of users automatically, and you should not pass it in theusersparameter.This is particularly useful to populate the bot’s memory of who is in a channel.
If
blockingisTrue, this method will wait to join all running triggers’ threads before returning. Setting it toFalsewill skip this step. If not specified, thejoin_threadsattribute will be obeyed.Changed in version 7.1: The
blockingparameter has been added.Note
To add a user to a channel after using this method, you should use the
join()method.
- invite( ) None¶
Send events as if a
usersent anINVITE.- Parameters:
user – the user sending the
INVITEmessagenick – the nick of the invited user
channel – where the nick is invited to
blocking – whether to block until all triggered threads have finished (optional)
This will send one event: an
INVITEevent fromusertonickto join the givenchannel.Use this to emulate when a user invites someone else to a channel:
factory.invite(MockUser('Owner'), 'Sopel' '#destination')
If
blockingisTrue, this method will wait to join all running triggers’ threads before returning. Setting it toFalsewill skip this step. If not specified, thejoin_threadsattribute will be obeyed.Added in version 8.1.
Note
To add the bot to a channel after using this method, you should use the
channel_joined()method.To add a different user to a channel after using this method, you should use the
join()method.
- join( ) None¶
Send a
channelJOIN event fromuser.- Parameters:
user – factory for the user who joins the
channelchannel – channel the
userjoinedblocking – whether to block until all triggered threads have finished (optional)
This will send a
JOINmessage as ifuserjust joined the channel:factory.join(MockUser('NewUser'), '#test')
If
blockingisTrue, this method will wait to join all running triggers’ threads before returning. Setting it toFalsewill skip this step. If not specified, thejoin_threadsattribute will be obeyed.Changed in version 7.1: The
blockingparameter has been added.See also
This function is a shortcut to call the bot with the result from the user factory’s
join()method.
- join_threads: bool¶
Flag if the server should wait on running triggers.
The default
join_threadsbehavior is suitable for testing most common plugin callables, and ensures that all callables dispatched by thebotin response to messages sent via thisMockIRCServerare finished running before execution can continue.If set to
False, the mock server will not wait for the bot to finish processing threaded callables before returning.Added in version 7.1.
Note
You can override
join_threadson a per-method-call basis with theblockingarguments to the instance methods.
- message(raw: str, *, blocking: bool | None = None) None¶
Send a
rawmessage as if the bot received it.- Parameters:
raw – an IRC event from the server as seen by the bot
blocking – whether to block until all triggered threads have finished (optional)
This is a shortcut to calling Sopel’s
on_message()method and dealing with running triggers’ threads.It can be used with any messages (
PRIVMSG, numeric events, etc.) the bot would receive from a server in order to test the bot and its plugins’ behavior.If
blockingisTrue, this method will wait to join all running triggers’ threads before returning. Setting it toFalsewill skip this step. If not specified, thejoin_threadsattribute will be obeyed.Added in version 8.1.
- mode_set( ) None¶
Send a MODE event for a
channel- Parameters:
channel – channel receiving the MODE event
flags – MODE flags set
users – users getting the MODE flags
blocking – whether to block until all triggered threads have finished (optional)
This will send a MODE message as if
ChanServadded/removed channel modes for a set ofusers. This method assumes theflagsparameter follows the IRC specification for MODE:factory.mode_set('#test', '+vo-v', ['UserV', UserOP', 'UserAnon'])
If
blockingisTrue, this method will wait to join all running triggers’ threads before returning. Setting it toFalsewill skip this step. If not specified, thejoin_threadsattribute will be obeyed.Changed in version 7.1: The
blockingparameter has been added.
- pm( ) None¶
Send a
PRIVMSGto the bot by auser.- Parameters:
user – factory for the user object who sends a message
text – content of the message sent to the bot
blocking – whether to block until all triggered threads have finished (optional)
This will send a
PRIVMSGmessage as forwarded by the server for ausersending it to the bot:factory.pm(MockUser('NewUser'), 'A private word.')
If
blockingisTrue, this method will wait to join all running triggers’ threads before returning. Setting it toFalsewill skip this step. If not specified, thejoin_threadsattribute will be obeyed.Changed in version 7.1: The
blockingparameter has been added.See also
This function is a shortcut to call the bot with the result from the user factory’s
privmsg()method, using the bot’s nick as recipient.
- say( ) None¶
Send a
PRIVMSGtochannelbyuser.- Parameters:
user – factory for the user who sends a message to
channelchannel – recipient of the
user’sPRIVMSGtext – content of the message sent to the
channelblocking – whether to block until all triggered threads have finished (optional)
This will send a
PRIVMSGmessage as ifusersent it to thechannel, and the server forwarded it to its clients:factory.say(MockUser('NewUser'), '#test', '.shrug')
If
blockingisTrue, this method will wait to join all running triggers’ threads before returning. Setting it toFalsewill skip this step. If not specified, thejoin_threadsattribute will be obeyed.Changed in version 7.1: The
blockingparameter has been added.See also
This function is a shortcut to call the bot with the result from the user’s
privmsg()method.
- class sopel.tests.mocks.MockUser( )¶
Fake user that can generate messages to send to a bot.
The
UserFactoryfactory can be used to create such mock object, either directly or by usingpytestand theuserfactory()fixture.- join(channel: str) str¶
Generate a
JOINcommand forwarded by the server for the user.- Parameters:
channel – channel the user joined
- Returns:
the
JOINcommand the server sends to its clients present in the samechannelwhen the user joins it.