//: The goal of layers is to make programs more easy to understand and more //: malleable, easy to rewrite in radical ways without accidentally breaking //: some corner case. Tests further both goals. They help understandability by //: letting one make small changes and get feedback. What if I wrote this line //: like so? What if I removed this function call, is it really necessary? //: Just try it, see if the tests pass. Want to explore rewriting this bit in //: this way? Tests put many refactorings on a firmer footing. //: //: But the usual way we write tests seems incomplete. Refactorings tend to //: work in the small, but don't help with changes to function boundaries. If //: you want to extract a new function you have to manually test-drive it to //: create tests for it. If you want to inline a function its tests are no //: longer valid. In both cases you end up having to reorganize code as well as //: tests, an error-prone activity. //: //: In response, this layer introduces the notion of domain-driven *white-box* //: testing. We focus on the domain of inputs the whole program needs to //: handle rather than the correctness of individual functions. All white-box //: tests invoke the program in a single way: by calling run() with some //: input. As the program operates on the input, it traces out a list of //: _facts_ deduced about the domain: //: trace("label") << "fact 1: " << val; //: //: Tests can now check for these facts in the trace: //: CHECK_TRACE_CONTENTS("label", "fact 1: 34\n" //: "fact 2: 35\n"); //: //: Since we never call anything but the run() function directly, we never have //: to rewrite the tests when we reorganize the internals of the program. We //: just have to make sure our rewrite deduces the same facts about the domain, //: and that's something we're going to have to do anyway. //: //: To avoid the combinatorial explosion of integration tests, each layer //: mainly logs facts to the trace with a common *label*. All tests in a layer //: tend to check facts with this label. Validating the facts logged with a //: specific label is like calling functions of that layer directly. //: //: To build robust tests, trace facts about your domain rather than details of //: how you computed them. //: //: More details: http://akkartik.name/blog/tracing-tests //: //: --- //: //: Between layers and domain-driven testing, programming starts to look like a //: fundamentally different activity. Instead of focusing on a) superficial, //: b) local rules on c) code [like say http://blog.bbv.ch/2013/06/05/clean-code-cheat-sheet], //: we allow programmers to engage with the a) deep, b) global structure of //: the c) domain. If you can systematically track discontinuities in the //: domain, you don't care if the code used gotos as long as it passed all //: tests. If tests become more robust to run, it becomes easier to try out //: radically different implementations for the same program. If code is //: super-easy to rewrite, it becomes less important what indentation style it //: uses, or that the objects are appropriately encapsulated, or that the //: functions are referentially transparent. //: //: Instead of plumbing, programming becomes building and gradually refining a //: map of the environment the program must operate under. Whether a program //: is 'correct' at a given point in time is a red herring; what matters is //: avoiding regression by monotonically nailing down the more 'eventful' //: parts of the terrain. It helps readers new and old, and rewards curiosity, //: to organize large programs in self-similar hierarchies of example tests //: colocated with the code that makes them work. //: //: "Programming properly should be regarded as an activity by which //: programmers form a mental model, rather than as production of a program." //: -- Peter Naur (http://akkartik.name/naur.pdf) //:: == Core data structures :(before "End Globals") trace_stream* Trace_stream = NULL; :(before "End Types") struct trace_stream { vector past_lines; // End trace_stream Fields trace_stream() { // End trace_stream Constructor } ~trace_stream() { // End trace_stream Destructor } // End trace_stream Methods }; //:: == Adding to the trace //: Top-level method is trace() which can be used like an ostream. Usage: //: trace(depth, label) << ... << end(); //: Don't forget the 'end()' to actually append to the trace. :(before "End Includes") // No brackets around the expansion so that it prints nothing if Trace_stream // isn't initialized. #define trace(...) !Trace_stream ? cerr : Trace_stream->stream(__VA_ARGS__) :(before "End trace_stream Fields") // accumulator for current trace_line ostringstream* curr_stream; string curr_label; int curr_depth; // other stuff int collect_depth; // avoid tracing lower levels for speed ofstream null_stream; // never opened, so writes to it silently fail //: Some constants. :(before "struct trace_stream") // include constants in all cleaved compilation units const int Max_depth = 9999; :(before "End trace_stream Constructor") curr_stream = NULL; curr_depth = Max_depth; collect_depth = Max_depth; :(before "struct trace_stream") struct trace_line { string contents; string label; int depth; // 0 is 'sea level'; positive integers are progressively 'deeper' and lower level trace_line(string c, string l) { contents = c; label = l; depth = 0; } trace_line(string c, string l, int d) { contents = c; label = l; depth = d; } }; string unescape_newline(string& s) { std::stringstream ss; for (int i = 0; i < SIZE(s); ++i) { if (s.at(i) == '\n') ss << "\\n"; else ss << s.at(i); } return ss.str(); } void dump_trace_line(ostream& s, trace_line& t) { s << std::setw(2) << t.depth << ' ' << t.label << ": " << unescape_newline(t.contents) << '\n'; } //: Starting a new trace line. :(before "End trace_stream Methods") ostream& stream(string label) { return stream(Max_depth, label); } ostream& stream(int depth, string label) { if (depth > collect_depth) return null_stream; curr_stream = new ostringstream; curr_label = label; curr_depth = depth; (*curr_stream) << std::hex; // printing addresses is the common case return *curr_
if __name__ == '__main__': from __init__ import init; init()

from os.path import realpath, join, dirname

from ranger import fsobject
from ranger.fsobject.file import File
from ranger.fsobject.directory import Directory
from ranger.shared.settings import SettingsAware

SettingsAware._setup()

TESTDIR = realpath(join(dirname(__file__), 'testdir'))
TESTFILE = join(TESTDIR, 'testfile5234148')
NONEXISTANT_DIR = join(TESTDIR, 'nonexistant')

import unittest
class Test1(unittest.TestCase):
	def test_initial_condition(self):
		# Check for the expected initial condition
		dir = Directory(TESTDIR)

		self.assertEqual(dir.path, TESTDIR)
		self.assertFalse(dir.content_loaded)
		self.assertEqual(dir.filenames, None)
		self.assertEqual(dir.files, None)
		self.assertRaises(fsobject.NotLoadedYet, len, dir)
		self.assertRaises(fsobject.NotLoadedYet, dir.__getitem__, 0)

	def test_after_content_loaded(self):
		import os
		# Check whether the directory has the correct list of filenames.
		dir = Directory(TESTDIR)
		dir.load_content()

		self.assertTrue(dir.exists)
		self.assertEqual(type(dir.filenames), list)

		# Get the filenames you expect it to have and sort both before
		# comparing. I don't expect any order after only loading the filenames.
		assumed_filenames = os.listdir(TESTDIR)
		assumed_filenames = list(map(lam