- ☑️ Write one-line unit tests in the Google Earth Engine code editor
- ⏱️ Evaluate client or server-side objects asynchronously
First, import the should:test
module into your script.
var should = require("users/aazuspan/should:test");
Then write your first test.
should.equal(ee.Number(42), 42, "Check numbers are equal");
Hit run
and the test will evaluate and let you know if it passed ✅ or failed 🛑. Write more tests and should-test
will run them and summarize the results, printing out any errors that occur.
Tests in should-test
work transparently with client- and server-side objects. For example, both of the following work:
var year = 2022;
should.beGreater(year, 2010, "Check client-side year");
var year = ee
.Image("LANDSAT/LC09/C02/T1_L2/LC09_001006_20220404")
.date()
.get("year");
should.beGreater(year, 2010, "Check server-side year");
Tests with Earth Engine objects run asynchronously and report their results when finished, so there's no risk of freezing the browser with getInfo
.
By default, all the tests you've called will evaluate when you run your script. To filter tests that run, call should.settings.skip
and/or should.settings.run
at the top of your script. These functions match a regular expression pattern against the test descriptions and skip or run accordingly.
should.settings.run("band");
should.contain(image.bandNames(), "SR_B4", "check for band"); // run
should.beLess(collection.size(), 100, "compare size"); // skipped
In order to run each test, the should
assertion needs to be called. For organization, you can combine the assertion and any setup steps needed into a function and call that function, like so:
// Build the test
var myTest = function () {
var l9 = ee.ImageCollection("LANDSAT/LC09/C02/T1_L2");
var geom = ee.Geometry.Point([-112.690234375, 41.13290902574011]);
var col = l9.filterBounds(geom);
var cloudless = col.filter(ee.Filter.lt("CLOUD_COVER", 5));
should.beGreater(cloudless.size(), 1, "check # of cloud-free images");
};
// Run the test
myTest();
For convenience, you can skip naming and calling your test function using should.utils.call
, like so:
// Build and run the test
should.utils.call(function () {
var l9 = ee.ImageCollection("LANDSAT/LC09/C02/T1_L2");
var geom = ee.Geometry.Point([-112.690234375, 41.13290902574011]);
var col = l9.filterBounds(geom);
var cloudless = col.filter(ee.Filter.lt("CLOUD_COVER", 5));
should.beGreater(cloudless.size(), 1, "check # of cloud-free images");
});
There are two assertions that test whether a function throws an error: should.throw
and should.notThrow
. To use these, be sure to pass the callable function, not it's evaluated result. For example:
var myFunction = function () {
print("Hello world");
};
// Correct!
should.throw(myFunction);
// Incorrect! This will test the return value of the function instead of the function.
should.throw(myFunction());
If the function you want to test requires arguments, you can pass them using an anonymous function.
var myFunction = function(message) { print(message) };
// Wrap your function in an anonymous function to pass arguments
should.notThrow(function() {
myFunction("Hello world");
}
Assertions test a condition and fail when false. All assertions take a description
that is used to log test results.
To use a comparison assertion, Earth Engine objects must implement the corresponding operator, e.g. eq
, neq
, gt
, etc.
should.beTrue(value, description)
: Thevalue
should be true (strict for JS objects).should.beFalse(value, description)
: Thevalue
should be false (strict for JS objects).should.equal(actual, expected, description)
: Theactual
should equal the expected.should.notEqual(actual, expected, description)
: Theactual
should not equal theexpected
.should.almostEqual(actual, expected, description, error)
: Theactual
should be within a relativeerror
(default1e-6
) of theexpected
.should.beGreater(value, other, description)
: Thevalue
should be greater thanother
.should.beGreaterOrEqual(value, other, description)
: Thevalue
should be greater than or equal toother
.should.beLess(value, other, description)
: Thevalue
should be less thanother
.should.beLessOrEqual(value, other, description)
: Thevalue
should be less than or equal toother
.
should.match(string, pattern, description)
: The regexpattern
should match thestring
.should.notMatch(string, pattern, description)
: The regexpattern
should not match thestring
.should.contain(list, value, description)
: Thelist
should contain thevalue
.should.notContain(list, value, description)
Thelist
should not contain thevalue
.
should.throw(function, description)
: Callingfunction
should throw an error.should.notThrow(function, description)
: Callingfunction
should not throw an error.
should.exist(assetID, description)
: The asset should exist.should.bePublic(assetID, description)
: The asset should be public. Only usable by the asset owner or writer.
should.settings.skip(pattern)
: Tests with descriptions that match the regexpattern
are skipped.should.settings.run(pattern)
: Only tests with descriptions that match the regexpattern
are run.
should.utils.call(func)
: Callfunc
. Handy for wrapping anonymous functions.