I'm on a project interacting with files, and I would like to use text files to test my work. However tests aren't run from the tests/ directory, and thus I cannot reliably find them when running cargo run.
Does Cargo handle this by always running test from the root directory (which seems to be the case but I didn't find anything attesting it)?
The environment variable CARGO_MANIFEST_DIR can give you a stable base point to reference other files. Here, we assume that there's a resources/test directory at the top level of the crate:
use std::path::PathBuf;
fn main() {
let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
d.push("resources/test");
println!("{}", d.display());
}
See also:
How can a Rust program access metadata from its Cargo package?
Building on top of the answer provided by #Shepmaster, presuming you intend to read the files for testing:
macro_rules! test_case {($fname:expr) => (
concat!(env!("CARGO_MANIFEST_DIR"), "/resources/test/", $fname) // assumes Linux ('/')!
)}
which is simply used in your unit test like:
test_case!("json_data/example.json")
More or less accomplishes same goal but at compile-time (helpful for catching missing files) and fairly minimal. If someone knows how to make this compile-time and platform indepent - please feel welcome to edit.
See the full discussion in rust-lang issue #2841
Related
Suppose I have a type MyType with a private method (mt *MyType) private() in a package mypackage.
I also have a directory tests, where I want to store tests for my package. This is how tests/mypackage_test.go looks like:
package mypackage_test
import (
"testing"
"myproj/mypackage"
)
func TestPrivate(t *testing.T) {
// Some test code
}
However, when I run go test I get the cannot refer to unexported field or method my package.(*MyType)."".private) error. I've googled a bit and found out that functions starting with lower case can not be seen outside their own package (and this seems to be true, 'cause upper case functions are freely callable from the tests).
I also read somewhere that adding <...>_internal_test.go to the test file could solve my problem like this (tests/mypackage_internal_test.go):
package mypackage
import (
"testing"
)
func TestPrivate(t *testing.T) {
mt := &MyType{}
// Some test code
}
But with this I only get undefined: MyType. So, my question: how can I test internal/private methods?
Why do you place your tests in a different package? The go testing mechanism uses _test as a suffix for test files so you can place tests in the same packages as the actual code, avoiding the problem you describe. Placing tests in a separate package is not idiomatic Go. Do not try to fight the Go conventions, it's not worth the effort and you are mostly going to lose the fight.
Go insists that files in the same folder belong to the same package, that is except for _test.go files. Moving your test code out of the package allows you to write tests as though you were a real user of the package. You cannot fiddle around with the internals, instead you focus on the exposed interface and are always thinking about any noise that you might be adding to your API.
And:
If you do need to unit test some internals, create another file with _internal_test.go as the suffix. Internal tests will necessarily be more brittle than your interface tests — but they’re a great way to ensure internal components are behaving, and are especially useful if you do test-driven development.
Source: https://medium.com/#matryer/5-simple-tips-and-tricks-for-writing-unit-tests-in-golang-619653f90742
There are different opinions on how you should struct you tests within a golang project and I suggest you to read the blog above.
I'd like to make some changes to my copy of the rust standard library, then run the tests in the source files I changed. I do not need to test the compiler itself. How can I do this without testing a lot of things I am not changing and do not care about?
Here are some things I've already tried. A note - the specific file I want to play around with is libstd/io/net/pipes.rs in rust 0.12.0.
I tried rustc --test pipes.rs - the imports and options are not set up properly, it seems, and a multitude of errors is the result.
Following the rust test suite documentation, I tried make check-stage1-std NO_REBUILD=1, but this failed with "can't find crate for `green`". A person on the #rust-internals irc channel informed me that "make check-stage1 breaks semi-often as it's not the 'official way' to run tests."
Another person on that channel suggested make check-stage0-std, which seems to check libstd, but doesn't restrict testing to the file I changed, even if I use the TESTNAME flag as specified in the rust test suite documentation.
As of 2022 the way to run the test suite for the rust standard library is documented at https://rustc-dev-guide.rust-lang.org/tests/running.html .
While the documentation mentions the ability to test a single file it appears to malfunction
$ ./x.py test library/core/tests/str.rs
Updating only changed submodules
Submodules updated in 0.01 seconds
Building rustbuild
Finished dev [unoptimized] target(s) in 0.09s
thread 'main' panicked at 'error: no rules matched library/core/tests/str.rs', src/bootstrap/builder.rs:286:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Build completed unsuccessfully in 0:00:00
Later on it mentions a different syntax like ./x.py test library/alloc/ --test-args str which appears to succesfully run the unit tests in library/alloc/tests/str.rs
make check-stage1-std NO_REBUILD=1 or ... check-stage2-std ... should work, if you've done a full build previously. They just build the test runner directly without doing the rest of the bootstrap.
In any case, the full std test runner is built always, since, as you noticed, the imports etc are set up for the full crate. TESTNAME is the correct way to restrict which tests are run, but there's no way to restrict tests are built.
Another option is to pull the test/relevant code into an external file, and yet another is to build the test runner by running rustc manually on libstd/lib.rs: rustc --test lib.rs. One could edit the rest of the crate to remove the tests/code you're not interested in.
Currently, I define the following function in the REPL at the start of a coding session:
(defn rt []
(let [tns 'my.namespace-test]
(use tns :reload-all)
(cojure.test/test-ns tns)))
And everytime I make a change I rerun the tests:
user=>(rt)
That been working moderately well for me. When I remove a test, I have to restart the REPL and redefine the method which is a little annoying. Also I've heard bad rumblings about using the use function like this. So my questions are:
Is using use this way going to cause me a problem down the line?
Is there a more idiomatic workflow than what I'm currently doing?
most people run
lein test
form a different terminal. Which guarantees that what is in the files is what is tested not what is in your memory. Using reload-all can lead to false passes if you have changed a function name and are still calling the old name somewhere.
calling use like that is not a problem in it's self, it just constrains you to not have any name conflicts if you use more namespaces in your tests. So long as you have one, it's ok.
using lein lets you specify unit and integration tests and easily run them in groups using the test-selectors feature.
I also run tests in my REPL. I like doing this because I have more control over the tests and it's faster due to the JVM already running. However, like you said, it's easy to get in trouble. In order to clean things up, I suggest taking a look at tools.namespace.
In particular, you can use clojure.tools.namespace.repl/refresh to reload files that have changed in your live REPL. There's alsorefresh-all to reload all the files on the classpath.
I add tools.namespace to my :dev profile in my ~/.lein/profiles.clj so that I have it there for every project. Then when you run lein repl, it will be included on the classpath, but it wont leak into your project's proper dependencies.
Another thing I'll do when I'm working on a test is to require it into my REPL and run it manually. A test is just a no-argument function, so you can invoke them as such.
I am so far impressed with lein-midje
$ lein midje :autotest
Starts a clojure process watching src and test files, reloads the associated namespaces and runs the tests relevant to the changed file (tracking dependencies). I use it with VimShell to open a split buffer in vim and have both the source and the test file open as well. I write a change to either one and the (relevant) tests are executed in the split pane.
Is there a way to run an ant build such that you get an output of what the build would do, but without actually doing it?
That is to say, it would list all of the commands that would be submitted to the system, output the expansion of all filesets, etc.
When I've searched 'ant' and 'test', I get overwhelming hits for running tests with ant. Any suggestions on actually testing ant build files?
It seems, that you are looking for a "dry run".
I googled it a bit and found no evidence that this is supoorted.
Heres a bugzilla-request for that feature, that explains things a bit:
https://issues.apache.org/bugzilla/show_bug.cgi?id=35464
This is impossible in theory and in practice. In theory, you cannot test a program meaningfully without actually running it (basically the halting problem).
In practice, since individual ant tasks very often depend on each other's output, this would be quite pointless for the vast majority of Ant scripts. Most of them compile some source code and build JARs from the class files - but what would the fileset for the JAR contain if the compiler didn't actually run?
The proper way to test an Ant script is to run it regularly, but on a test system, possibly a VM image that you can restory to the original state easily.
Here's a problem: You have target #1 that builds a bunch of stuff, then target #2 that copies it.
You run your Ant script in test mode, it pretends to do target #1. Now it comes to target #2 and there's nothing to copy. What should target #2 return? Things can get even more confusing when you have if and unless clauses in your ant targets.
I know that Make has a command line parameter that tells it to run without doing a build, but I never found it all that useful. Maybe that's why Ant doesn't have one.
Ant does have a -k parameter to tell it to keep going if something failed. You might find that useful.
As Michael already said, that's what Test Systems - VM's come in handy- are for
From my ant bookmarks => some years ago some tool called "Virtual Ant" has been announced, i never tried it. So don't regard it as a tip but as something someone heard of
From what the site says =
"With Virtual Ant you no longer have to get your hands dirty with XML to create or edit Ant build scripts. Work in a completely virtualized environment similar to Windows Explorer and run your tasks on a Virtual File System to see what they do, in real time, without affecting your real file system*. The actual Ant build script is generated in the background."
Hm, sounds to good to be true ;-)
..without affecting your real file system.. might be what you asked for !?
They provide a 30day trial license so you won't lose no money but only the time to have a look on..
This is what I'm doing:
extract contents of my JRE's rt.jar
extract src.zip of my JDK (same version)
Now, if I copy Runtime.java from the extracted src folder and compile it using javac.exe without any modifications and then put it in the extracted rt folder to finally put everything back in a jar file using jar.exe, everything works as expected. The JRE runs fine.
However, if I make the slightest change to Runtime.java and compile it and put it in rt.jar, the JRE crashes whenever I attempt to start it. This is an example of a slight change that causes the silent crash:
/** Don't let anyone else instantiate this class */
private Runtime() {
System.out.println("This is a test.");
}
Instead of:
/** Don't let anyone else instantiate this class */
private Runtime() {}
Could anyone tell me why this is causing my JRE to crash?
Thanks in advance.
It's possible that System.out has not been initialised at the time that the Runtime() constructor runs. Usually console output is not considered a "slight" change, but at the wrong time it can invoke way too much stuff that may not be set up at all yet.
You're doing this all wrong. You can't distribute that modified JRE for a start, so it is only useful inside your organization . Install a SecurityManager and don't grant your codebase any of the RuntimePermissions you're trying to protect against.
#Tom - I advise you NOT to try to do this:
You cannot distribute the modified rt.jar file without violating the Sun binary license.
Even if you did, you would not be allowed to call it Java.
As you are finding, there are lots of complications that arise when you make changes, particularly when those changes might interfere with the JVM's behind the scenes initialization. And when things blow up during initialization, the JVM often cannot report the problem in an intelligible way.
If you do succeed in making the modified rt.jar work for one JRE, there is no guarantee that the same hacks will work for a different version.
Nobody in their right mind would knowingly use a modified JVM (especially one modified by a third-party) in a production app.
EDIT : judging from your other questions, I guess you are trying to reverse engineer or modify some third party Java application with a custom launcher. If you provided more information on what you were really trying to do, we might be able to suggest the right way to do it ... rather than using "desperate measures" such as modifying the JRE.
That's pretty strange, as I did the same trick with many classes in rt.jar in past.
Can you provide us with the crashed process output?