-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add the ability to get the current script or project path when using the new test runner #110
Comments
This is the sort of thing that should be exposed through the API (#48). |
/sub ... I'm having the same problem (also covered in #123). Our existing tests use Platform.script to load data, making hard to migrate to test runner. Anecdotally: most packages I've worked on with VM tests end up using data files. Anyway, I'm guessing I can work around this with dart:mirrors ... instead of Platform.script, find the script's library URI via mirrors. |
dart_style becomes a dev_dependency, and remove the ability to auto-run it from dart backend, instead use the test formatter migrate to package:test, which has a few tricky bits: * expect can only appear inside a test now (dart-lang/test#132) * mirrors is needed to get the test folder (dart-lang/test#110) * test `main` can't take arguments. not sure what's up there, but not a big deal for us either. [email protected] Review URL: https://codereview.chromium.org/1166683005
Is there a simple hack/workaround for this, that we can use until it is implemented? (Apart from setting an environment variable) |
I use the following ugly workaround (cross posted on SO) that gets me the directory name of the current test script if I'm running it directly or with pub run test. It will definitely break if anything in the implementation changes but I needed this desperately...
|
fyi, I got it working with something a bit simpler: import 'dart:mirrors';
import 'package:path/path.dart' as path;
final String testDirectory =
path.dirname((reflectClass(_TestUtils).owner as LibraryMirror).uri.path);
class _TestUtils {} Basically, get your own library through mirrors and grab the URI path. |
If you don't want to make a fake class, you can also do: currentMirrorSystem().findLibrary(#your_library).uri.path); |
Is this a bug/feature of |
No, if anything, it's an issue with the core libraries. The forthcoming resource/package-spec stuff should solve it, though. |
dart_style becomes a dev_dependency, and remove the ability to auto-run it from dart backend, instead use the test formatter migrate to package:test, which has a few tricky bits: * expect can only appear inside a test now (dart-lang/test#132) * mirrors is needed to get the test folder (dart-lang/test#110) * test `main` can't take arguments. not sure what's up there, but not a big deal for us either. [email protected] Review URL: https://codereview.chromium.org/1166683005
@nex3: Regarding your last comment, do you know if it's been solved yet? Or if there is an SDK issue to link to? I'd love an issue to track. |
I had this problem when I trying read some files in my tests section, to solve that and the problem to open file em multiple platforms, I write the following script:
|
I think this issue should be taken up again. Seems like the It would be really nice to have a getter in |
@sigurdm directory like One concern with exposing a path only is that it isn't useful on the web. If we make APIs for reading files, we could potentially make it work on all platforms and build systems. Differences in the directory layout is an ongoing pain point between |
Yeah - that would work for me! |
|
Capturing some thoughts about this after some conversations with @jakemac53 and @nshahan An alternative could be a builder (eventually a macro) that inlines file content to a const String or list of bytes in Dart source. Even if we had macros today, this alternative might not be satisfying since it doesn't allow for reading a large file, handling it, and then freeing it from memory before reading the next. I had proposed a hardcoded directory
I think we prefer either a hardcoded directory or the package root. Relative to the file that makes this too complicated to implement, and relative to the currently running test suite could be confusing. Use the package root:
Cons
Use
Cons
|
An example of the type of code written to work around the environment differences: https://dart-review.googlesource.com/c/sdk/+/242162 Neither of the proposals above would solve this issue. Either could solve the issue if there was a step outside of running the tests which copied or symlinked the files into the package somewhere. I could imagine doing that in bazel in place of setting up the environment variables, but we wouldn't have a good solution for this case externally. |
There is some potential for aligning this with our internal bazel build rules and having a close coupling with the b/235365551 |
Yes, I think we should read from |
Another thing to consider here is reading data from other packages, likely via |
Another hacky alternative is to extract the path from the stack trace. I think this works (for non-web cases)? import 'package:stack_trace/stack_trace.dart' as stacktrace;
String currentDartFilePath({bool packageRelative = false}) {
var caller = stacktrace.Frame.caller(1);
return packageRelative ? caller.library : caller.uri.toFilePath();
} |
It's very plausible that things like parsing the stack trace will work in some environments and not others. I don't know the specific behavior in bazel internally. |
I also ran into this, and also made a workaround. Without knowing about this discussion, I also gravitated towards using the package root. That being said, a FWIW, my code (only tested on VM, not in browser, and not tested with Bazel). /// Test files are run in a variety of ways, find this package root in all.
///
/// Test files can be run from source from any working directory. The Dart SDK
/// `tools/test.py` runs them from the root of the SDK for example.
///
/// Test files can be run from dill from the root of package. `package:test`
/// does this.
Uri findPackageRoot(String packageName) {
final script = Platform.script;
final fileName = script.name;
if (fileName.endsWith('_test.dart')) {
// We're likely running from source.
var directory = script.resolve('.');
while (true) {
final dirName = directory.name;
if (dirName == packageName) {
return directory;
}
final parent = directory.resolve('..');
if (parent == directory) break;
directory = parent;
}
} else if (fileName.endsWith('.dill')) {
final cwd = Directory.current.uri;
final dirName = cwd.name;
if (dirName == packageName) {
return cwd;
}
}
throw StateError("Could not find package root for package '$packageName'. "
'Tried finding the package root via Platform.script '
"'${Platform.script.toFilePath()}' and Directory.current "
"'${Directory.current.uri.toFilePath()}'.");
}
Uri packageUri = findPackageRoot('c_compiler');
extension on Uri {
String get name => pathSegments.where((e) => e != '').last;
} |
Fwiw, to get the root of the current package it might be a bit more robust to use |
My test data contains dart projects that contain tests, so nesting it inside |
We do have the |
Don't you mean The paths are not globs, so we have to enumerate everything under |
Ah I didn't catch that it was basename only. Using |
Can this be part of the programmatic API, that is, a /// Returns the package root (the directory with `pubspec.yaml`) for the currently running test.
///
/// This is a partial replacement for the functionality of `Platform.script.path`, but works regardless of whether
/// the script is run directly (`dart run test/my_test.dart`) or through the test runner (`dart test test/my_test.dart`).
String get currentPackageRoot {
// ...
} I would find this super helpful, and it would make adopting something like |
What would the expected behavior be for non-cli tests? For example web tests or flutter tests. Or even for cli tests, it gets weird in bazel or |
We'd prefer it not be, since this isn't a path we can provide in google3. What would you do with that information after you have it? And would you be skipping those tests in google3? |
Flutter tests do have access to the file system (it's a thin embedder on top of the Dart VM), but ignoring that - I think it would be OK to either give the root anyway (assuming it's possible) - it won't be useful information but it could still be provided, or to have the API throw
I'm worried we're making perfect enemy of the good here - the workarounds needed to get functionality that needs to 95-99% of the time just run on the Dart VM independent of google3 are significant, and fixable. If pkg/test has an "embedder" API, it could allow providing a resolver for this method, and Bazel/g3 could use it, otherwise it could just throw Unsupported. |
Historically we had a fair amount of pain during rolls into google3 when there are tests that rely on the particulars of external pub project structure and fail in google3. Do you expect usage of this particular API to remain limited to tests which are easy and safe to exclude from google3 testing?
Would it be sufficient to provide the package name for the currently running test and require the test embedder to do something meaningful from the name? From #110 (comment) the main concern in your use case is knowing what package to look up right? That would leave the decision to introduce non-cross-compatible behavior outside of the test package. |
You could even not export this in the google3 build |
You could even not export this in the google3 build, i.e. its not part of the g3 API.
I think the answer is "yes", assuming the default embedder does it :) |
#2245 is precedent for exposing information about the package config location to test embedders (through a somewhat suspect communication channel which works around limitations in providing this information through the VM service while the isolate is paused). Edit: The package config URI that we know about here likely isn't useful for |
Hmm, we might not even reliably know the package name. |
One idea here is to just expose the relative path to the current test script. So, something like For most tests, you can then do |
One snag with the relative path solution is supporting running test files directly, although we could try to infer it from |
http://stackoverflow.com/questions/30214563/get-current-script-path-or-current-project-path-using-new-test-runner
I am porting old vm unittest files using the new test package. Some relies on input files in sub directories of my test folder. Before I was using Platform.script to find the location of such files. This works fine when using
However using
this is now pointing to a temp folder (tmp/dart_test_xxxx/runInIsolate.dart). I am unable to locate my test input files anymore. I cannot rely on the current path as I might run the test from a different working directory.
Is there a way to find the location of my_test.dart (or event the project root path), from which I could derive the locations of my files?
The text was updated successfully, but these errors were encountered: