In a Kotlin multi-platform (or JS) project, (how) can one pass custom command line arguments to Node.js? - node.js

I'm working on a Kotlin multi-platform project, and I need my JS tests to run on Node.js but with custom command line arguments (specifically I need node to run with the --expose-gc flag, because some tests need to trigger garbage collection).
Looking at the documentation for the Gradle Kotlin JS DSL I didn't find any mention of how to do that; does anyone know whether it's at all possible and how?

Unfortunately can not answer your question directly, but there is some suggestion to help you with reverse engineering.
Let's start from some example. We have Gradle tasks to run our project using webpack's dev server such as browserDevelopmentRun, browserProductionRun (not sure if multi-platform projects have it, but JS projects do). We can add:
println(tasks.named("browserProductionRun").get().javaClass)
to build.gradle.kts to find out the exact class used for this task. When we sync Gradle, it outputs:
org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack_Decorated
Now we know the exact class of this task so we can investigate its API. The auto completion or navigating inside of the KotlinWebpack class helps us to find out that it has a helpful nodeArgs property to configure NodeJS arguments for it, so we can set them, for example:
tasks.named("browserProductionRun", org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack::class).get().nodeArgs.add("--trace-deprecation")
Getting back to your question.
In your case I guess you need to investigate the browserTest task. Let's get some info about it by adding:
println(tasks.named("browserTest").get().javaClass)
to build.gradle.kts - a-ha - it seems to be of the org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest_Decorated type. Let's check what's inside. Open KotlinJsTest.kt somehow - for example by typing its name into the window being opened by CMD + Shift + O (make sure to select "All Places" here) or just by typing its name somewhere in build.gradle.kts and navigating inside it.
The only interesting thing I see inside this open class is the following block:
override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec {
val forkOptions = DefaultProcessForkOptions(fileResolver)
forkOptions.workingDir = npmProject.dir
forkOptions.executable = nodeJs.requireConfigured().nodeExecutable
val nodeJsArgs = mutableListOf<String>()
return testFramework!!.createTestExecutionSpec(
task = this,
forkOptions = forkOptions,
nodeJsArgs = nodeJsArgs,
debug = debug
)
}
So maybe it can work out to create your own extension of this class, override its createTestExecutionSpec method and provide nodeJsArgs as you need inside it. After that you'll be needing to declare another Gradle task to launch tests inside build.gradle.kts which will use this new extended class.

Related

Suave with netcoreapp2.0

I've been following this Suave tutorial:
https://legacy.gitbook.com/book/theimowski/suave-music-store/details
And in general this looks good. However, I was trying to make it work with Linux and for some reason I was unable to compile it with code when TargetFramework was set to "net461" (Target Framework not found), so I tried changing it to "netcoreapp2.0". It compiled, but I hit a problem later on:
https://theimowski.gitbooks.io/suave-music-store/content/en/css.html
At the end it says to add a WebPart:
pathRegex "(.*)\.(css|png)" >=> Files.browseHome
which fails for me. All compiles, but I get
This page isn’t working
localhost didn’t send any data.
I took a look at Suave's source code and it turned out that "Files.browseHome" searches for a file under "ctx.runtime.homeDirectory".
I noticed that this is set on my machine to:
/home/<my_user_name>/.nuget/packages/suave/2.2.1/lib/netstandard1.6
and obviously, that's not my project directory, so no wonder it couldn't find the file.
My question here is: what shall I do in order to make my Suave app handle my css/png files correctly using Files.browseHome ?
EDIT:
Just found out that replacing the WebPart with:
pathRegex "(.*)\.(css|png)" >=> Files.browse "/home/<my_username>/<path_to_my_project>/bin/Debug/netcoreapp2.0/"
works fine, but it looks ugly. Any idea how to make it better ? Basically I don't want to be forced to hardcode the absolute path anywhere.
I think the answer is to be found in https://suave.io/files.html, which suggests creating a config as follows:
let config =
{ defaultConfig with homeFolder = Some (Path.GetFullPath "./public") }
The path returned by Path.GetFullPath will depend on the current working directory that your app sees when it's started (which will, in turn, depend on how you start the app: from the command line, from a systemd unit file, etc.) There are too many possible variables here for me to be able to give you exact instructions, but if your startup method can cd into an appropriate folder before starting your Suave server, then that should solve your problem.
If you run into difficulties with getting the current working directory set correctly, then you could just hardcode the full path in the config:
let config =
{ defaultConfig with homeFolder = Some "/home/<your_username>/<path_to_your_project>/bin/Debug/netcoreapp2.0/" }
But that's kind of ugly, and not really portable (you'd have to modify that path again once you deploy the app). So I'd recommend the approach of making sure your start script does a cd to the right location, then using Path.GetFullPath with a relative path. Alternately, you could have a config file that gets read in at app startup where you specify the home path, or pass it in as an environment variable... All kinds of possibilities. Just make sure that your code can be handed some information on startup that specifies the correct "home" folder, and then put that in your Suave config as I've shown, and that should solve it.

Cucumber feature outlines

Is it possible to parameterise a feature file in the same way it is a scenario? So each scenario in the feature could refer to some variables which are later defined by a single table for the entire feature file?
All of the answers I've found so far (Feature and scenario outline name in cucumber before hook for example) use Ruby meta-programming, which doesn't inspire much hope for the jvm setup I'm using.
No its not, and for good reason. Feature files are meant to be simple and readable, they are not for programming. Even using scenario outlines and tables is generally not a good thing, so taking this further and having a feature that cannot be understood without reading some other thing that defines variables is counter productive.
You can however put all your variables and stuff in step definitions and write your feature at a higher level of abstraction. You'll find implementing this much easier, as you can use a programming language (which is good at this stuff).
One way of parameterising a feature file is to generate it from a template at compile-time. Then at runtime your cucumber runner executes the generated feature file.
This is fairly easy to do if you are using gradle. Here is an example:
In build.gradle, add groovy code like this:
import groovy.text.GStringTemplateEngine
task generateFeatureFiles {
doFirst {
File featuresDir = new File(sourceSets.main.output.resourcesDir, "features")
File templateFile = new File(featuresDir, "myFeature.template")
def(String bestDay, String currentDay) = ["Friday", "Sunday"]
File featureFile = new File(featuresDir, "${bestDay}-${currentDay}.feature")
Map bindings = [bestDay: bestDay, currentDay: currentDay]
String featureText = new GStringTemplateEngine().createTemplate(templateFile).make(bindings)
featureFile.text = featureText
}
}
processResources.finalizedBy(generateFeatureFiles)
myFeature.template is in the src/main/resources/features directory and might look like this:
Feature: Is it $bestDay yet?
Everybody wants to know when it's $bestDay
Scenario: $currentDay isn't $bestDay
Given today is $currentDay
When I ask whether it's $bestDay yet
Then I should be told "Nope"
Running the build task will create a Friday-Sunday.feature file in build/src/main/resources with the bestDay and currentDay parameters filled in.
The generateFeatureFiles custom task runs immediately after the processResources task. The generated feature file can then be executed by the cucumber runner.
You could generate any number of feature files from the feature template file. The code could read in parameters from a config file in your resources directory for example.

minko / lua issue : premake5.lua:3: attempt to index global 'minko' (a nil value)

I am working with minko and managed to compile MINKO SDK properly for 3 platforms (Linux, Android, HTML5) and build all tutorials / examples. Moving on to create my own project, I followed the instructions on how to use the existing skeleton project, then using an existing example project.
(I believe there is an error in the skeleton code at this line :
auto sceneManager = SceneManager::create(canvas->context()); //does not compile
where as the example file look like this :
auto sceneManager = SceneManager::create(canvas); //compile and generate binary
I was able to do so by modifying premake5.lua (to include more plugins) and calling script/solution_gmake_gcc.sh
to generate the make solution a week ago. Today, I tried to make a new project in a new folder but calling
script/solution_gmake_gcc.sh and script/clean failed with this error:
minko-master/skel_tut/mycode/premake5.lua:3: attempt to index global 'minko' (a nil value)
Now at premake5.lua line 3 there is this line : minko.project.solution(PROJECT_NAME),
however sine i am not familiar with lua at all, can anyone shed any light on the issue ?
What is supposed to be declared here, why is it failing suddenly... ?
(I can still modify,compile and run the code but i can't for example add more plug-ins)
PS: weirdly enough, the previously 'working' project is also failing at this point.
Thanks.
PROJECT_NAME = path.getname(os.getcwd())
minko.project.application("minko-tutorial-" .. PROJECT_NAME)
files { "src/**.cpp", "src/**.hpp", "asset/**" }
includedirs { "src" }
-- plugins
minko.plugin.enable("sdl")
minko.plugin.enable("assimp")
minko.plugin.enable("jpeg")
minko.plugin.enable("bullet")
minko.plugin.enable("png")
--html overlay
minko.plugin.enable("html-overlay")
Assuming that's indeed your project premake5.lua file (please us the code tags next time), you should have include "script" at the beginning of the file:
https://github.com/aerys/minko/blob/master/skeleton/premake5.lua#L1
If you don't have this line, it will not include script/premake5.lua which is in charge of including the SDK build system files that defines everything inside the minko Lua namespace/table. That's why you get that error.
I think you copy pasted one of the examples/tutorials premake5.lua file instead of modifying the one provided by the skeleton. The premake conf file of the examples/tutorials are different since they are included from the SDK premake files. But your app premake5.lua does the "opposite": it includes the SDK conf files rather than being included by them.
The best practice is to edit your app's copy of the skeleton's premake5.lua (instead of copy/pasting one from the examples/tutorials).
(I believe there is an error in the skeleton code at this line :
That's possible. Our build server doesn't test the skeleton code. That's a mistake we will fix ASAP to make sure it works properly.
script/solution_gmake_gcc.sh and script/clean failed with this error:
minko-master/skel_tut/mycode/premake5.lua:3: attempt to index global 'minko' (a nil value)
Could you copy/paste your premake5.lua file?
Also, what's the value you set for the MINKO_HOME env var? Maybe you've moved the SDK...
Note that instead of setting a global MINKO_HOME env var, you can also set the corresponding LUA constant at the very begining of your premake5.lua file.

What is the simplest way to create a UI test in Android Studio that can take screenshots when I need it to?

I am trying to create a UI test in Android Studio which will navigate through the various screens of my application and take screenshots when I tell it to.
I am new to Android Studio and Android programming in general; I have a decent understanding of XML and Java, but I don't know much about build files and I am not very good at using Android Studio, it seems.
I started this endeavor a couple weeks ago, and the first solution I tried was to use uiautomator. However, the documentation on that page (and seemingly just about everywhere else) is geared towards development with Eclipse, which I would like to avoid using for this project if possible.
The next thing I tried was Espresso. After I overcame some issues with implementing Espresso into my project, I was able to write tests with Espresso which would navigate through the screens of my application. However, unlike uiautomator, Espresso does not have built-in functionality to take screenshots at this time.
I first attempted to solve this problem of being unable to take screenshots with Espresso by writing custom code; as I'm still unfamiliar with Android, I wasn't really sure how to go about that, so I searched for help on the Internet (How to programmatically take a screenshot in Android?). However, I was unable to get the solutions I found to function from inside the test file.
Somebody recommended the usage of this tool: https://github.com/rtyley/android-screenshot-lib but I could not figure out how to import that into my project.
I eventually came back to uiautomator; I was still having a lot of trouble importing it into my project, and some people said that Robotium would help with that. I got Robotium to work, but I still could not import uiautomator.
It has been probably one month since I started using Android Studio, and in that time, I've had nothing but trouble simply getting the software to function properly. For the sake of brevity, I've omitted all the problems I have managed to solve on my own, but, to put it bluntly, I'm at the end of my patience.
TL;DR
If somebody could either:
-explain in the simplest possible way how to import uiautomator into an Android Studio project (I have read a lot of documentation about how to import external libraries into a project, but they all tell me to add a 'libs' folder to my project, but do not specify which type of folder to use [Java Resource Folder? Assets Folder? Module? etc.], and/or they tell me to go into Project Structure, select my app, go to dependencies, and choose "Import as Module," which does not work...)
OR
-explain how best to take a screenshot from inside of an Espresso test, including any instructions on how to import any required libraries
OR
-explain in detail some other way to create a UI test that can take screenshots...
...I would really appreciate it. I've spent days trying to figure out how to do this, and I am so frustrated. Many people have asked similar questions, but the answers are either too vague or the problems aren't close enough to my own.
Thanks!
Alright, after much trouble, I've found a very simple solution. It took me a very long time to work out, but if anyone else needs to do something similar, I'll put my conclusion here.
First of all, the testing framework that is easiest to use with Android Studio, it seems, is Espresso. Setting up Espresso is fairly simple; most of the instructions can be found here: https://code.google.com/p/android-test-kit/wiki/EspressoSetupInstructions Make sure you read it carefully -- it tells you basically everything you need to know, but I missed some important details and that caused me a lot of trouble.
If you browse around that Espresso site, it tells you just about everything you need to know about how to write Espresso tests. It was a little frustrating for me because, if I wrote a test and the test failed, my device would then have connection issues with my laptop and I would have to disconnect and reconnect the USB cord I was using. I think this had something to do with the fact that I was using a Nexus 7 with a Windows 8 laptop, which has given me some problems in other areas, so you may not encounter this issue yourself.
Now, unlike uiautomator, the documentation of which claims to have support for taking screenshots, Espresso does not have built-in support for taking screenshots. That means you'll have to figure out a different way to take screenshots. My solution was to create a new class (called HelperClass, in my case) inside my androidTest package and add this method to it.
public static void takeScreenshot(String name, Activity activity)
{
//slightly modified version of solution from http://www.ssaurel.com/blog/how-to-programmatically-take-a-screenshot-in-android/
//I added "/Pictures/" to my path because that's the folder where I wanted to store my screenshots -- you might not have that folder on your device, so you might want to replace "/Pictures/" with just "/" until you decide where you want to store the screenshots
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Pictures/" + name;
View v = activity.getWindow().getDecorView().getRootView();
v.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());
v.setDrawingCacheEnabled(false);
OutputStream out = null;
File imageFile = new File(path);
//the following line will help you find where the screen will be stored on your device
Log.v("Screenshot", "The image file path is " + imageFile.getPath());
try {
out = new FileOutputStream(imageFile);
// choose JPEG format
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
} catch (FileNotFoundException e) {
// manage exception
} catch (IOException e) {
// manage exception
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception exc) {
}
}
}
In order for this function to work, you will also have to add the following line to your manifest file.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Without that, the function above will throw a FileNotFoundException every time you run it.
Finally, to call the takeScreenshot function from inside your Espresso test code, use this line (assuming you called your class HelperClass... if not, use the name of your class instead.
HelperClass.takeScreenshot("Whatever you want to call the file", getActivity());
Finding where your screenshots are stored can be a little difficult if you don't know where to look. I added a line of code to the takeScreenshot function that would print the filepath to LogCat, but I was using the file explorer on my computer to look for the screenshots on my Nexus (which was, of course, connected to the computer), and I couldn't find that path. However, I got a file explorer application on my tablet which made it very easy to find where the files were located in relation to everything else.
My solution may not be the simplest and it certainly isn't the best -- you'll fill your device up with screenshots before long if you aren't careful to delete the ones you don't need anymore, and I haven't got any idea how one would go about saving the screenshots directly to, say, a computer connected to the tablet via USB. That would certainly be helpful. However, if you really need a simple UI test that takes screenshots, and you're frustrated to no end like I was, this solution should probably help. I certainly found it useful.
I hope this helps somebody else -- it definitely solved my problems, at least for now.
Of course if you don't have all the restrictions that I did when I had to write a UI test that took screenshots, the other posts in this thread probably work much better.
You should give AndroidViewClient/culebra a try. Using culebra GUI, you can automatically generate a test case that interacts with your app and takes screenshot exactly when you indicate so.

Is GroovyResourceLoader ever called outside the main ClassLoader?

Ive setup a GroovyResourceLoader and it seems to get requests for groovy scripts as necessary. I was just wondering is it specially used anywhere besides class loading ? Is there any benefit in simply wrapping a ClassLoader and loading *.groovy files there as opposed to using a GRL ? Are they just different ways to the same end ?
GroovyResourceLoader (GRL) is used by GroovyClassLoader (GCL) and at least since Groovy 1.8 indirectly through GroovyScriptEngine (GSE). But GSE loads it through a GCL as well.
But what GRL does is to "locate" the scripts and return an URL to the location. What GCL does is use the URL returned by a GRL to get the source and compile it to create the class, which is then available for loading.
GRL is a backend for GCL. So they are not different ways to the same end. True, you still have to do more things to actually execute the script code (unless it is precompiled), but "get the script source, compile it, make a Class out of it and finally execute it" are the steps you always have to do. In our GRL/GCL discussion, GRL does part of the first step, GCL itself does the third step. Step 2 is done by CompilationUnit inside GCL and the last step is yours to be done. There are other ways to complete these steps of course, but that's out of the scope for this discussion.

Resources