Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Runs on Windows. Assumes you have QC installed. The code needs some love, but does work.
$:.unshift File.expand_path(File.dirname(__FILE__))
require 'win32ole'
require 'qc_automation'
require 'qc_test'
require 'fileutils'
module QCIntegration
class TestFolder
attr_accessor :kids
end
end
def file_name(test, base_path)
File.join(base_path, test.folder.path.gsub(/^\/Subject\//,""), "#{test.name}.ts")
end
def dump_test_to_file(test, base_path, folder_id)
# file_path = file_name(test, base_path)
folder_path = File.join(base_path, folder_id)
FileUtils.mkdir_p(folder_path)
File.open(File.join(folder_path, "#{test.name}.ts"), 'w+') do |f|
f << test.get_steps_content.join("\n")
end
end
def link_folder(folder, base_path)
return if folder.id == -1
FileUtils.mkdir_p(File.join(base_path, folder.id.to_s))
name = folder.desc
name = "root" if name.length == 0
#FileUtils.ln_s("#{base_path}\\#{folder.father_id}\\#{name}", "#{base_path}\\#{folder.id}")
puts `#{base_path}link.bat "#{base_path}#{folder.father_id}\\#{folder.desc}" "#{base_path}#{folder.id}"`
end
def link_folders(father, base_path)
return unless father.kids
father.kids.each{|kid|
link_folder(kid, base_path)
link_folders(kid, base_path)
}
end
exit if Object.const_defined?(:Ocra)
Settings = Struct.new(:url, :username,:password,:project)
settings = Settings.new("http://your.qc.address:8080/qcbin","user","password","project") #assumes DEFAULT
@qc = QCIntegration::QCAutomation.new(settings, $stdout)
@qc.open
@qc.folders.values.compact.each{|f|
if(f.father)
f.father.kids ||= []
f.father.kids << f
end
}
BASE_PATH = 'C:\\QC_BOND_Q_Tests\\'
link_folders(@qc.root_folder, BASE_PATH)
@qc.find_all_tests.each{ |id, name, father_id|
test = @qc.find_test_by_id(id)
begin
dump_test_to_file(test, BASE_PATH, father_id)
rescue => e
puts e.message
end
}
puts "done"
@qc.close
module QCIntegration
class TestFolder
attr_reader :id, :father_id,:desc
def initialize(id, father_id, desc, nodes)
#puts "New Folder: #{id}\t#{desc}"
@id, @father_id, @desc, @nodes = id, father_id, desc, nodes
end
def path
"#{father ? father.path : ""}#{desc}/"
end
def father
f = @nodes[father_id]
end
end
# begin
# qc = QCIntegration::QCAutomation.new(QcSetting.first, $stdout)
# qc.open
# t = qc.find_test_by_name('"Bond Advance TS Test Cases/Functional/Functional - Manage Protocols FR"', "Create Preparation Protocol Supervisor - example 0_0")
# # t.clear_steps
# # t.add_step("action", "object type", "object path", "data", "expected result")
# # qc.new_folder('something','subject\bond\case\add case')
# ensure
# qc.close
# end
#exporter = QCIntegration::QCExporter.new(QcSetting.first, $stdout)
class QCAutomation
def print_ole_methods(obj, output=nil)
output ||= @log
output.puts obj
if(!obj.is_a? String)
output.puts obj.ole_methods.collect{|m| "#{m}(#{m.params.join(', ')})"}.sort.uniq
end
end
def initialize(settings, log)
@settings = settings
@log = log
@folder_cache = {}
end
def open
#STDOUT.puts "opening QC connection to #{@settings.url} user:#{@settings.username}}"
STDOUT.flush
@tdc = WIN32OLE.new('TDApiOle80.TDConnection')
WIN32OLE.codepage = WIN32OLE::CP_UTF8
@tdc.InitConnectionEx(@settings.url)
@tdc.Login @settings.username, @settings.password
qcDomain = "DEFAULT"
qcProject = @settings.project
@tdc.Connect qcDomain, qcProject
@tdc
end
def find_or_add_test(path, test_name, test_type)
find_test_by_name(path, test_name) || add_test(path, test_name, test_type)
end
def add_test(path, test_name, test_type)
testF = get_test_factory(path)
test1 = testF.AddItem([test_name, test_type])
QCTest.new(test1, @tdc.ReqFactory, testF, @log, self)
end
def find_all_items
command = @tdc.command
command.CommandText = "select al_item_id, al_father_id, al_description from all_lists"
rec = command.Execute
list = []
until rec.EOR
list << [rec.FieldValue(0), rec.FieldValue(1), rec.FieldValue(2)]
rec.Next
end
list
end
def find_every_test
command = @tdc.command
command.CommandText = "select TS_TEST_ID, TS_NAME, TS_SUBJECT from TEST"
rec = command.Execute
list = []
until rec.EOR
list << [rec.FieldValue(0), rec.FieldValue(1), rec.FieldValue(2)]
rec.Next
end
list
end
def find_all_tests
command = @tdc.command
command.CommandText = "select TS_TEST_ID, TS_NAME, TS_SUBJECT from TEST WHERE TS_TYPE = 'VAPI-XP-TEST'"
rec = command.Execute
list = []
until rec.EOR
list << [rec.FieldValue(0), rec.FieldValue(1), rec.FieldValue(2)]
rec.Next
end
list
end
# Returns a hash of id(int) => TestFolder
def folders(refresh = false)
if @folders.nil? || refresh
@folders = Hash.new
find_all_items.each{|id, father_id, desc|
@folders[id.to_i] = TestFolder.new(id.to_i, father_id.to_i, desc, @folders)
}
end
@folders
end
def root_folder
folders.find{|k,v| v.father_id == -1 }[1]
end
def test_names(refresh = false)
if @tests.nil? || refresh
f = folders(refresh)
@tests = []
find_all_tests.each do |id, name, folder_id|
if f[folder_id.to_i]
@tests << "#{f[folder_id.to_i].path}#{name}"
else
@log.puts_error("Can't find folder #{folder_id}")
@tests << "Unattached/#{name}"
end
end
end
@tests
end
def find_test_by_name(path, name)
begin
@tdc.RefreshConnectionState
@log.puts_error "Lost Connection!!" if !@tdc.Connected
@log.puts_error "Logged out!!" if !@tdc.LoggedIn
testF = get_test_factory(path)
aFilter = testF.Filter
aFilter.setproperty("Filter","TS_NAME","\"#{name}\"")
#@log.puts "Filtering for '#{aFilter.Text}'"
testsList = testF.NewList(aFilter.Text)
testsList.Count > 0 ? QCTest.new(testsList.Item(1), @tdc.ReqFactory, testF, @log, self) : nil
rescue
@log.puts "ERROR: Failed to find test #{path}/#{name}"
nil
end
end
def find_test_by_id(id)
begin
@tdc.RefreshConnectionState
@log.puts_error "Lost Connection!!" if !@tdc.Connected
@log.puts_error "Logged out!!" if !@tdc.LoggedIn
testF = @tdc.TestFactory
aFilter = testF.Filter
aFilter.setproperty("Filter","TS_TEST_ID","#{id}")
testsList = testF.NewList(aFilter.Text)
testsList.Count > 0 ? QCTest.new(testsList.Item(1), @tdc.ReqFactory, testF, @log, self) : nil
rescue
@log.puts "ERROR: Failed to find test #{id}"
nil
end
end
def close
@tdc.Disconnect if @tdc.Connected
@tdc.Logout if @tdc.LoggedIn
@tdc.ReleaseConnection
end
def new_folder(folder_name, parent_folder)
treeM = @tdc.TreeManager
folder = treeM.NodeByPath(parent_folder)
item = folder.AddNode(folder_name)
item.Post
item
end
def download_automation_script
STDOUT.puts "download_automation_script"
objResourceFactory = @tdc.QCResourceFactory
objResourceFilter = objResourceFactory.Filter
objResourceFilter.setproperty("Filter","RSC_NAME","VapiScript")
objResourceList = objResourceFactory.NewList(objResourceFilter.Text)
objVapiScriptResource = objResourceList.item(1)
objVapiScriptResource.DownloadResource(QCTest.client_path, true)
objResourceFactory = nil
objResourceFilter = nil
objResourceList = nil
objVapiScriptResource = nil
end
def get_or_add_folder(path)
puts "Find or add : #{path}"
p = path.split(/[\/\\]/)
treeM = @tdc.TreeManager
folder = treeM.NodeByPath('subject')
p.each {|item| folder = (find_folder(item, folder) || add_folder(item,folder)) }
folder
end
private
def get_test_factory(path)
@folder_cache[path] ||= get_test_factory2(path)
@folder_cache[path]
end
def get_test_factory2(path)
folder = get_or_add_folder(path)
testF = folder.testFactory
end
def add_folder(folder_name, parent_folder)
@log.puts("add folder '#{folder_name}' - '#{parent_folder.inspect}'")
item = parent_folder.AddNode(folder_name)
item.Post
item
end
def find_folder(item, folder)
@log.puts("find folder '#{item}' - '#{folder.inspect}'")
begin
folder.FindChildNode(item)
rescue Exception
nil
end
end
end
end
module QCIntegration
class QCTest
def save
@test.Post if(@dirty)
end
def print_ole_methods(obj)
puts obj
if(!obj.is_a? String)
puts obj.ole_methods.collect{|m| "#{m}(#{m.params.join(', ')})"}.sort
end
end
def initialize(test, req_factory, test_factory, log, qc)
@qc = qc
@test = test
@req_factory = req_factory
@test_factory = test_factory
@log = log
@version_control = @test.VCS
@step_fieldmap = {}
@ds_factory = @test.DesignStepFactory
@ds_factory.Fields.each { |f| @step_fieldmap[f.Property().UserLabel()] = f.Name }
@test_fieldmap = {}
@test_factory.Fields.each { |f| @test_fieldmap[f.Property().UserLabel()] = f.Name }
@dirty = false
end
def check_out
if (!@checked_out && @version_control && !@version_control.IsCheckedOut)
@log.puts "checking out test"
begin
@version_control.CheckOut(-1, "checked out by automation", false)
@checked_out = @version_control.IsCheckedOut
rescue => e
puts e.inspect
@checked_out = true
end
end
@checked_out
end
def check_in(message)
save()
if (@checked_out && @version_control)
@log.puts "check in"
@version_control.CheckIn(nil, message, nil, nil)
@checked_out = false
end
end
def force_check_in(message)
save()
@log.puts "forced check in of test"
if (@version_control && @version_control.IsCheckedOut)
@version_control.CheckIn(nil, message, nil, nil)
@checked_out = false
end
end
def add_step(content)
content = {"Description" => content } unless( content.is_a? Hash)
@log.puts "add step"
begin
# @test.LockObject if !@test.IsLocked
check_out
step_num = @test.DesStepsNum
#Create the new design step
desStep = @ds_factory.AddItem(0)
desStep.setproperty("Field", @step_fieldmap["Step Name"] , "Step #{step_num}") if @step_fieldmap["Step Name"]
content.each{|k,v|
desStep.setproperty("Field", @step_fieldmap[k] , v) if @step_fieldmap[k]
}
# desStep.setproperty("Field", @step_fieldmap["Description"] , content) if @step_fieldmap["Description"]
# desStep.setproperty("Field", @step_fieldmap["Action"] ,action).to_s if @step_fieldmap["Action"]
# desStep.setproperty("Field", @step_fieldmap["Object Type"], object_type.to_s) if @step_fieldmap["Object Type"]
# desStep.setproperty("Field", @step_fieldmap["Object Path"], object_path.to_s) if @step_fieldmap["Object Path"]
# desStep.setproperty("Field", @step_fieldmap["Data"],data.to_s) if @step_fieldmap["Data"]
# desStep.setproperty("Field", @step_fieldmap["Expected Result"],expected_result.to_s) if @step_fieldmap["Expected Result"]
desStep.Post
ensure
check_in("Added steps")
end
end
def get_steps_content(fields = ["Description"])
content = []
list = @ds_factory.NewList("")
list.each {|step|
s = fields.map{|f|step.Field(@step_fieldmap[f])}
s = s[0] if s.length == 1
content << s
}
content
end
#######################################################################
# Generate a bunch of fields.
%w(status type description owner:TS_RESPONSIBLE subject).each do |meth|
accessor, field_name = meth.split(":")
field_name ||= "TS_#{meth.upcase}"
define_method(accessor+"=") { |value|
@test.setproperty("Field", field_name , value)
@dirty = true
}
define_method(accessor) {
@test.Field(field_name)
}
end
#######################################################################
def approver=(approver)
@test.setproperty("Field", @test_fieldmap["Approved by"] , approver)
@dirty = true
# @test.Post
end
def approver
@test.Field(@test_fieldmap["Approved by"])
end
def manualid=(manualid)
@test.setproperty("Field", @test_fieldmap["Automated Tests"] , manualid)
@dirty = true
# @test.Post
end
def manualid
@test.Field(@test_fieldmap["Automated Tests"])
end
def clear_steps
@log.puts "clear steps"
begin
check_out
list = @ds_factory.NewList("")
list.each {|step|
begin
@ds_factory.RemoveItem(step.ID)
rescue e
@log.puts "************can't delete step #{step.ID}"
end
}
ensure
check_in("Cleared steps")
end
end
def link_to_requirements(new_requirements)
@log.puts "link to requirements"
coverage_ids = requirements
(new_requirements - coverage_ids).each{|req| link_to_requirement(req)}
(coverage_ids - new_requirements).each{|req| unlink_requirement(req)}
end
def requirements
l = @test.GetCoverList()
(1..l.Count).map{|i| l.Item(i).ID} # to_a doesn't work
end
def link_to_requirement(requirement_id)
@log.puts "link to requirement"
begin
aReq = @req_factory.Item(requirement_id)
aReq.AddTestToCoverage @test.ID
aReq = nil
rescue => e
@log.puts "Error: failed to link requirement ##{requirement_id} to test #{@test.Name}"
@log.puts e.message
@log.puts e.backtrace
aReq = nil
end
end
def unlink_requirement(requirement_id)
@log.puts "unlink requirement"
begin
aReq = @req_factory.Item(requirement_id)
aReq.RemoveCoverage @test.ID
aReq = nil
rescue => e
@log.puts "Error: failed to unlink requirement ##{requirement_id} from test #{@test.Name}"
@log.puts e.message
@log.puts e.backtrace
aReq = nil
end
end
def unlink_all_requirements()
requirements.each{|req| unlink_requirement(req)}
end
def ID
@test.ID
end
def folder
#Note: Subject is already a Folder object as far as I can see, we should just wrap it.
@qc.folders[subject.NodeID.to_i]
end
def attach_template_files()
attach_template_files_in_folder(QCTest.client_path)
end
def attach_template_files_in_folder(folder)
@log.puts "storing files from #{folder}"
estore = @test.ExtendedStorage
estore.ClientPath = folder
estore.Save("*.*", true)
@dirty = true
# @test.Post
end
def name
@test.Name
end
def move(new_folder_id)
subject = new_folder_id
end
def self.client_path()
File.join(File.dirname(File.expand_path(__FILE__)),"template_files").gsub('/','\\')
end
# def method_missing(argc, *argv, &block)
# @log.puts "unknown method: #{argc}"
# @test.send(argc, *argv, &block)
# end
end
end
@ghost

This comment has been minimized.

Copy link

ghost commented Apr 17, 2018

How to update result of test execution in QC for ruby selenium script ?
Please help .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.