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”