How to use caller method of Assertions Package

Best Minitest_ruby code snippet using Assertions.caller

reasonerJobHelper.rb

Source:reasonerJobHelper.rb Github

copy

Full Screen

1require 'brl/genboree/tools/workbenchJobHelper'2require 'brl/genboree/rest/helpers/kbApiUriHelper'3require 'brl/genboree/kb/propSelector'4require 'brl/genboree/kb/helpers/modelsHelper'5require 'brl/genboree/kb/transformers/transformedDocHelper'6module BRL; module Genboree; module Tools7 class ReasonerJobHelper < WorkbenchJobHelper8 TOOL_ID = "reasoner"9 TRANSFORM_PARAM = "transform"10 FORMAT_PARAM = "format"11 FORMAT_VALUE = "json"12 13 R_MODULE_NAME = "R"14 R_VERSION = "3.1"15 MODULE_NAME = "Reasoner"16 MODULE_VERSION = "1.0"17 CONCLUDER_NAME = "Reasoner"18 CMD_NAME = "Reasoner.R"19 # Extract information from stdout/stderr20 # @todo this is unique to reasoner121 # Providing this information as a set of variables that should be easily modified if the 22 # script changes its output style; pattern must have $1 match group as the information23 # to be retrieved and used by the wrapper24 # Assertions are presented e.g.25 # Assertion => LikelyPathogenic , Pathogenic , LikelyPathogenic , Benign , LikelyBenign26 # ReasonForAssertion => Pathogenic.Moderate >=3 , Pathogenic.Strong >=2 , Pathogenic.Moderate 27 # >=1 & Pathogenic.Supporting >=4 , Benign.Strong >=2 , Benign.Supporting >=228 # Warning messages are presented e.g.29 # "Warning Name => Guidelines Parse Warning."30 # "Warning Message => The last column is not named Inference"31 # Error messages are presented e.g.32 # "Error: Error Name => Evidence Parse Error."33 # "Error Message => One or More of evidence tags that you supplied are not known to provided Guidelines! They are listed here: \"Pathogenic.Very Not Strong\"."34 ASSERTION_DELIM = REASON_DELIM = WARNING_DELIM = ERROR_DELIM = "\\s*=>\\s*"35 ASSERTION_ITEM_DELIM = ","36 ASSERTION_PREFIX = "Assertion"37 ASSERTION_PATTERN = %r{#{ASSERTION_PREFIX}#{ASSERTION_DELIM}(.*)$}38 REASON_ITEM_DELIM = ","39 REASON_PREFIX = "ReasonForAssertion"40 REASON_PATTERN = %r{#{REASON_PREFIX}#{REASON_DELIM}(.*)$}41 WARNING_NAME_PREFIX = "Warning Name"42 WARNING_MESSAGE_PREFIX = "Warning Message"43 WARNING_NAME_PATTERN = %r{#{WARNING_NAME_PREFIX}#{WARNING_DELIM}(.*)$}44 WARNING_MESSAGE_PATTERN = %r{#{WARNING_MESSAGE_PREFIX}#{WARNING_DELIM}(.*)$}45 ERROR_NAME_PREFIX = "Error Name"46 ERROR_MESSAGE_PREFIX = "Error Message"47 ERROR_NAME_PATTERN = %r{#{ERROR_NAME_PREFIX}#{ERROR_DELIM}(.*)$}48 ERROR_MESSAGE_PATTERN = %r{#{ERROR_MESSAGE_PREFIX}#{ERROR_DELIM}(.*)$}49 def initialize(toolIdStr, genbConf=nil, dbu=nil, *args)50 super(toolIdStr, genbConf, dbu, args)51 @kbApiUriHelper = BRL::Genboree::REST::Helpers::KbApiUriHelper.new(dbu, genbConf)52 cmds = [53 "module load #{MODULE_NAME}/#{self.class::MODULE_VERSION}",54 "unset R_HOME"55 ]56 @reasonerCmdPrefix = "#{cmds.join(" ; ")} ; #{CMD_NAME}"57 @adminMsg = "Please contact the administator at #{@genbConf.send(:gbAdminEmail)}." rescue nil58 end59 # Override parent runInProcess() so that we can run on the web server60 # @return [Boolean] whether or not job succeeded61 # @set @workbenchJobObj.results with a Conclusion document62 # @set @workbenchJobObj.context['wbErrorMsg'] if error occurs63 # @todo @workbenchJobObj.settings['updateDoc']64 # @todo would like to put @apiCaller setup in initialize but user authentication hasnt happened at that stage:65 # it happens with executionCallback is called from the toolJob resource, which in turn executes this function66 def runInProcess()67 success = false68 @apiCaller = BRL::Genboree::REST::WrapperApiCaller.new("", "", @userId) 69 begin70 # fill in conclusion doc as we go71 # @todo conclusionDoc only needed for reasoner172 conclusionDoc = getConclusionTemplate() # @todo use generic doc template from model73 conclusionDoc.setPropVal("Conclusion.Concluder", CONCLUDER_NAME)74 rulesDocUrl = @workbenchJobObj.settings["rulesDoc"]75 conclusionDoc.setPropVal("Conclusion.Guidelines", rulesDocUrl)76 rulesDoc = getRulesDoc(rulesDocUrl, @apiCaller)77 # construct transformation URL based on inputs78 # use first input of each type (if there are multiple inputs of the same type)79 type2Input = classifyInputs(@workbenchJobObj.inputs)80 81 # kbDoc is available, get the latest version for timestamp82 # @todo perhaps once GET on kbDocProp is finished we can get JUST the timestamp83 timeObj = getInputDocTimestamp(type2Input[:kbDoc], @apiCaller)84 conclusionDoc.setPropVal("Conclusion.TimeStampOfDocument", timeObj)85 86 # then no errors, apply kb transform to kb doc 87 transformDoc = transformDocument(type2Input[:kbDoc], type2Input[:kbTransform], @apiCaller)88 89 # with the transform and rules docs, extract the data necessary for Reasoner90 # build guildlines tsv string91 # @todo reasoner2 needs evidence and meta from guidelines92 guidelines = parseGuidelines(rulesDoc)93 guidelinesTsv = self.class.hashToCsv(guidelines, "\t")94 95 evidence = parseEvidence(guidelines, transformDoc)96 evidenceCsv = formatEvidence(evidence)97 98 # run Reasoner99 # @todo what if module load part fails? pray100 guidelinesTsv.gsub!("\t", "\\t")101 guidelinesTsv.gsub!("\n", "\\n")102 cmd = @reasonerCmdPrefix + " \"#{guidelinesTsv}\" " + " \"#{evidenceCsv}\" "103 cmdStatus, stdout, stderr = BRL::Util::popen4Wrapper(cmd)104 assertions = warningName = warningMsg = errorName = errorMsg = nil105 if(cmdStatus.exitstatus == 0)106 success = true107 # check for warnings108 # @todo reasoner2 has no warnings or assertions to parse109 warningName, warningMsg = checkWarning(stderr)110 assertions = parseAssertions(stdout)111 if(assertions.empty?)112 # success and no assertions is a bug113 raise ReasonerJobError.new("Could not parse assertions from #{CMD_NAME}. #{@adminMsg}", :"Internal Server Error")114 end115 conclusionAssertions = []116 assertions.each_index { |ii|117 assertionDoc = BRL::Genboree::KB::KbDoc.new()118 assertionDoc.setPropVal("Assertion", "Assertion-#{ii}")119 assertionDoc.setPropProperties("Assertion", assertions[ii])120 conclusionAssertions.push(assertionDoc)121 }122 conclusionDoc.setPropItems("Conclusion.Assertions", conclusionAssertions)123 else124 success = false125 # check for warning, error126 warningName, warningMsg = checkWarning(stderr)127 errorName, errorMsg = checkError(stderr)128 end129 # fill in Conclusion document with cmd information130 status = name = message = nil131 if(!errorName.nil? or !errorMsg.nil?)132 status = "error"133 name = errorName134 message = errorMsg135 elsif(!warningName.nil? or !warningMsg.nil?)136 status = "warning"137 name = warningName138 message = warningMsg139 else140 status = "ok"141 name = "ok"142 message = "ok"143 end144 conclusionDoc.setPropVal("Conclusion.Status", status)145 conclusionDoc.setPropVal("Conclusion.Status.Name", name)146 conclusionDoc.setPropVal("Conclusion.Status.Message", message)147 # finally, the timestamp when we are done148 conclusionDoc.setPropVal("Conclusion.TimeStampOfConclusion", Time.now.to_s)149 @workbenchJobObj.results = conclusionDoc150 # @todo re upload document on success151 rescue => err152 logAndPrepareError(err)153 success = false154 end155 156 return success157 end158 # @note if @rackEnv is set @genbConf must be set159 def getRulesDoc(rulesDocUrl, apiCaller=@apiCaller)160 # retrieve rules doc, validated by rulesHelper161 uriObj = URI.parse(rulesDocUrl)162 apiCaller.setHost(uriObj.host)163 apiCaller.setRsrcPath("#{uriObj.path}?#{uriObj.query}")164 apiCaller.initInternalRequest(@rackEnv, @genbConf.machineNameAlias) if(@rackEnv)165 resp = apiCaller.get()166 unless(apiCaller.succeeded?)167 parsedBody = apiCaller.parseRespBody() rescue nil168 msg = parsedBody.respond_to?(:getNestedAttr) ? parsedBody.getNestedAttr("status.msg") : nil169 code = parsedBody.respond_to?(:getNestedAttr) ? parsedBody.getNestedAttr("status.statusCode") : nil170 code = (code.nil? ? :"Internal Server Error" : code.to_sym)171 raise ReasonerJobError.new("Unable to retrieve rulesDoc #{rulesDocUrl.inspect} ; Status message: #{msg.inspect}", code)172 end173 rulesDoc = apiCaller.parseRespBody()['data']174 return rulesDoc175 end176 # @note @kbApiUriHelper must be set177 def classifyInputs(inputs)178 type2Input = {}179 inputs.each{ |input|180 type = @kbApiUriHelper.classifyUri(input)181 if(!type.nil? and !type2Input.key?(type))182 type2Input[type] = input183 end184 }185 unless(type2Input[:kbDoc] and type2Input[:kbTransform])186 # this is redundant with workbench.rules.json and reasonerRulesHelper187 missingType = (type2Input.key?(:kbDoc) ? :kbDoc : :kbTransform)188 raise ReasonerJobError.new("Missing an input of type #{missingType}; this tool requires a kbDoc and a kbTransform", :"Bad Request")189 end190 return type2Input191 end192 # @todo perhaps once GET on kbDocProp is finished we can get JUST the timestamp193 def getInputDocTimestamp(kbDocUrl, apiCaller=@apiCaller)194 uriObj = URI.parse(kbDocUrl)195 kbDocVersionPath = "#{uriObj.path.chomp("/")}/ver/HEAD"196 apiCaller.setHost(uriObj.host)197 apiCaller.setRsrcPath(kbDocVersionPath)198 apiCaller.initInternalRequest(@rackEnv, @genbConf.machineNameAlias) if(@rackEnv)199 resp = apiCaller.get()200 unless(apiCaller.succeeded?)201 parsedBody = apiCaller.parseRespBody() rescue nil202 msg = parsedBody.respond_to?(:getNestedAttr) ? parsedBody.getNestedAttr("status.msg") : nil203 code = parsedBody.respond_to?(:getNestedAttr) ? parsedBody.getNestedAttr("status.statusCode") : nil204 code = (code.nil? ? :"Internal Server Error" : code.to_sym)205 raise ReasonerJobError.new("Could not retrieve head version of #{kbDocUrl} for its timestamp ; Status message: #{msg.inspect}", code)206 end207 respBody = apiCaller.parseRespBody()['data']208 timestamp = respBody['versionNum']['properties']['timestamp']['value']209 timeObj = Time.rfc2822(timestamp) rescue nil210 if(timeObj.nil?)211 $stderr.debugPuts(__FILE__, __method__, "ERROR", "Timestamp from version document not parsable according to rfc2822: #{timestamp.inspect}")212 raise ReasonerJobError.new("Could not retrieve valid timestamp from version document #{apiCaller.fillApiUriTemplate.inspect}", :"Internal Server Error")213 end214 return timeObj215 end216 # Transform a KB document through the HTTP API217 # @param [String] kbDocUrl the document to transform218 # @param [String] transformDocUrl URL to document describing to transform it219 # @param [BRL::Genboree::REST::ApiCaller] apiCaller the object used to make the HTTP request220 # @return [Hash] the transformed document221 def transformDocument(kbDocUrl, transformDocUrl, apiCaller=@apiCaller)222 escapedTransform = CGI.escape(transformDocUrl)223 uriObj = URI.parse(kbDocUrl)224 url = "#{uriObj.scheme}://#{uriObj.host}#{uriObj.path}?#{TRANSFORM_PARAM}=#{escapedTransform}&#{FORMAT_PARAM}=#{FORMAT_VALUE}"225 uriObj = URI.parse(url)226 apiCaller.setHost(uriObj.host)227 apiCaller.setRsrcPath("#{uriObj.path}?#{uriObj.query}")228 apiCaller.initInternalRequest(@rackEnv, @genbConf.machineNameAlias) if(@rackEnv)229 resp = apiCaller.get()230 unless(apiCaller.succeeded?)231 parsedBody = apiCaller.parseRespBody() rescue nil232 msg = parsedBody.respond_to?(:getNestedAttr) ? parsedBody.getNestedAttr("status.msg") : nil233 code = parsedBody.respond_to?(:getNestedAttr) ? parsedBody.getNestedAttr("status.statusCode") : nil234 code = (code.nil? ? :"Internal Server Error" : code.to_sym)235 raise ReasonerJobError.new("Could not retrieve transformation via #{url.inspect} ; Status message: #{msg.inspect}", code)236 end237 transformDoc = apiCaller.parseRespBody()['data'] # the actual response is wrapped238 return transformDoc239 end240 # Represent evidence as comma-separated A=V pairs for strictly positive evidences241 # @param [Hash] evidence @see parseEvidence with at least one strictly positive value242 # @return [String] formatted evidence for use by the Reasoner243 def formatEvidence(evidence)244 evidenceCopy = evidence.deep_clone()245 evidenceCopy = evidenceCopy.delete_if { |kk, vv| vv <= 0 }246 if(evidenceCopy.empty?)247 # should have already errored in parse stage248 raise ReasonerJobError.new("Could not format evidence #{evidence.inspect} for #{CMD_NAME} because no evidence value is strictly positive", :"Internal Server Error")249 end250 evidenceArray = evidenceCopy.collect { |kk, vv| "#{kk}=#{vv}" }251 return evidenceArray.join(",")252 end253 # @param [Hash] guidelines @see parseGuidelines254 # @param [Hash] transformDoc the results of applying the transform to the data document255 # @return [Hash] association of PartitionPath paths with some metric applied by the256 # transform (sum, count, etc.)257 def parseEvidence(guidelines, transformDoc, aggregationRule=nil)258 partitionPaths = guidelines[:header].deep_clone()259 partitionPaths.delete("Guidelines")260 partitionPaths.delete("Inference")261 if(partitionPaths.empty?)262 raise ReasonerJobError.new("No partition paths to count evidence for! Verify the guidelines document.", :"Bad Request")263 end264 pathToCount = {}265 partitionPaths.each{ |partitionPath|266 count = BRL::Genboree::KB::Transformers::TransformedDocHelper.getCountForPath(transformDoc, partitionPath, :op => "sum") # override count to sum267 if(count == :no_path)268 count = 0269 pathToCount[partitionPath] = count270 elsif(count == :no_count)271 raise ReasonerJobError.new("Could not determine the evidence belonging to #{partitionPath.inspect}. #{@adminMsg}", :"Internal Server Error")272 else273 pathToCount[partitionPath] = count274 end275 }276 anyEvidence = false277 pathToCount.each_key { |kk| 278 vv = pathToCount[kk]279 anyEvidence = (anyEvidence || (vv > 0)) 280 }281 unless(anyEvidence)282 raise ReasonerJobError.new("Could not parse any evidence from the transformation document with the given guidelines. Please verify that the transformation document and the resulting transformed data document match your guidelines.", :"Bad Request")283 end284 return pathToCount285 end286 # The Reasoner's first argument is a tsv file as a string describing conditions on properties287 # required to make an assertion, construct this file from the rulesDoc288 # @note rulesDoc refers to a single KB document with ALL the rules for the Reasoner289 # ruleDocs refer to individual sub documents rooted at a particular rule of the rulesDoc290 # @todo "Guidelines" "Inference", other strings291 # @todo how does the property selector communicate errors? handle those292 # @param [Hash] rulesDoc a previously validated rules document (@see getRulesModel())293 # @return [Hash] with keys294 # [Array<String>] :header fields that can be used in order for a TSV file295 # [Hash<String, Hash>>] :data association of a guideline to the relevant data for the Reasoner:296 # a sub-hash mapping a partitionPath to a condition and an associated inference if297 # the combined condition is met298 def parseGuidelines(rulesDoc)299 guidelines = { :header => [], :data => {} }300 # documents are assumed to have a single root301 docId = rulesDoc.keys.first302 # extract header data for tsv file303 header = {}304 rulesPropSelector = BRL::Genboree::KB::PropSelector.new(rulesDoc)305 path = "<>.Rules.[].Rule.Conditions.[].Condition.PartitionPath"306 partitionPaths = nil307 begin308 partitionPaths = rulesPropSelector.getMultiPropValues(path)309 rescue RuntimeError, ArgumentError => err310 # document is assumed to be valid, error of this type is a bug311 raise ReasonerJobError.new("Could not retrieve conditions from the rules document. #{@adminMsg}")312 end313 partitionPaths.each{ |partitionPath|314 header[partitionPath] = nil315 }316 header["Guidelines"] = nil317 header["Inference"] = nil318 # order is not required except for inference last but this is a nice layout319 columnOrder = ["Guidelines"]320 keys = header.keys321 keys.delete("Guidelines")322 keys.delete("Inference")323 keys.sort!()324 columnOrder += keys325 columnOrder.push("Inference")326 guidelines[:header] = columnOrder327 # extract row data for tsv file328 path = "<>.Rules.[].Rule"329 ruleDocs = nil330 begin331 ruleDocs = rulesPropSelector.getMultiObj(path)332 rescue ArgumentError, RuntimeError => err333 raise ReasonerJobError.new("Could not retrieve rules from the rules document. #{@adminMsg}")334 end335 partitionPathSubPath = "Rule.Conditions.[].Condition.PartitionPath"336 conditionSubPath = "Rule.Conditions.[].Condition.Condition"337 # @todo aggregation is provided in the model but should be handled already by338 # the transformation document and finished already once we obtain the transformed339 # result; why is it in this model? it belongs in the transform instead. is this an override?340 aggregationSubPath = "Rule.Conditions.[].Condition.AggregationOperation"341 inferenceSubPath = "Rule.Inference"342 ruleDocs.each_index { |ii|343 ruleDoc = ruleDocs[ii]344 ruleValue = ruleDoc["Rule"]["value"]345 datum = header.deep_clone()346 datum["Guidelines"] = ruleValue347 rulePropSelector = BRL::Genboree::KB::PropSelector.new(ruleDoc)348 # retrieve parallel arrays349 columns = values = nil350 begin351 columns = rulePropSelector.getMultiPropValues(partitionPathSubPath)352 values = rulePropSelector.getMultiPropValues(conditionSubPath)353 rescue ArgumentError, RuntimeError => err354 raise ReasonerJobError.new("Could not retrieve condition values from the rules document. #{@adminMsg}")355 end356 unless(columns.size == values.size)357 raise ReasonerJobError.new("Could not associate partition path with a condition. #{@adminMsg}")358 end359 columns.each_index { |ii| datum[columns[ii]] = values[ii] }360 datum["Inference"] = rulePropSelector.getMultiPropValues(inferenceSubPath).first361 guidelines[:data][datum["Guidelines"]] = datum362 }363 # @note we assume that since the partitionPathSubPath and path for the header specify the364 # same elements so that our tsv with at least one row will be a valid one for the Reasoner365 if(guidelines[:data].empty?)366 raise ReasonerJobError.new("Could not retrieve any rules from the rules document. Please verify that rules are present", :"Bad Request")367 end368 return guidelines369 end370 # Parse stdout for assertions371 # @param [String] stdout the stdout from the Reasoner, a pair of padded csv strings,372 # @see ASSERTION_DELIM373 # @return [Array<Hash>] list of assertion objects374 def parseAssertions(stdout)375 retVal = []376 assertions = reasons = nil377 matchData = REASON_PATTERN.match(stdout)378 unless(matchData.nil?)379 reasons = matchData[1].split(",")380 reasons.map!{|xx| xx.strip()}381 end382 matchData = ASSERTION_PATTERN.match(stdout)383 unless(matchData.nil?)384 assertions = matchData[1].split(",")385 assertions.map!{|xx| xx.strip()}386 end387 if(assertions.size == reasons.size)388 assertions.each_index { |ii|389 assertion = assertions[ii]390 reason = reasons[ii]391 retVal.push( { "Assertion" => { "value" => assertion }, 392 "ReasonForAssertion" => { "value" => reason } } )393 }394 else395 raise ReasonerJobError.new("Could not associate assertions with reasons for those assertions. #{@adminMsg}")396 end397 return retVal398 end399 # Parse stderr for warning messages400 # @param [String] stderr the stderr from the Reasoner401 # @return [Array<String>] 2-tuple warning name, warning message402 def checkWarning(stderr)403 retVal = [nil, nil]404 warningName, warningMsg = nil405 matchData = WARNING_NAME_PATTERN.match(stderr)406 warningName = matchData[1] unless(matchData.nil?)407 matchData = WARNING_MESSAGE_PATTERN.match(stderr)408 warningMsg = matchData[1] unless(matchData.nil?)409 retVal = [warningName, warningMsg]410 return retVal411 end412 # Parse stderr for error messages413 # @param [String] stderr the stderr from the Reasoner414 # @return [Array<String>] 2-tuple error name, error message415 def checkError(stderr)416 retVal = [nil, nil]417 errorName, errorMsg = nil418 matchData = ERROR_NAME_PATTERN.match(stderr)419 errorName = matchData[1] unless(matchData.nil?)420 matchData = ERROR_MESSAGE_PATTERN.match(stderr)421 errorMsg = matchData[1] unless(matchData.nil?)422 retVal = [errorName, errorMsg]423 return retVal424 end425 # Return a conditions path that can be used for selecting conditions426 # from the rulesDoc427 # @param [String] docId the document id as provided by the workbench job inputs428 # @todo can prop selector path use {} or <> at root level property? if so, dont 429 # need this function and can just use "<>" in place of docId430 def getRulePath(docId)431 return "#{docId}.Rules.[].Rule"432 end433 # Return a path that can be used for selecting PartitionPath elements434 # from a rulesDoc435 # @see getRulePath436 def getPartitionPathPath(docId)437 return "#{docId}.Rules.[].Rule.Conditions.[].Condition.PartitionPath"438 end439 # @todo this is a generic need for kb modelsHelper440 # @note assumes a certain model for a Conclusion document, @see getConclusionModel441 def getConclusionTemplate()442 kbDoc = BRL::Genboree::KB::KbDoc.new()443 kbDoc.setPropVal("Conclusion", "")444 valueHash = { "value" => "" }445 # flat properties446 properties = {447 "TimeStampOfDocument" => valueHash.deep_clone(),448 "TimeStampOfConclusion" => valueHash.deep_clone(),449 "Concluder" => valueHash.deep_clone(),450 "Guidelines" => valueHash.deep_clone(),451 }452 kbDoc.setPropProperties("Conclusion", properties)453 # assertions454 assertion = { "ReasonForAssertion" => valueHash.deep_clone() , "Assertion" => valueHash.deep_clone() }455 kbDoc.setPropItems("Conclusion.Assertions", [assertion])456 # status457 status = { "Name" => valueHash.deep_clone(), "Message" => valueHash.deep_clone() }458 kbDoc.setPropProperties("Conclusion.Status", status)459 return kbDoc460 end461 462 def getConclusionModel()463 model = <<EOS464{465 "name": "Conclusion",466 "domain": "regexp(Conclusion-[A-Z0-9]{20})",467 "required": true,468 "identifier": true,469 "unique": true,470 "properties": [471 {472 "name": "TimeStampOfDocument",473 "domain": "timestamp",474 "required": true475 },476 {477 "name": "TimeStampOfConclusion",478 "domain": "timestamp",479 "required": true480 },481 {482 "name": "Assertions",483 "domain": "[valueless]",484 "fixed": true,485 "items": [486 {487 "name": "Assertion",488 "domain": "regexp(Assertion-[A-Z0-9]{20})",489 "identifier": true,490 "properties": [491 {492 "name": "Assertion",493 "domain": "string",494 "required": true495 },496 {497 "name": "ReasonForAssertion",498 "domain": "string",499 "required": true500 }501 ]502 }503 ]504 },505 {506 "name": "Concluder",507 "domain": "string",508 "required": true509 },510 {511 "name": "Guidelines",512 "domain": "url",513 "required": true514 },515 {516 "name": "Status",517 "domain": "enum(ok, error, warning)",518 "required": true,519 "properties": [520 {521 "name": "Name",522 "domain": "string"523 },524 {525 "name": "Message",526 "domain": "string"527 }528 ]529 }530 ]531}532EOS533 end534 ######################################################################535 # Utility methods #536 ######################################################################537 # Utility function to transform a hash to a tsv string538 # @param [Hash] hash containing csv data539 # :header [Array] array with field names in a specified order540 # :data [Array<Hash>] array of header-like hashes with a row name key mapped to 541 # column keys mapped to values542 # @param [String] delimiter to use to separate fields/columns543 # @todo associated file version? adding pieces to file chunk by chunk?544 # @todo put this somewhere?545 def self.hashToCsv(hh, delim=",")546 retVal = ""547 retVal << hh[:header].join(delim) << "\n"548 data = hh[:data].collect { |kk, vv| vv }549 data.each { |datum|550 values = hh[:header].map{ |column| datum[column] }551 retVal << values.join(delim) << "\n"552 }553 return retVal554 end555 end556 class ReasonerJobError < WorkbenchJobError557 end558end; end; end...

Full Screen

Full Screen

singleton_class.rb

Source:singleton_class.rb Github

copy

Full Screen

1# coding: us-ascii2# frozen_string_literal: true3module Declare4 ScopeSummary = Struct.new(:target, :caller_entry, :nesting_level, keyword_init: true)5 @failures = {}6 @scope_summaries = []7 @pass_counter = 08 @declare_counter = 09 class << self10 attr_reader :failures11 def describe(&block)12 BasicScope.new.instance_exec(&block)13 end14 def auto_run15 at_exit do16 $! || report17 end18 end19 # @return [AssertionsScope]20 def new_scope(target, &block)21 AssertionsScope.new(target).instance_exec(target, &block)22 end23 def declared!24 @declare_counter += 125 end26 def scope!(target, caller_entry)27 @scope_summaries << ScopeSummary.new(target: target, caller_entry: caller_entry, nesting_level: caller_entry.block_level)28 end29 def pass!30 @pass_counter += 131 end32 def failure!(report)33 @failures[@scope_summaries.last] ||= []34 @failures[@scope_summaries.last] << report35 end36 def failure_count37 @failures.values.flatten.size38 end39 def report40 unless @failures.empty?41 report_detail42 puts '-' * 7843 end44 failure_count = failure_count()45 puts "#{@scope_summaries.length} scopes, #{@declare_counter} assertions, #{failure_count} failures"46 exit(failure_count)47 end48 private49 def report_detail50 top_header = 'Detail testing report'51 puts top_header52 puts '=' * top_header.length, nil53 @failures.each_pair do |scope, lines|54 header = (55 case scope.nesting_level56 when 057 obj_header = "#{scope.target.inspect} [#{scope.caller_entry.file_name}:#{scope.caller_entry.line_number}]"58 "#{obj_header}\n#{'-' * obj_header.length}"59 else60 "###{'#' * scope.nesting_level} #{scope.target.inspect} ###{'#' * scope.nesting_level} [#{scope.caller_entry.file_name}:#{scope.caller_entry.line_number}]"61 end62 )63 puts header, nil64 puts(lines.map { |l| "* #{l}" })65 end66 end67 end68end...

Full Screen

Full Screen

scope.rb

Source:scope.rb Github

copy

Full Screen

...10 end11 # @param [Integer] level12 # @return [CallerEntry]13 def _declare_called_from(level=0)14 CallerEntry.parse(caller[1 + level])15 end16 end17 class AssertionsScope < BasicScope18 include Assertions19 attr_reader :it20 def initialize(target)21 super()22 @it = target23 end24 end25end...

Full Screen

Full Screen

caller

Using AI Code Generation

copy

Full Screen

1 assert(1 == 2, "1 is not equal to 2")21.rb:16:in `c': 1 is not equal to 2 (RuntimeError)3 assert { 1 == 2 }42.rb:16:in `c': Failed assertion (RuntimeError)5 assert { 1 == 1 }6 assert("1 is not equal to 5") { 1 == 2 }

Full Screen

Full Screen

caller

Using AI Code Generation

copy

Full Screen

1 def self.assert_equals(expected, actual)2 def self.assert_equals(expected, actual)3 def self.assert_equals(expected, actual)4 def self.assert_equals(expected, actual)5 def self.assert_equals(expected, actual)

Full Screen

Full Screen

caller

Using AI Code Generation

copy

Full Screen

1 def self.assert_equals(expected, actual)2 def self.assert_equals(expected, actual)3 def self.assert_equals(expected, actual)4 def self.assert_equals(expected, actual)5 def self.assert_equals(expected, actual)

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Minitest_ruby automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful