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.