If you are into VOIP development and want to automate your sip call flows for testing, you might be interested in this project SIPr.
I have been involved in a project for a few months now which provides an advanced callcenter service leveraging the Broadworks Platform. Like any callcenter, the customer calls the CallCenter , Callcenter Queues the Call and Selects an agent and delivers the Call to the Agent. The agent is a registered user of Broadworks.
I have been looking for the right tool to automate the SIP Call Flows. After playing a while with sippr, I end up writing these test cases:
The CUSTOMER controller:
It justs sends the INVITE to a broadworks number which is the QUEUE. After the call gets received, it waits and sends BYE to terminate the call.
require 'sip_test_driver_controller'
class CustomerController < SIP::SipTestDriverController
transaction_usage :use_transactions=>false
start_on_load false
def initialize
logd('Controller created')
end
def on_provisional_res(session)
end
def start
session = create_udp_session(SipperConfigurator[:DefaultRIP], SipperConfigurator[:DefaultRP])
session.request_with('INVITE', 'sip:sajidqueue1@bwas.broadworkslab.com')
puts 'Sending INVITE Dest: ', 'sip:sajidqueue1@bwas.broadworkslab.com';
end
def on_invite(session)
puts 'customer got re-invite : '
session.respond_with(200)
session.schedule_timer_for("send 200!", 15000)
end
def on_timer(session , task)
puts 'sending bye'
session.request_with('BYE')
session.invalidate(true)
end
def on_success_res(session)
puts 'customer ---> on_success_res'
session.request_with('ACK')
end
end
Here is the Agent Controller:
It registers with Broadworks and waits for calls from the queue and receives it after 10 sec Ring and then waits for the BYE from the customer.
require 'sip_test_driver_controller'
class AgentController < SIP::SipTestDriverController
transaction_usage :use_transactions=>false
# change the directive below to true to start after loading.
start_on_load false
def specified_transport
[SipperConfigurator[:LocalSipperIP],SipperConfigurator[:LocalSipperPort][1]]
end
def initialize
logd('Controller created')
end
def on_invite(session)
if !session['invite']
puts 'Agent got call from Queue '
session.respond_with(100)
session.respond_with(180)
session['invite']=1
session.schedule_timer_for("send 200!", 5000)
else
puts 'agent got re-invite'
session.respond_with(200)
end
end
def on_timer(session , task)
puts 'Agent is going to accept the call from customer!', task
session.respond_with(200)
end
def on_bye(session)
puts 'Agent received BYE from Customer!'
session.respond_with(200)
session.invalidate(true)
session.flow_completed_for("CustomerAgentTest")
end
def on_provisional_res(session)
end
def start
contact = SipperConfigurator[:LocalSipperIP]+":"
r = Request.create_initial("REGISTER", "sip:" + "bwas.broadworkslab.com'",
:from=>"sip:2401120075@bwas.dhaka.vantage.com", :to=>"sip:2401120075@bwas.broadworkslab.com'",
:contact=>"sip:sajidagent1@"+ SipperConfigurator[:LocalSipperIP]+":"+SipperConfigurator[:LocalSipperPort][1].to_s(),
:expires=>"300",
:cseq=>"1 REGISTER",
:p_session_record=>"msg-info")
r.contact.q="0.9"
session = create_udp_session(SipperConfigurator[:DefaultRIP], SipperConfigurator[:DefaultRP])
#session.create_register_request('sip:bwas.dhaka.vantage.com', '<sip:sajidagent1@bwas.broadworkslab.com'>')
session.send(r)
#print "Sent a new REGISTER from "+name+"\n"
end
def on_success_res_for_register(s)
s.invalidate(true);
end
def on_success_res(session)
puts 'on_success_res->'
end
def on_ack(session)
end
def on_failure_res(session)
if session.iresponse.code == 401
r = session.create_request_with_response_to_challenge(session.iresponse.www_authenticate, false,"a", "b")
session.send r
session[:auth] = r.authorization
end
end
end
And Here is the Test Case that runs both controller and performs Validation/Assertion for the call flow.
$:.unshift File.join(ENV['SIPPER_HOME'],'sipper_test')
require 'driven_sip_test_case'
class CustomerAgentTest < DrivenSipTestCase
def setup
super
SipperConfigurator[:SessionRecord]='msg-info'
puts '------------------------------------'
end
def test_case1
start_named_controller_non_blocking("AgentController")
sleep 1
start_named_controller_non_blocking("CustomerController")
#it waits for Agent & Customer flow complete. The agent controller triggers the completion with session.flow_completed_for invocation.
wait_for_signaling()
self.expected_flow = ['< INVITE', '> 100', '> 180', '> 200', '< ACK ' , '< INVITE', '> 200', '< ACK', '< INVITE', '> 200', '< ACK' , '< BYE', '> 200']
verify_call_flow(:in,0)
self.expected_flow = ['> INVITE', '< 100 {0,}', '< 200', '> ACK', '< INVITE', '> 200', '< ACK', '< INVITE', '> 200', '< ACK', '> BYE' ]
verify_call_flow(:out, 1)
puts "done tests"
end
end
Ain’t this cool! Just a few lines of Code and you get a test case with Both UAC & UAS simulation!. I wish the Sipper Guys posted some more examples. We are planning to integrate this testcases with Watir & FunFX to automate the Full VOICE + WEB Mash up.
We are pleased to see the growing list of Sipper users and that Sipper is helping the VOIP community.
Sipper has been developed with Test Driven approach so every feature in Sipper has a corresponding test for it in sipper_test directory. It is a very good source for example test cases. You can find the sipper_test under “\ruby\lib\ruby\gems\1.8\gems\Sipper-2.0.0\sipper_test”