use Selenium::Waiter 'wait_until';
use Selenium::Remote::Driver;
$selen = Selenium::Remote::Driver->new( ... );
$elem = wait_until { $selen->find_element('//h1[#class="banner-heading"]') };
In the above code, if the element being looked for is not found, or the wait_until times out, I want to the script to die. How can I make this happen? The default behaviour of wait_until is to return an empty string if it times out.
As Selenium::Waiter docs say on die-ing
PLEASE check the return value before proceeding, as we unwisely suppress any attempts your BLOCK may make to die or croak. The BLOCK you pass is called in a "try" in Try::Tiny, and if any of the invocations of your function throw and the BLOCK never becomes true, we'll carp exactly once at the end immediately before returning false.
and then proceed to allow us to bail out
If you want to die anyways, just pass die => 1 to wait_until instead:
# Dies on the first failure, do your own error handling:
wait_until { die 'oops' } die => 1;
I've tested it and it works. One can also adjust wait period and intervals for re-tries.
Note the docs' warning to make sure that implicit_wait from Selenium::Remote::Driver is set to a low value (it is by default but if
set_implicit_wait_timeout is called that may be changed).
As for die-ing on failing to find_element, the Selenium::Remote::Driver does that by default
If the element cannot be found, we will CROAK, killing your script.
So
my $elem = wait_until { $selen->find_element(...) } die => 1;
should do what you need.
Related
I'm testing a function using Chai's expect ... not.to.throw pattern (v4.3.4):
describe('parseInt', () => {
it('does not throw TypeError', () => {
// foo is not defined, so a ReferenceError is thrown... somewhere?
expect(() => parseInt(foo)).not.to.throw(TypeError);
});
});
The closure throws an error, but I don't see this error anywhere in the output (running mocha). The test passes without the slightest indication of the problem inside the closure.
I expect to at least see the error in the console, even if the tests pass.
This answer says that such errors must be run like so:
// wrapping describe/it are elided
try {
expect(() => parseInt(foo)).not.to.throw(TypeError);
} catch (e) {
expect(e).to.be.a(ReferenceError); // should PASS, and does
}
This passes, but doesn't appear to be testing the second condition. I can flip it and the test still passes:
// wrapping describe/it are elided
try {
expect(() => parseInt(foo)).not.to.throw(TypeError);
} catch (e) {
expect(e).not.to.be.a(ReferenceError); // should FAIL, but does not
}
What am I missing?
Edit
I think the behavior you are observing is actually expected. The original post you referenced may be misleading.
Consider the following test:
// describe/it wrappers have been redacted
expect(()=>parseInt(foo)).to.not.throw(TypeError)
Should this test pass or fail? Intuitively it should pass since the assertion is met: a TypeError was not thrown.
Again for the following test, should 'hello there' be logged to the console?
// describe/it wrappers have been redacted
try {
expect(() => parseInt(foo)).to.not.throw(TypeError);
} catch (e) {
console.log('hello there')
}
If yes, then the statement expect(() => parseInt(foo)).to.not.throw(TypeError), must throw.
And for it to throw, the assertion - not throw a TypeError - must not be met, but we have already established that the assertion is met, and so no exception is thrown.
Therefore, all code in the catch block is unreachable.
This is why the second assertion in your original example is never executed. It will only be reached if the code somehow threw a TypeError and caused the assertion to fail.
Possible solution
For the approach you are taking, I think it could work if there was a way to tell mocha/chai to still go ahead and propagate the error that is thrown by the target function even if the assertion is met. I am unsure of if there is a way to do this, though.
Alternative approach
Alternatively, I think you can get the same (or similar) outcome for the test you have in mind by doing this instead:
// describe/it wrappers have been redacted
const myFunc = () => parseInt(foo)
expect(myFunc).to.not.throw(TypeError)
expect(myFunc).to.throw(ReferenceError)
Here are the assumptions underlying the above test:
You are expecting an error
The error should under no circumstances be a TypeError
The error thrown should always be a ReferenceError.
In case these assumptions do not match what you are currently testing for, or if my alternate approach does not satisfy your needs, kindly let me know!
PS, I used mocha: "^9.1.0" and chai: "^4.3.4" for these tests.
Sorry, I couldn't come up with a better title. My problems is the following: If I execute a Tcl proc, I can wrap the execution in catch to catch and process errors. I do this in my code to have the same error output everywhere. However, my program provides numerous procs which the user can use in scripts (mostly at the outermost level), and it would be cumbersome if the user would have to wrap every one of them in a catch. I could of course use an additional level of indirection in each of those commands, but I wanted to ask whether there is a way to catch errors from all commands executed, without explicitly using catch on each invocation?
Thanks for your help!
Read this paragraph first: ↓
The single most important principle of error handling is don't throw away errors unless you know for sure that that's the correct way to handle them. Doing so just because they're unsightly is very bad! (Logging them is far better.)
The closest you can get is to run the whole of your existing code inside a catch or try. You can put a source inside that, so a little driver script to retrofit on existing code is just something like:
set argc [llength [set argv [lassign $argv argv0]]]
catch {source $argv0}
Assuming you're applying it during the call to the overall script. You also might need to set up interp bgerror:
interp bgerror {} {apply {{msg opt} {
if {[lindex [dict get $opt -errorcode] 0] eq "EXPECTED"} {
# Ignore this
} else {
# Unexpected error; better tell the user
puts "ERROR: $msg"
puts [dict get $opt -errorinfo]
}
}}}
It's not a really good idea to do this though. If you hide all the errors, how will you find and fix any errors? Using try is better, since that lets you hide only expected errors:
try {
source $argv0
} trap EXPECTED {} {
# Ignore this
}
and I'd probably wrap things up so that I have local variables:
apply {{} {
global argv0 argv argc
set argc [llength [set argv [lassign $argv argv0]]]
try {
uplevel #0 [list source $argv0]
} trap EXPECTED {msg} {
# Log this; the logging engine is out of scope for the question
log DEBUG $msg
}
}}
You'll need to experiment to see what to trap.
I see the following code in Perl 6:
await do for #files -> $file {
start {
#do something ... }
}
which runs in async mode.
Why does the above code need do? What is the purpose of do in Perl 6? Could someone please explain the above code in detail?
Also is there are an option to write something like this:
for #files -> $file {
start {
#do something ... }
}
and await after the code for the promises to be fulfilled?
The purpose of do
The for keyword can be used in two different ways:
1) As a stand-alone block statement:
for 1..5 { say $_ }
2) As a statement modifier appended to the end of a statement:
say $_ for 1..5;
When the bare for keyword is encountered in the middle of a larger statement, it is interpreted as that second form.
If you want to use the block form inside a larger statement (e.g. as the argument to the await function), you have to prefix it with do to tell the parser that you're starting a block statement here, and want its return value.
More generally, do makes sure that what follows it is parsed using the same rules it would be parsed as if it were its own statement, and causes it to provide a return value. It thus allows us to use any statement as an expression inside a larger statement. do if, do while, etc. all work the same way.
Explanation of your code
The code you showed...
await do for #files -> $file {
start {
#do somthing ... }
}
...does the following:
It loops of over the array #files.
For each iteration, it uses the start keyword to schedule an asynchronous task, which presumably does something with the current element $file. (The $*SCHEDULER variable decides how the task is actually started; by default it uses a simple thread pool scheduler.)
Each invocation of start immediately returns a Promise that will be updated when the asynchronous task has completed.
The do for collects a sequence of all the return values of the loop body (i.e. the promises).
The await function accepts this sequence as its argument, and waits until all the promises have completed.
How to "await after the code"
Not entirely sure what you mean here.
If you want to remember the promises but not await them just jet, simply store them in an array:
my #promises = do for #files -> $file {
start {
#do something ... }
}
#other code ...
await #promises;
There is no convenience functionality for awaiting all scheduled/running tasks. You always have to keep track of the promises.
i am processing a ragged semicolon delimited file using script component as transformation.
The component is able to process the data and load to oledb destination. But when error is found it should stop processing further. As i am using try catch block the component doesn't fail and continue to process till the end.
Is there any way i could stop the processing further without failing the component/package?
Let me know if any other information/details required?
sample code:
str.split(";");
if(column[0] == "H")
{
col1=Column[3];
}
if(column[0] != "T")
{
try
{
Row.col1=Column[0];
Row.col2=Column[1];
.....
}
catch
{
update the variable to check if we have error in file.
}
}
Thank you for your time.
The general idea will be that you want to use try/catch blocks to ensure the data processing itself doesn't abort. Once you know your script isn't reporting a failure back to the engine, it's a simple process to not call the AddRow()
Pseudocode
foreach(line in fileReader)
{
try
{
// perform dangerous operations here
// Only add row if you have been able to parse current line
Output0Buffer.AddRow();
Output0Buffer.Col1 = parsedContent;
}
catch
{
// Signal that we should break out of the loop
// do not propagate the error
// You might want to do something though so you know you
// have an incomplete load
break;
}
}
If you are looking to just skip the current bad line, you can substitute continue for the break above.
C# loop - break vs. continue
I didn't get any help from anywhere, But as a work around i have placed a return statement in the code. It checks the error variable if it's true then i will return without processing further. But the thing still is it processes the whole file :(. But it works!!!
This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 5 years ago.
From a tutorial on the intertubes I learned a bit about doing PDO queries. The tutorial used try/catch and the queries are basically structured like so:
try {
$dbh = new PDO("mysql:host=$hostname;dbname=$dbname", $user, $pass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$stmt = $dbh->prepare("UPDATE users yada yada yadda");
$stmt->bindParam(':param1', $param1, PDO::PARAM_INT);
$stmt->bindParam(':param2', $param2, PDO::PARAM_INT);
$stmt->execute();
}
catch(PDOException $e)
{
echo $e->getMessage();
}
This of course echos mysql errors on the screen. Not that I intend on having bad queries, but I do not like the idea of echoing out errors right on the screen, figuring what if an attacker tries to induce said errors and try to learn something from them.
Is there a better way to do this so that any errors go to a log file instead, or do I in actuality have nothing to fear in this regard since the bound parameters eliminate the risk of any sql injection?
The tutorial is correct in that you want to use try..catch blocks to catch code that will possibly cause an error and bring down whatever you're loading. So, if you have some code that is dependent on this code executing you'd want to include it in your try section. If you absolutely need this code to execute for whatever you're creating to work, then you'll probably want to catch the error and redirect the user to some type of error page.
If you use the php error log function then instead of
echo $e->getMessage();
You can use
error_log($e->getMessage(),0);
to send the error message from PDO directly to your php error log. If you don't know where the error log is, you can check out this link for a couple pointers to it if you're running a *nix system. If you're running windows there should be a config file somewhere that will tell you. Or you can check the php ini file for the location it's pointing to for a surefire way to find the log.
Is there a better way to do this
Yes, sure!
That's apparently wrong way of handling PDO errors this tutorial taught you.
So, just get rid of these try..catch commands - that's all.
This way you'll have PDO exceptions handled the same way as other PHP errors. Thus, in case of query error your script will be halted and error will be logged (if you tell PHP so).
To tell PHP so, you have to set log_errors ini directive to 1
To tell PHP not to show errors on-screen, set display_errors ini directive to 0 (on a development server you may wish to reverse them though)
Well, my answer probably not in the best practice, so please leave it to the last option. But for my case, it works perfectly.
PDO::__construct however will give you an exception anyway no matter what you set in PDO::ATTR_ERRMODE. I don't know why they design it to behave like that.
My way to solve this problem is to create a code area i call it Debug Critical Section (means you need very careful about the codes in the section), any errors in this section will not directly output to user.
Here is the code i made for my framework:
private function doPDOConnect($dbIndex, &$DBInfo, &$error) {
$dbh = null;
$successed = false;
if (!isset($this->connectedDB[$dbIndex])) {
// Enter Critical Section so no error below belowing code will cause error output, but the error still in log though
facula::core('debug')->criticalSection(true);
try {
$dbh = new PDO($DBInfo['Driver'] . ':' . $DBInfo['Connection'] . '=' . $DBInfo['Host'] . ';dbname=' . $DBInfo['Database'], $DBInfo['Username'], $DBInfo['Password'], array( PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_TIMEOUT => $DBInfo['Timeout'] )); // ATTR_ERRMODE => PDO::ERRMODE_WARNING. or we will cannot get anything even error happens
$dbh->facula_prefix = $DBInfo['Prefix'];
$dbh->facula_index = $dbIndex;
$dbh->facula_connection = $DBInfo; // In order you want to reconnect this specify database after connection lost etc, remove if you worry about the security issue.
$successed = true;
} catch (PDOException $e) {
$error = $e->getMessage(); // If any error, catch it, to &$error.
}
// Exit Critical Section, restore error caught
facula::core('debug')->criticalSection(false);
if ($successed) {
return $this->connectedDB[$dbIndex] = $dbh;
}
} else {
return $this->connectedDB[$dbIndex];
}
return false;
}
So in your case, you may replace my facula::core('debug')->criticalSection to display_errors off/on to handle the error display handler correctly.
For example:
$display_error_status = ini_get('display_errors');
function criticalSection($entered) {
global $display_error_status;
if ($entered) {
ini_set('display_errors', '0');
} else {
ini_set('display_errors', $display_error_status);
}
}