We’re cluttering up our database something fierce, and at some point we’re bound to hit a limit on the server.
We need to clean up after ourselves, which means the test code has to hit the database. So we add an After hook
to the Cucumber code.
After('@db_cleanup')do|scenario|connect_hash={username:ENV['DB_USERNAME'],password:ENV['DB_PASSWORD'],dataserver:ENV['DB_DATASERVER'],database:ENV['DB_NAME']}puts"After hook connecting to #{ENV['DB_DATASERVER']} database #{ENV['DB_NAME']}..."client=TinyTds::Client.new(connect_hash)puts" Connected."ifclient.active?result=client.execute("DELETE
FROM [#{ENV['DB_NAME']}].[dbo].[Account]
WHERE account LIKE 'test%'
AND email LIKE '%301days.com'")puts"Rows deleted from [Account]: #{result.do}"result=client.execute("SELECT playerID, account, name
FROM [#{ENV['DB_NAME']}].[dbo].[Player]
WHERE account LIKE 'test%'
AND name LIKE 'Dude.%'")players_to_delete=[]result.each(:symbolize_keys=>true)do|rowset|players_to_delete<<rowset[:playerID]endputs"Players to delete: #{players_to_delete}"player_tables=["PlayerBelt","PlayerEffects","PlayerFlags","PlayerHeld","PlayerLocker","PlayerQuests","PlayerRings","PlayerSack","PlayerSettings","PlayerSkills","PlayerSpells","PlayerWearing","Player"]players_to_delete.eachdo|player_to_delete|puts"Deleting player #{player_to_delete}"player_tables.eachdo|table|result=client.execute("DELETE
FROM [#{ENV['DB_NAME']}].[dbo].[#{table}]
WHERE playerID = '#{player_to_delete}'")puts"Rows deleted from [#{table}]: #{result.do}"endendend
As long as we have all of the appropriate environment variables set, and the @db_cleanup tag on the test, all of the test accounts/characters will get cleaned
up after the test runs.
After hook connecting to AQUALUNG\SQLEXPRESS database DSpineBackup...
Connected.
Rows deleted from [Account]: 1
Players to delete: [3005]
Deleting player 3005
Rows deleted from [PlayerBelt]: 8
Rows deleted from [PlayerEffects]: 20
Rows deleted from [PlayerFlags]: 1
Rows deleted from [PlayerHeld]: 2
Rows deleted from [PlayerLocker]: 20
Rows deleted from [PlayerQuests]: 0
Rows deleted from [PlayerRings]: 8
Rows deleted from [PlayerSack]: 21
Rows deleted from [PlayerSettings]: 1
Rows deleted from [PlayerSkills]: 1
Rows deleted from [PlayerSpells]: 35
Rows deleted from [PlayerWearing]: 20
Rows deleted from [Player]: 1
d:\>sqlcmd -S AQUALUNG\SQLEXPRESS -U sa -d DSpineBackup -Q "SELECT
account FROM [DSpineBackup].[dbo].[Account] WHERE account LIKE 'test%' AND email
LIKE '%301days.com'"
account
--------------------
(0 rows affected)
Of course our test code just got tightly coupled to the server database schema, which is generally a bad thing.
A better solution is to just restore the database to the pre-test state (optionally saving the state post-test for
debugging), although that can be either slow (for non-trivial db) or a problem (if the server can’t tolerate it).
deftelnet_commands(connection,commands)commands.eachdo|command|output=telnet_command(connection,command[0],command[1])endoutputenddeftelnet_command(connection,string,match,overrides={})puts"Sending #{string} and waiting for #{match}..."connection.cmd({"String"=>string,"Match"=>match}.merge(overrides)){|c|putsansi_strip(c)unlessc.nil?}enddefansi_strip(string)parsed=string.gsub(/\e\[[^a-zA-Z]*[a-zA-Z]/,"")# puts "I made #{string} into #{parsed}!"end
When(/^I log in with the wrong then right password$/)do@connection=create_telnet_connectiontelnet_command(@connection,"",/Login\: /,{"Timeout"=>120})output=telnet_commands(@connection,[[@user[:acct_name],/Password\: /],["oops",/:/]])expect(output).toinclude("Invalid password.")telnet_commands(@connection,[[@user[:acct_name],/Password\: /],[@user[:acct_password],/Command\: /]])end
and I get this:
Sending oops and waiting for /:/...
Invalid password.
login:
expected output to some stream to include "Invalid password.", but it does not respond to `include?`
Diff:
@@ -1,2 +1,2 @@
-["Invalid password."]
+(output to some stream)
(RSpec::Expectations::ExpectationNotMetError)
./features/steps/login_steps.rb:70:in `/^I log in with the wrong then right password$/'
features/login.feature:25:in `And I log in with the wrong then right password'
What the heck is “output to some stream”? Maybe what’s coming back from Net::Telnet#cmd isn’t quite what I expected. I’ll add a .to_s to the return from telnet_commands to sort that out, and:
expected "#<RSpec::Matchers::BuiltIn::Output:0x3114558>" to include "Invalid password." (RSpec::Expectations::ExpectationNotMetError)
./features/steps/login_steps.rb:70:in `/^I log in with the wrong then right password$/'
Just to be clear, that “too sick to go to work but not too sick to make games” thing really never happens.
I’m a software engineer with a decent internet connection; if I can do gamedev I can do my job. So it waits
until after hours, sick or no.