TestRunner.run() doesn't run testst? - ceylon

I have created a 'Hello World' type test suite, but I can't seem to have it run any tests. When executed, it simply says:
reached run function
Process finished with exit code 0
I can thus tell that my two functions containing tests are never executed, as they contain print statements that are never printed.
This is the source code of my tests/run.ceylon file:
import ceylon.test {
TestRunner, createTestRunner
}
Anything myTests1 () {
// assert something true!
assert(40 + 2 == 42);
print("myTests1");
return null;
}
void myTests2 () {
// assert something false!
assert(2 + 2 == 54);
print("myTests2");
}
"Run the module `tests`."
shared void run() {
print("reached run function");
TestRunner myTestRunner = createTestRunner(
[`function myTests1`, `function myTests2`]);
myTestRunner.run();
}

the test function has to be annotated with test annotation, see https://modules.ceylon-lang.org/repo/1/ceylon/test/1.3.3.1/module-doc/api/index.html#start

Related

Async function returns two different results after another

I have written an async Flutter/Dart function which behaves unexpectedly in my opinion. Following code structure:
static Future<bool> verifySometing() async {
try {
await getCloudData().then((snapshot) {
if (snapshot.exists && snapshot.hasData) {
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
}
});
} catch (e) {
print('Error $e');
return false;
}
print('Something went wrong');
return false;
}
The expected result would be that the function awaits the cloud data, then awaits validation and returns true if the data is valid. In this case, the console would show the following and the function would return true:
Data is correct
What happens in practice is that the console shows the following output and the function first returns true and then false:
Data is correct
Something went wrong
This goes against anything I thought to know about funtions in Dart because I always assumed that once return is fired, the function is done. Any ideas how this happens?
The issue is with this line.
await getCloudData().then((snapshot) {
Here, instead of just awaiting, you have also attached a then callback. So in actuality, whatever you are returning is return value of the callback function ie., (snapshot) {}.
The callback function that you need to pass into the then takes that return true and gives it to us as the result of await.
So, if you would've put something like
var bool = await getCloudData().then((snapshot) { ..... });
Then this bool, would've been equal to true. That's it. No return from the your main function.
Change it to this,
var snapshot = await getCloudData();
if (snapshot.exists && snapshot.hasData) {
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
}
Hope, I was able to explain clearly.
There are a few of faults in your assumptions.
First, you've attached a then to the future returned by getCloudData(). This means that you aren't awaiting getCloudData(), but instead the additional future returned by getCloudData().then(...), and that future will return when the callback function passed to it completes. (And unless the first future throws an error, the callback will be called.)
Second, the callback function operates on its own scope. So this code is not doing what you think it's doing:
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
This return will affect the callback function, not the verifySomething function.
Given these, the order of operation is as follows:
The validateSomething function awaits getCloudData().then(...).
getCloudData() gets called.
getCloudData() returns, the callback passed to then is called.
(Assuming the snapshot has data) validateData is called.
(Assuming data is successfully validated) "Data is correct" gets printed and the callback function returns true.
validateSomething is notified that the awaited future is complete, so execution resumes.
"Something went wrong" gets printed and the validateSomething function returns false.
Generally speaking, these kinds of errors are common when mixing async/await and then patterns. Unless you know what you're doing, stick with either one or the other, preferably the async/await pattern. For example, a refactor of your code to eliminate the call to then is as follows:
static Future<bool> verifySometing() async {
try {
final snapshot = await getCloudData();
if (snapshot.exists && snapshot.hasData) {
bool dataValid = await validateData(snapshot.data);
if (dataValid) {
print('Data is correct');
return true;
}
}
} catch (e) {
print('Error $e');
return false;
}
print('Something went wrong');
return false;
}
Now that there isn't a pesky closure to deal with, return will return from validateSomething as expected and you don't need to deal with issues like callbacks and scope.

Conditional gulp task inside gulp.paralell() or gulp.series()

Too much information about conditions tasks inside pipes (e. g. "gulp-if" plugin). However, actually it is not "conditional tasks": it is the "conditional plugin usage", and one task can use multiple plugins. Here is how to conditionally run task NOT inside pipe (for example, inside gulp.paralell())
Suppose that task name can contain spaces for providing easy-to-understand task meaning.
gulp.task('Build', gulp.paralell(
'Preprocess HTML',
'Prepeocess styles',
done => {
if(checkSomeCondition()){
runTask('some Task') // but how?
}
else {
done();
}
}
))
The beauty of gulp4.0 is that your tasks can just be functions, so the following works:
gulp.task('Preprocess HTML', function () {
console.log("in Preprocess HTML");
return gulp.src('./');
});
You can use either the above version (the 'old way') or the newer
way below.
I show two tasks here that use both versions but I personally wouldn't mix them.
// function PreprocessHTML() {
// console.log("in Preprocess HTML");
// return gulp.src('./');
// }
function PreprocessStyles() {
console.log("in Preprocess styles");
return gulp.src('./');
}
function testTaskTrue() {
console.log("in testTaskTrue");
return gulp.src('./');
}
function testTaskFalse() {
console.log("in testTaskFalse");
return gulp.src('./');
}
function checkSomeCondition() {
console.log("in checkSomeCondition");
return false;
}
// Again, I definitely wouldn't mix the two versions of tasks as shown below.
// Just here for demonstration purposes.
gulp.task('test', gulp.parallel( 'Preprocess HTML', PreprocessStyles,
done => {
if (checkSomeCondition()) {
// so testTaskTrue can be any gulp4.0 task, easy to call since it just a function
testTaskTrue();
}
else {
testTaskFalse();
}
done();
}
));
For gulp 4, first create this helper function:
function gulpTaskIf(condition, task) {
task = gulp.series(task) // make sure we have a function that takes callback as first argument
return function (cb) {
if (condition()) {
task(cb)
} else {
cb()
}
}
}
As its first argument, this helper takes a condition in the form of a function. The condition function is run at the time when the task execution is to start, so you can i.e. check output of previous steps in the condition function.
The second arguments specifies the task to be run and can be the same values that gulp.parallel() or gulp.series() accept as arguments, i.e. string, function reference, or a return value from another gulp.parallel() or gulp.series().
Returns a function that can be passedto gulp.task() as second argument or as an argument to gulp.parallel() or gulp.series() call.
Examples (first one matches question):
embedded in e.g. gulp.parallel() or gulp.series(), calling task by name
gulp.task('Build', gulp.parallel(
'Preprocess HTML',
'Prepeocess styles',
runTaskIf(checkSomeCondition, 'some Task')
))
as a task, calling task by name
function myTask() {
return gulp.src(...)
...
.dest(...)
}
gulp.task('my-task', myTask)
gulp.task('default', gulpTaskIf(
function () {
return Math.random() < 0.5; // example condition
},
'my-task')
as a standalone task, calling task by function reference
function myTask() {
return gulp.src(...)
...
.dest(...)
}
gulp.task('default', gulpTaskIf(() => Math.random() < 0.5, myTask)
as a standalone task, calling gulp.parallel() or gulp.series() reference
const manyTasks = gulp.parallel(task1, task2, task3)
gulp.task('default', gulpTaskIf(
function () {
return Math.random() < 0.5;
},
manyTasks)
It is really simple. No need of helper function:
gulp.task('Build', function() {
const tasks = ['Preprocess HTML', 'Preprocess styles'];
if(checkSomeCondition()) tasks.push('some Task');
return gulp.parallel(tasks);
}());
The clue is in calling the function at the last line - it will return an adjusted gulp.parallel task - I am using this to handle command line arguments (yargs)
WARNING: this will be executed before the first task is executed and will be executed also when other task than 'Build' is run. Just have it on your mind when implementing logic ;)
I have an array for plugins where I do a simple If query and then expand the array, see line 280 here.
Based on Gulp 4.
For the build process I changed the Const to Let and also queried it with If.

Readable stream `_read` not called in test

I have the following simplified ava test case. When I run it by ava _read() never get called (ONDATA is OK). On the other hand, when I run this test body (without assertions) as node script I always get _read() called as expected.
Probably I miss some key feature, please advice.
test('...', async t => {
class R extends stream.Readable {
_read() { console.log('READ'); }
}
const rs = new R();
rs.on('data', data => {
console.log('ONDATA ', data.toString());
});
rs.push(Buffer.from('data'));
// t.is(...)
})
I can't immediately recall in what scenario _read() should get called, but most likely your test ends before that happens. You have an async test but you don't seem to await anything. Try returning an explicit promise or otherwise use test.cb() so you can end the test with t.end().
Thanks! Essentially I messed up with readable stream callbacks and async test. The desired test looks like
test.cb('...', t => {
class R extends stream.Readable {
_read() {
console.log('READ');
// t.pass() or t.end() HERE
}
}
const rs = new R();
rs.on('data', data => {
// t.pass() or t.end() HERE
console.log('ONDATA ', data.toString());
});
rs.push(Buffer.from('data'));
})

How do I run a delegate on a ui thread?

I am in a worker thread (I mean, thread pool task)...
I windows phone I would do:
Deployment.Current.Dispatcher.BeginInvoke(
delegate ()
{
// Do something on ui thread...
}
);
How can I do this in a Windows Store app?
I searched through msdn but came up empty...
Thanks
Here is the answer:
class ThreadUtility
{
// Warning: "Because this call is not awaited, execution of the current method
// continues before the call is completed. Consider applying the 'await'
// operator to the result of the call."
// But that's what we want here --- just to schedule it and carry on.
#pragma warning disable 4014
public static void runOnUiThread(Windows.UI.Core.DispatchedHandler del)
{
CoreWindow window = CoreWindow.GetForCurrentThread();
window.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, del);
}
#pragma warning restore 4014
}
...
ThreadUtility.runOnUiThread(
delegate ()
{
if(handler != null)
{
// Do something on ui thread...
}
}
);

Alert event handler

I have 2 functions which are dependent on each other. func1 is a method returning a value from database. If there is an error executing func1, an alert box shows and I dont want to execute func2. If func1 executes successfully without an error, then only I want func2 to get executed. I dont know how to achieve this. Any help will be greatly appreciated. Thank you in advance.
Regards,
Kevin.
Perhaps I'm missing something, but isn't as simple as:
private function getData():void
{
//get data
if (data)
{
onDataLoad();
}
else
{
//alert();
}
}
private function onDataLoad():void
{
//do something
}
Or, if your data load function returns a boolean, just work it into a similar scenario.
the function func1 should throw an error (A) or return an error code / null pointer (B).
(A)
try {
func1();
func2(); // only executed if func1 does not throw any errors
} catch (e:Error) {
// error handling
}
(B)
var myData:Object = func1();
if(myData != null) {
func2();
}