text:
Archive for the 'Testing' Category
Speeding up multi-browser Selenium Testing using concurrency
I haven't used Selenium for awhile, so I took some time to dig into the options to get some mainline tests running against Caliper in multiple browsers. I wanted to be able to test a variety of browsers against our staging server before pushing new releases. Eventually this could be integrated into Continuous Integration (CI) or Continuous Deployment (CD).
The state of Selenium testing for Rails is currently in flux:
- Selenium Core/IDE (integrated browser test runner) vs. Selenium RC
- Webdriver/Selenium 2.0
- Webrat and Capybara are merging
So there are multiple gems / frameworks:
- selenium-on-rails (Selenium IDE/Core test runner)
- selenium-client (Selenium RC)
- Webrat (uses selenium-client)
- Capybara (supports WebDriver / Selenium 2.0)
- and likely others…
I decided to investigate several options to determine which is the best approach for our tests.
I originally wrote a couple example tests using the selenium-on-rails plugin. This allows you to browse to your local development web server at '/selenium' and run tests in the browser using the Selenium test runner. It is simple and the most basic Selenium mode, but it obviously has limitations. It wasn't easy to run many different browsers using this plugin, or use with Selenium-RC, and the plugin was fairly dated. This lead me to try simplest next thing, selenium-client
open '/' assert_title 'Hosted Ruby/Rails metrics - Caliper' verify_text_present 'Recently Generated Metrics' click_and_wait "css=#projects a:contains('Projects')" verify_text_present 'Browse Projects' click_and_wait "css=#add-project a:contains('Add Project')" verify_text_present 'Add Project' type 'repo','git://github.com/sinatra/sinatra.git' click_and_wait "css=#submit-project" verify_text_present 'sinatra/sinatra' wait_for_element_present "css=#hotspots-summary" verify_text_present 'View full Hot Spots report'
I quickly converted my selenium-on-rails tests to selenium-client tests, with some small modifications. To run tests using selenium-client, you need to run a selenium-RC server. I setup Sauce RC on my machine and was ready to go. I configured the tests to run locally on a single browser (Firefox). Once that was working I wanted to run the same tests in multiple browsers. I found that it was easy to dynamically create a test for each browser type and run them using selenium-RC, but that it was increadly slow, since tests run one after another and not concurrently. Also, you need to install each browser (plus multiple versions) on your machine. This led me to use Sauce Labs' OnDemand.
browser.open '/' assert_equal 'Hosted Ruby/Rails metrics - Caliper', browser.title assert browser.text?('Recently Generated Metrics') browser.click "css=#projects a:contains('Projects')", :wait_for => :page assert browser.text?('Browse Projects') browser.click "css=#add-project a:contains('Add Project')", :wait_for => :page assert browser.text?('Add Project') browser.type 'repo','git://github.com/sinatra/sinatra.git' browser.click "css=#submit-project", :wait_for => :page assert browser.text?('sinatra/sinatra') browser.wait_for_element "css=#hotspots-summary" assert browser.text?('View full Hot Spots report')
Using Selenium-RC and Sauce Labs Concurrently
Running on all the browsers Sauce Labs offers (12) took 910 seconds. Which is cool, but way too slow, and since I am just running the same tests over in different browsers, I decided that it should be done concurrently. If you are running your own Selenium-RC server this will slow down a lot as your machine has to start and run all of the various browsers, so this approach isn't recommended on your own Selenium-RC setup, unless you configure Selenium-Grid. If you are using Sauce Labs, the tests run concurrently with no slow down. After switching to concurrently running my Selenium tests, run time went down to 70 seconds.
My main goal was to make it easy to write pretty standard tests a single time, but be able to change the number of browsers I ran them on and the server I targeted. One approach that has been offered explains how to setup Cucumber to run Selenium tests against multiple browsers. This basically runs the rake task over and over for each browser environment.
Althought this works, I also wanted to run all my tests concurrently. One option would be to concurrently run all of the Rake tasks and join the results. Joining the results is difficult to do cleanly or you end up outputting the full rake test output once per browser (ugly when running 12 times). I took a slightly different approach which just wraps any Selenium-based test in a run_in_browsers block. Depending on the options set, the code can run a single browser against your locally hosted application, or many browsers against a staging or production server. Then simply create a separate Rake task for each of the configurations you expect to use (against local selenium-RC and Sauce Labs on demand).
I am pretty happy with the solution I have for now. It is simple and fast and gives another layer of assurances that Caliper is running as expected. Adding additional tests is simple, as is integrating the solution into our CI stack. There are likely many ways to solve the concurrent selenium testing problem, but I was able to go from no Selenium tests to a fast multi-browser solution in about a day, which works for me. There are downsides to the approach, the error output isn't exactly the same when run concurrently, but it is pretty close. As opposed to seeing multiple errors for each test, you get a single error per test which includes the details about what browsers the error occurred on.
In the future I would recommend closely watching Webrat and Capybara which I would likely use to drive the Selenium tests. I think the eventual merge will lead to the best solution in terms of flexibility. At the moment Capybara doesn't support selenium-RC, and the tests I originally wrote didn't convert to the Webrat API as easily as directly to selenium-client (although setting up Webrat to use Selenium looks pretty simple). The example code given could likely be adapted easily to work with existing Webrat tests.
namespace :test do namespace :selenium do desc "selenium against staging server" task :staging do exec "bash -c 'SELENIUM_BROWSERS=all SELENIUM_RC_URL=saucelabs.com SELENIUM_URL=http://caliper-staging.heroku.com/ ruby test/acceptance/walkthrough.rb'" end desc "selenium against local server" task :local do exec "bash -c 'SELENIUM_BROWSERS=one SELENIUM_RC_URL=localhost SELENIUM_URL=http://localhost:3000/ ruby test/acceptance/walkthrough.rb'" end end end
require "rubygems" require "test/unit" gem "selenium-client", ">=1.2.16" require "selenium/client" require 'threadify' class ExampleTest 1 errors = [] browsers.threadify(browsers.length) do |browser_spec| begin run_browser(browser_spec, block) rescue => error type = browser_spec.match(/browser\": \"(.*)\", /)[1] version = browser_spec.match(/browser-version\": \"(.*)\",/)[1] errors < type, :version => version, :error => error} end end message = "" errors.each_with_index do |error, index| message +="\t[#{index+1}]: #{error[:error].message} occurred in #{error[:browser]}, version #{error[:version]}\n" end assert_equal 0, errors.length, "Expected zero failures or errors, but got #{errors.length}\n #{message}" else run_browser(browsers[0], block) end end def run_browser(browser_spec, block) browser = Selenium::Client::Driver.new( :host => selenium_rc_url, :port => 4444, :browser => browser_spec, :url => test_url, :timeout_in_second => 120) browser.start_new_browser_session begin block.call(browser) ensure browser.close_current_browser_session end end def test_basic_walkthrough run_in_all_browsers do |browser| browser.open '/' assert_equal 'Hosted Ruby/Rails metrics - Caliper', browser.title assert browser.text?('Recently Generated Metrics') browser.click "css=#projects a:contains('Projects')", :wait_for => :page assert browser.text?('Browse Projects') browser.click "css=#add-project a:contains('Add Project')", :wait_for => :page assert browser.text?('Add Project') browser.type 'repo','git://github.com/sinatra/sinatra.git' browser.click "css=#submit-project", :wait_for => :page assert browser.text?('sinatra/sinatra') browser.wait_for_element "css=#hotspots-summary" assert browser.text?('View full Hot Spots report') end end def test_generate_new_metrics run_in_all_browsers do |browser| browser.open '/' browser.click "css=#add-project a:contains('Add Project')", :wait_for => :page assert browser.text?('Add Project') browser.type 'repo','git://github.com/sinatra/sinatra.git' browser.click "css=#submit-project", :wait_for => :page assert browser.text?('sinatra/sinatra') browser.click "css=#fetch" browser.wait_for_page assert browser.text?('sinatra/sinatra') end end end
Improving Code using Metric_fu
Often, when people see code metrics they think, "that is interesting, I don't know what to do with it." I think metrics are great, but when you can really use them to improve your project's code, that makes them even more valuable. metric_fu provides a bunch of great metric information, which can be very useful. But if you don't know what parts of it are actionable it's merely interesting instead of useful.
One thing when looking at code metrics to keep in mind is that a single metric may not be as interesting. If you look at a metric trends over time it might help give you more meaningful information. Showing this trending information is one of our goals with Caliper. Metrics can be your friend watching over the project and like having a second set of eyes on how the code is progressing, alerting you to problem areas before they get out of control. Working with code over time, it can be hard to keep everything in your head (I know I can't). As the size of the code base increases it can be difficult to keep track of all the places where duplication or complexity is building up in the code. Addressing the problem areas as they are revealed by code metrics can keep them from getting out of hand, making future additions to the code easier.
I want to show how metrics can drive changes and improve the code base by working on a real project. I figured there was no better place to look than pointing metric_fu at our own devver.net website source and fixing up some of the most notable problem areas. We have had our backend code under metric_fu for awhile, but hadn't been following the metrics on our Merb code. This, along with some spiked features that ended up turning into Caliper, led to some areas getting a little out of control.
When going through metric_fu the first thing I wanted to start to work on was making the code a bit more DRY. The team and I were starting to notice a bit more duplication in the code than we liked. I brought up the Flay results for code duplication and found that four databases models shared some of the same methods.
Flay highlighted the duplication. Since we are planning on making some changes to how we handle timestamps soon, it seemed like a good place to start cleaning up. Below are the methods that existed in all four models. A third method 'update_time' existed in two of the four models.
def self.pad_num(number, max_digits = 15) "%%0%di" % max_digits % number.to_i end def get_time Time.at(self.time.to_i) end
Nearly all of our DB tables store time in a way that can be sorted with SimpleDB queries. We wanted to change our time to be stored as UTC in the ISO 8601 format. Before changing to the ISO format, it was easy to pull these methods into a helper module and include it in all the database models.
module TimeHelper module ClassMethods def pad_num(number, max_digits = 15) "%%0%di" % max_digits % number.to_i end end def get_time Time.at(self.time.to_i) end def update_time self.time = self.class.pad_num(Time.now.to_i) end end
Besides reducing the duplication across the DB models, it also made it much easier to include another time method update_time, which was in two of the DB models. This consolidated all the DB time logic into one file, so changing the time format to UTC ISO 8601 will be a snap. While this is a trivial example of a obvious refactoring it is easy to see how helper methods can often end up duplicated across classes. Flay can come in really handy at pointing out duplication that over time that can occur.
Flog gives a score showing how complex the measured code is. The higher the score the greater the complexity. The more complex code is the harder it is to read and it likely contains higher defect density. After removing some duplication from the DB models I found our worst database model based on Flog scores was our MetricsData model. It included an incredibly bad high flog score of 149 for a single method.
|Total score
|Average score
|Highest score
The method in question was extract_data_from_yaml, and after a little refactoring it was easy to make extract_data_from_yaml drop from a score of 149 to a series of smaller methods with the largest score being extract_flog_data! (33.6). The method was doing too much work and was frequently being changed. The method was extracting the data from 6 different metric tools and creating summary of the data.
The method went from a sprawling 42 lines of code to a cleaner and smaller method of 10 lines and a collection of helper methods that look something like the below code:
def self.extract_data_from_yaml(yml_metrics_data) metrics_data = Hash.new {|hash, key| hash[key] = {}} extract_flog_data!(metrics_data, yml_metrics_data) extract_flay_data!(metrics_data, yml_metrics_data) extract_reek_data!(metrics_data, yml_metrics_data) extract_roodi_data!(metrics_data, yml_metrics_data) extract_saikuro_data!(metrics_data, yml_metrics_data) extract_churn_data!(metrics_data, yml_metrics_data) metrics_data end def self.extract_flog_data!(metrics_data, yml_metrics_data) metrics_data[:flog][:description] = 'measures code complexity' metrics_data[:flog]["average method score"] = Devver::Maybe(yml_metrics_data)[:flog][:average].value(N_A) metrics_data[:flog]["total score"] = Devver::Maybe(yml_metrics_data)[:flog][:total].value(N_A) metrics_data[:flog]["worst file"] = Devver::Maybe(yml_metrics_data)[:flog][:pages].first[:path].fmap {|x| Pathname.new(x)}.value(N_A) end
Churn gives you an idea of files that might be in need of a refactoring. Often if a file is changing a lot it means that the code is doing too much, and would be more stable and reliable if broken up into smaller components. Looking through our churn results, it looks like we might need another layout to accommodate some of the different styles on the site. Another thing that jumps out is that both the TestStats and Caliper controller have fairly high churn. The Caliper controller has been growing fairly large as it has been doing double duty for user facing features and admin features, which should be split up. TestStats is admin controller code that also has been growing in size and should be split up into more isolated cases.
Churn gave me an idea of where might be worth focusing my effort. Diving in to the other metrics made it clear that the Caliper controller needed some attention.
The Flog, Reek, and Roodi Scores for Caliper Controller:
|Total score
|Average score
|Highest score
Roodi Report app/controllers/caliper.rb:34 - Method name "index" has a cyclomatic complexity is 14. It should be 8 or less. app/controllers/caliper.rb:38 - Rescue block should not be empty. app/controllers/caliper.rb:51 - Rescue block should not be empty. app/controllers/caliper.rb:77 - Rescue block should not be empty. app/controllers/caliper.rb:113 - Rescue block should not be empty. app/controllers/caliper.rb:149 - Rescue block should not be empty. app/controllers/caliper.rb:34 - Method name "index" has 36 lines. It should have 20 or less. Found 7 errors.
Roodi and Reek both tell you about design and readability problems in your code. The screenshot of our Reek 'code smells' in the Caliper controller should show how it had gotten out of hand. The code smells filled an entire browser page! Roodi similarly had many complaints about the Caliper controller. Flog was also showing the file was getting a bit more complex than it should be. After picking off some of the worst Roodi and Reek complaints and splitting up methods with high Flog scores, the code had become easily readable and understandable at a glance. In fact I nearly cut the Reek complaints in half for the controller.
Refactoring one controller, which had been quickly hacked together and growing out of control, brought it from a dizzying 203 LOC to 138 LOC. The metrics drove me to refactor long methods (52 LOC => 3 methods the largest being 23 LOC), rename unclear variable names (s => stat, p => project), move some helpers methods out of the controller into the helper class where they belong. Yes, all these refactorings and good code designs can be done without metrics, but it can be easy to overlook bad code smells when they start small, metrics can give you an early warning that a section of code is becoming unmanageable and likely prone to higher defect rates. The smaller file was a huge improvement in terms of cyclomatic complexity, LOC, code duplication, and more importantly, readability.
Obviously I think code metrics are cool, and that your projects can be improved by paying attention to them as part of the development lifecycle. I wrote about metric_fu so that anyone can try these metrics out on their projects. I think metric_fu is awesome, and my interest in Ruby tools is part of what drove us to build Caliper, which is really the easiest way try out metrics for your project. Currently, you can think of it as hosted metric_fu, but we are hoping to go even further and make the metrics clearly actionable to users.
In the end, yep, this is a bit of a plug for a product I helped build, but it is really because I think code metrics can be a great tool to help anyone with their development. So submit your repo in and give Caliper hosted Ruby metrics a shot. We are trying to make metrics more actionable and useful for all Ruby developers out, so we would love to here from you with any ideas about how to improve Caliper, please contact us.
Unit Testing Filesystem Interaction
Like most Rubyists, I write unit tests to verify the non-trivial parts of my code. I also try to use mocks and stubs to stub out interactions with systems external to my code, like network services.
For the most part, this works fine. But I've always struggled to find a good way to test interaction with the filesystem (which can often be non-trivial and therefore should be tested). On the one hand, the filesystem could be considered "external" and mocked out. But on the other hand, the filesystem is accessible when the tests run. In this way, the filesystem is sort of like a local database – it could be mocked out, but it doesn't have to be, and there are tradeoffs to both approaches.
Over the past year or so, I've tried out a few approaches for testing interactions with the filesystem, each of which I'll explain below. Since none of the approaches met my needs, Avdi and I built a new testing library, which I'll introduce below.
Mocking the file system.
Sometimes, it is simplest to just mock the interaction with the filesystem. This works well for single calls to methods like
(these examples use Mocha):
File.stubs(:read).returns("file contents") File.stubs(:exist?).returns(true)
However, this approach breaks down when you want to test more complex code, which, of course, is the code you're more likely to want to test thoroughly. For instance, imagine trying to set up mocks/stubs for the following method (which atomically rewrites the contents of a file):
require 'tempfile' class Rewriter def rewrite_file!(target_path) backup_path = target_path + '.bak' FileUtils.mv(target_path, backup_path) Tempfile.open(File.basename(target_path)) do |outfile| File.open(backup_path) do |infile| infile.each_line do |line| outfile.write(yield(line)) end end outfile.close FileUtils.cp(outfile.path, target_path) end rescue Exception if File.exist?(backup_path) FileUtils.mv(backup_path, target_path) end raise end end
Now imagine setting up those same mocks/stubs for each of the five or so tests you'd want to test that method. It gets messy.
Even more importantly, mocking/stubbing out methods ties your tests to a specific implementation. For instance, if you use the above stub (
File.stubs(:read).returns("file contents")
) in your test and then refactor your implementation to use, say,
, you'll have to update your tests. No good.
MockFS is a library that mocks out the entire filesystem. It allows you write test code like this:
require 'test/unit' require 'mockfs' class TestMoveLog < Test::Unit::TestCase def test_move_log # Set MockFS to use the mock file system MockFS.mock = true # Fill certain directories MockFS.fill_path '/var/log/httpd/' MockFS.fill_path '/home/francis/logs/' # Create the access log MockFS.file.open( '/var/log/httpd/access_log', File::CREAT ) do |f| f.puts "line 1 of the access log" end # Run the method under test move_log # Test that it was moved, along with its contents assert( MockFS.file.exist?( '/home/francis/logs/access_log' ) ) assert( !MockFS.file.exist?( '/var/log/httpd/access_log' ) ) contents = MockFS.file.open( '/home/francis/logs/access_log' ) do |f| f.gets( nil ) end assert_equal( "line 1 of the access log\n", contents ) end end
Although I suspect MockFS would be a great fit for some projects, I ended up running into issues.
First of all, it depends on a library (extensions) that can have strange monkey-patching conflicts with other libraries. For example, compare this:
require 'faker' puts [].respond_to?(:shuffle) # true
to this:
require 'extensions/all' require 'faker' puts [].respond_to?(:shuffle) # false
Secondly, as you'll notice in the above example, using MockFS requires you to use methods like
instead of just
. This works fine if you're only testing your own code. However, if your code calls any libraries that use filesystem methods, MockFS won't work.
(Note: There is a way to mock out the default filesystem methods, but it's experimental. From the MockFS documentation:
"Reading the testing example above, you may be struck by one thing: Using MockFS requires you to remember to reference it everywhere, making calls such as MockFS.file_utils.mv instead of just FileUtils.mv. As another option, you can use File, FileUtils, and Dir directly, and then in your tests, substitute them by including mockfs/override.rb. I'd recommend using these with caution; substituting these low-level classes can have unpredictable results. ")
All that said, MockFS is probably your best option if you're only testing your code and you want to mock out files that you can't actually interact with – for instance, if you need to test that a method reads/writes a file in
(although for the sake of testability, it's generally good to avoid hardcoding fully-qualified paths in your code).
FakeFS is another library that uses this approach. I haven't used it personally, but it looks quite nice.
Creating temp files and directories (with Construct)
Besides mocking the filesystem, another option is to have tests interact with actual files and directories on disk. The advantages are that the test code can be simpler to write and you don't have to use any special filesystem methods.
Of course, as always, you want the test itself to contain all the relevant setup and teardown – you don't want your tests to depend upon some set of files that have no explicit connection to the test itself (or create files that aren't cleaned up).
To make this easy, we created a new library called Construct. Construct makes test setup simple by providing helpers to create temporary files and directories. It takes care of the cleanup by automatically deleting the directories and files that are created within the test. And because it creates regular files and directories, you can use plain old Ruby filesystem methods in your code and tests.
To install Construct, simply run:
# gem install devver-construct --source http://gems.github.com
Using Construct, you can write code like this:
require 'construct' class ExampleTest < Test::Unit::TestCase include Construct::Helpers def test_example within_construct do |construct| construct.directory 'alice/rabbithole' do |dir| dir.file 'white_rabbit.txt', "I'm late!" assert_equal "I'm late!", File.read('white_rabbit.txt') end end end end
Let's look at each line in more detail.
within_construct do |construct|
When you call
, a temporary directory is created. All files and directories are, by default, created within that temporary directory and the temporary directory is always deleted before
The block argument (
) is a Pathname object with some additional methods (
, which I'll explain below). You can use this object to get the path to the temporary directory created by Construct and easily create files and directories.
Note that, by default, the working directory is changed to the temp dir within the block provided to
construct.directory 'alice/rabbithole' do |dir|
Here we are using the
object to create a new directory within the temp directory. As you can see, you can create nested directories like
in one step. The block argument (
) is again a Pathname object with the same added functionality noted above.
Just like before, the working directory is changed to the newly created directory (in this case,
) within the block.
dir.file 'white_rabbit.txt', "I'm late!"
Here we use the
object to create a file. In this case, the file will be empty. However, it's easy to provide file contents using either an optional parameter or the return value of the supplied block:
within_construct do |construct| construct.file('foo.txt','Here is some content') construct.file('bar.txt') do <<-EOS The block will return this string, which will be used as the content. EOS end end
As a more real-world example, here's how you could use Construct to start testing the
method we looked at before:
require 'test/unit' require 'construct' require 'shoulda' class RewriterTest < Test::Unit::TestCase include Construct::Helpers context "#rewrite_file!" do should "alter each line in file" do within_construct do |c| c.file('bar/foo.txt',"a\nb\nc\n") Rewriter.new.rewrite_file!('bar/foo.txt') do |line| line.upcase end assert_equal "A\nB\nC\n", File.read('bar/foo.txt') end end should "not alter file if exception is raised" do within_construct do |c| c.file('foo.txt', "1\n2\nX\n") assert_raises ArgumentError do Rewriter.new.rewrite_file!('foo.txt') do |line| Integer(line)*2 end end assert_equal "1\n2\nX\n", File.read('foo.txt') end end end end
You can learn more at the project page (both the README and the tests have more examples).
(As an aside, since Construct changes the working directory, it doesn't play nicely with
. Specifically, if you place a breakpoint within a block, you'll see the message "No sourcefile available for test/unit/foo_test.rb" and you won't be able to view the source. If anyone knows an easy way to make
work with
, I'd very much appreciate some help!)
We've been moving our filesystem tests over to using Construct and so far have found it to be very useful. How do you test interactions with the filesystem? Do you use one of the above approaches, or something else? Or do you skip testing the filesystem altogether?
Devver adds Postgres and SQLite database support
We are working hard to quickly expand our compatibility on Ruby projects. With that goal driving us, we are happy to announce support for Postgres and SQLite databases. With the addition of these database options, along with our existing support for MySQL, Devver now supports all of the most popular databases commonly used with Ruby. These three databases are the default databases tested against ActiveRecord and we expect will cover the majority of the Ruby community.
To begin working with Postgres or SQLite on Devver all you need to do is have a database.yml with the test environment set to the adapter of your choice. If we don't support your favorite database, you can still request a beta invite and let us know which database you want us to support. If we just added support for your database, perhaps we can speed up your project on Devver, so request a beta invite.
Tracking down open files with lsof
The other day I was running in a weird error on Devver. After running around twenty test runs on the system, the component that actually runs individual unit tests was crashing due to "Too many open files – (Errno::EMFILE)"
Unfortunately, I didn't know much more than that. Which files were being kept open? I knew that this component loaded quite a few files, and that by default, OS X only allows 256 open file descriptors (
ulimit -n
will tell you the default on your system). If this was a valid case of needing to load more files, I could just up the limit using
ulimit -n <bigger_number>
Fortunately, a quick Google or two pointed the way to
. Unfortunately, my Unix-fu is never nearly as good as I wish and I didn't know much about this handy utility. But I quickly discovered that it's very useful for tracking down problems like this. I quickly used
to find the PID of the Devver process and then a quick
lsof -p <PID>
displayed all the files that the process had open. So easy!
Sure enough, there were a ton of redundant file handles to the file that we use to store information about the Devver run. Armed with this information, it was easy to find the buggy code where we called File.open but failed to ever close the file.
Unfortunately, I still don't know how to write a good unit test for this case. I guess I could do something ugly like call sytem("lsof -p pid | wc -l") before and after calling the code and make sure the number of descriptors stays constant, but that's really ugly. Is there a way to test this within Ruby? I'm open to ideas.
Still, it's always good to learn more about a powerful Unix tool. I'm constanly amazed by the power and depth of the Unit tool set.
Ruby Code Quality Tools
Update: Devver now offers a hosted metrics service for Ruby developers which can give you useful feedback about your code. Check out Caliper, to get started with metrics for your project.
This is the third post in my series of Ruby tools articles. This time I look at Ruby code quality tools. Rubyists like Ruby because the code can look so nice, simple, and sometimes beautiful. Unfortunately not all code is so great, in fact often the code I write doesn't look good. Fortunately while a great language can help you to write great code, great tools can help as well. As code grows it is easy for code bloat, dead code, or confusing complexities to slip in. The tools I review below can help with all of these problems. I recommend finding the one or two code quality tools you like best and starting to integrate them more into your development process.
Roodi gives you a bunch of interesting warnings about your Ruby code. We are about to release some code, so I took the opportunity to fix up anything Roodi complained about. It helped identify refactoring opportunities, both with long methods, and overly complex methods. The code and tests became cleaner and more granular after breaking some of the methods down. I even found and fixed one silly performance issue that was easy to see after refactoring, which improved the speed of our code. Spending some time with Roodi looks like it could easily improve the quality and readability of most Ruby projects with very little effort. I didn't solve every problem because in one case I just didn't think the method could be simplified anymore, but the majority of the suggestions were right on. Below is an example session with Roodi
dmayer$ sudo gem install roodi dmayer$ roodi lib/client/syncer.rb lib/client/syncer.rb:136 - Block cyclomatic complexity is 5. It should be 4 or less. lib/client/syncer.rb:61 - Method name "excluded" has a cyclomatic complexity is 10. It should be 8 or less. lib/client/syncer.rb:101 - Method name "should_be_excluded?" has a cyclomatic complexity is 9. It should be 8 or less. lib/client/syncer.rb:132 - Method name "find_changed_files" has a cyclomatic complexity is 10. It should be 8 or less. lib/client/syncer.rb:68 - Rescue block should not be empty. lib/client/syncer.rb:61 - Method name "excluded" has 25 lines. It should have 20 or less. lib/client/syncer.rb:132 - Method name "find_changed_files" has 27 lines. It should have 20 or less. Found 7 errors.
After Refactoring:
~/projects/gridtest/trunk dmayer$ roodi lib/client/syncer.rb lib/client/syncer.rb:148 - Block cyclomatic complexity is 5. It should be 4 or less. lib/client/syncer.rb:82 - Rescue block should not be empty. Found 2 errors.
I did have one problem with Roodi – the errors about rescue blocks just seemed to be incorrect. For code like the little example below it kept throwing the error even though I obviously am doing some work in the rescue code.
Roodi output: lib/client/syncer.rb:68 - Rescue block should not be empty. begin socket = TCPSocket.new(server_ip,server_port) socket.close return true rescue Errno::ECONNREFUSED return false end
Dust detects unused code like unused variables,branches, and blocks. I look forward to see how the project progresses. Right now there doesn't seem to be much out there on the web, and the README is pretty bare bones. Once you can pass it some files to scan, I think this will be something really useful. For now I didn't think there wasn't much I could actually do besides check it out. Kevin, who also helped create the very cool Heckle, does claim that code scanning is coming soon, so I look forward to doing a more detailed write up eventually.
Flog gives feedback about the quality of your code by scoring code using the ABC metric. Using Flog to help guide refactoring, code cleanup, and testing efforts can be highly effective. It is a little easier to understand the reports after reading how Flog scores your code, and what is a good Flog score. Once you get used to working with Flog you will likely want to run it often against your whole project after making any significant changes. There are two easy ways to do this a handy Flog Rake task or MetricFu which works with both Flog and Saikuro.
Running Flog against any subset of a project is easy, here I am running it against our client libraries
find ./lib/client/ -name \*.rb | xargs flog -n -m > flog.log
Here some example Flog output when run against our client code.
Total score = 1364.52395469781 Client#send_tests: (64.3) 14.3: assignment 13.9: puts 10.7: branch 10.5: send 4.7: send_quit 3.4: message 3.4: now 2.0: create_queue_test_msg 1.9: create_run_msg 1.9: test_files 1.8: dump 1.7: each 1.7: report_start 1.7: length 1.7: get_tests 1.7: - 1.7: open 1.7: load_file 1.6: empty? 1.6: nil? 1.6: use_cache 1.6: exists? ModClient#send_file: (32.0) 12.4: branch 5.4: + 4.3: assignment 3.9: send 3.1: puts 2.9: == 2.9: exists? 2.9: directory? 1.9: strftime 1.8: to_s 1.5: read 1.5: create_file_msg 1.4: info Syncer#sync: (30.8) 13.2: assignment 8.6: branch 3.6: inspect 3.2: info 3.0: puts 2.8: + 2.6: empty? 1.7: map 1.5: now 1.5: length 1.4: send_files 1.3: max 1.3: > 1.3: find_changed_files 1.3: write_sync_time Syncer#find_changed_files: (26.2) 15.6: assignment 8.7: branch 3.5: << 1.8: to_s 1.7: get_relative_path 1.7: > 1.7: mtime 1.6: exists? 1.6: == 1.5: prune 1.4: should_be_excluded? 1.3: get_removed_files 1.3: find ... and so on ...
Saikuro is another code complexity tool. It seems to give a little less information than some of the others. It does generate nice HTML reports. Like other code complexity tools it can be helpful to discover the most complex parts of your projects for refactoring and to help focus your testing. I liked the way Flog broke things down for me into a bit more detail, but either is a useful tool and I am sure it is a matter of preference depending on what you are looking for.
Ruby Test Quality Tools
Update: Devver now offers a hosted metrics service for Ruby developers which can give you useful feedback about your code. Check out Caliper, to get started with metrics for your project.
This is the second post in my series of Ruby tools articles. This time I am focused on Ruby test quality tools. Devver is always really interested in testing, and obviously the quality of a project's tests is important. We are always looking at ways to add even more value to the investment teams put in with testing. Simply knowing that you are writing higher quality tests helps increase the value returned on the time invested in testing. I haven't found many tools to help with test quality, but these tools are a great help to any Ruby tester.
Heckle is an interesting tool to do mutation testing of your tests. Heckle currently supports Test:Unit and RSpec, but does have a number of issues. I had to run it on a few different files and methods before I got some useful output that helped me improve my testing. The first problem was it crashing when I passed it entire files (crashing the majority of the time). I then began passing it single methods I was curious about, which still occasionally caused Heckle to get into an infinite loop case. This is a noted problem in Heckle, but -T and providing a timeout should solve that issue. In my case it was actually not an infinite loop timing error, but an error when attempting to rewrite the code, which lead to a continual failure loop that wouldn't time out. When I found a class and method that Heckle could test I got some good results. I found one badly written test case, and one case that was never tested. Lets run through a simple Heckle example.
#install heckle dmayer$ sudo gem install heckle #example of the infinite loop Error Heckle run heckle Syncer should_be_excluded? --tests test/unit/client/syncer_test.rb -v Setting timeout at 5 seconds. Initial tests pass. Let's rumble. ********************************************************************** *** Syncer#should_be_excluded? loaded with 13 possible mutations ********************************************************************** ... 2 mutations remaining... Replacing Syncer#should_be_excluded? with: 2 mutations remaining... Replacing Syncer#should_be_excluded? with: ... loops forever ... #Heckle run against our Client class and the process method dmayer$ heckle Client process --tests test/unit/client/client_test.rb Initial tests pass. Let's rumble. ********************************************************************** *** Client#process loaded with 9 possible mutations ********************************************************************** 9 mutations remaining... 8 mutations remaining... 7 mutations remaining... 6 mutations remaining... 5 mutations remaining... 4 mutations remaining... 3 mutations remaining... 2 mutations remaining... 1 mutations remaining... The following mutations didn't cause test failures: --- original +++ mutation def process(command) case command when @buffer.Ready then process_ready - when @buffer.SetID then + when nil then process_set_id(command) when @buffer.InitProject then process_init_project when @buffer.Result then process_result(command) when @buffer.Goodbye then kill_event_loop when @buffer.Done then process_done when @buffer.Error then process_error(command) else @log.error("client ignoring invalid command #{command}") if @log end end --- original +++ mutation def process(command) case command when @buffer.Ready then process_ready when @buffer.SetID then process_set_id(command) when @buffer.InitProject then process_init_project when @buffer.Result then process_result(command) when @buffer.Goodbye then kill_event_loop when @buffer.Done then process_done when @buffer.Error then process_error(command) else - @log.error("client ignoring invalid command #{command}") if @log + nil if @log end end Heckle Results: Passed : 0 Failed : 1 Thick Skin: 0 Improve the tests and try again. #Tests added / changed to improve Heckle resultsdef test_process_process_loop__random_result Client.any_instance.expects(:start_tls).returns(true) client = Client.new({}) client.stubs(:send_data) client.log = stub_everything client.log.expects(:error).with("client ignoring invalid command this is random") client.process("this is random") end def test_process_process_loop__set_id Client.any_instance.expects(:start_tls).returns(true) client = Client.new({}) client.stubs(:send_data) client.log = stub_everything cmd = DataBuffer.new.create_set_ids_msg("4") client.expects(:process_set_id).with(cmd) client.process(cmd) end
#A final Heckle run, showing successful results
dmayer$ heckle Client process --tests test/unit/client/client_test.rb
Initial tests pass. Let's rumble.
*** Client#process loaded with 9 possible mutations
9 mutations remaining...
8 mutations remaining...
7 mutations remaining...
6 mutations remaining...
5 mutations remaining...
4 mutations remaining...
3 mutations remaining...
2 mutations remaining...
1 mutations remaining...
No mutants survived. Cool!
Heckle Results:
Passed : 1
Failed : 0
Thick Skin: 0
All heckling was thwarted! YAY!!!
rcov is a code coverage tool for Ruby. If you are doing testing you should probably be monitoring your coverage with a code coverage tool. I don't know of a better tool for code coverage than rcov. It is simple to use and generates beautiful, easy-to-read HTML charts showing the current coverage broken down by file. An easy way to make you project more stable is to occasionally spend some time increasing the coverage you have on your project. I have always found it a great way to get back into a project if you have been off of it for awhile. You just need to find some weak coverage points and get to work.
rcov screenshot


text:
The financial services industry is undergoing transformative change in everything from administrative policy and investor expectations to automated technology and data analysis. Some developments promise positive momentum and others threaten damaging fallout for firms, but all of them present opportunities to shape a public image through media relations. If you're a firm trying to build your brand by attracting favorable attention, here are a few tips to keep in mind when communicating with reporters:
Avoid subjective/general descriptors.
Although your firm may have "high-quality" products and "experienced" investment professionals, these details hold little value for reporters trying to make objective comparisons across a vast and competitive industry. Use numbers when pitching stories—plot annual assets to show company growth and chart returns to show competitive performance. Extract the most relevant work history details from your portfolio managers or key leaders to demonstrate how your experience gives you an advantage.
Break it down.
Explain complicated topics in layman's terms. Reporters are likely to be more drawn to stories they understand well. Don't assume the reporter understands how a derivative works, or what the relationship is between mezzanine debt and a leveraged buyout. Explain concepts on a granular level, but remember to also explain how they fit into the larger financial services landscape. Consider bringing to the interview an outline or summary of your expected comments the reporter can keep, especially if the story must be turned around on a tight deadline.
Be colorful.
Analogies and lively quotes that evoke images and reveal personality will set you apart in financial services. They are rare, but even the more specialized trade publications want exciting copy. They want quotes that are succinct, but also colorful. Most readers or viewers won't remember the portfolio manager detailing the mechanics of a fund, but they will remember the one who drew an analogy between a fund's harvesting strategy and pigs eating at a trough.
Related: Got Bad News? How to Communicate When You Do
Humanize the story.
Reporters don't just hunt for stories, they seek people who can illustrate stories through personal experiences. They love anecdotes and narratives that reveal emotion, and often rely on them to breathe new life into second-day breaking news stories. While the issue may not be new, the way you relate the story might be. Explaining the necessity of implementing a good tax and estate plan is one story. An attorney who explains that through the eyes of a recently widowed client who failed to implement that plan is another story.

subset: commoncrawl


text:
I'm pretty into a {new to me} recipe blog called This Week for Dinner. The sandwich above, called the Rachel {sister to the Reuben} looks pretty tasty.Get good bread - wheat or white (I don't love rye but Reuben would be happy if you used it - the deli I mentioned always used white).
'Schmear' two slices with Thousand Island dressing.Top with swiss cheese, turkey slices and coleslaw.
Grill on the stove with a bit of butter on both sides.Enjoy {with Kettle Chips, carrot sticks and Simply Lemonade...Included this.}


text:
Tsukuba Marathon
The 26th Tsukuba Marathon is on this Sunday, 26 November 2006.
Start 42 km run: 9:30am
Start 10 km run: 10:10am
The roads in Tsukuba University will be blocked (closed) for the marathon, so try to avoid Tsukuba Uni on Sunday!
If you want to participate in the marathon next year, remember to check the website and apply by October 2007. You can apply through the website or at the university sports center.
Tsukuba Marathon website
Map of the marathon course
Source: TAIRA


text:
I received a letter yesterday. It was from a deliberately untraceable origin: a generic distribution centre in Toronto.
The return address was written in a spidery, nearly unintelligible script, as if by a crazed scholar or antiquarian. It felt rushed and desperate.
Inside was another envelope. This one was more tattered, beaten up and dirty. It had a dusty, musty brown stain on it that smelled faintly of cinnamon. I'm getting a little worried here as I see my name written in the same decrepit handwriting.
Upon opening it, I found that it had been stuffed with a printed letter (water stained) and four small sheafs of paper; excerpts from a novel, it seemed.
The letter explained that due to governmental and institutional censorship of literature, someone was trying to preserve a forbidden, controversial work by spreading parts of it throughout to world (like seeds… shudder).
His or her signature was completely destroyed by a water stain:
I dared to read the texts. I felt an exhilarating shudder as I saw the title of the play: The King in Yellow. I knew of this blasphemous play and of how it ruined lives. If it really existed, it deserved to be banned!
I could not help myself. I read all of the excerpts, feeling excitement and dread.
Somehow, someone out there knows of my fascination with The Yellow King, Hastur, as well as with the famous Mythos spawned from Azathoth and it's high Priest in R'lyeh.
How? Is it because I have friends out there on many forums and circles? I've spoken of dreaded Carcosa before on my blog. I'm both honoured and worried that I've been targeted by this mad, desperate scholar.
Carcosa. This isn't some fun, geek fandom thing. This play destroys life, ruins minds. I both thank and curse whoever found me out and targetted me. My life- no, worse, my soul- is set upon a course that I can no longer understand. I may be doomed.
Stay tuned… Please my readers… I don't know where this may go…
Pity me!


text:
If you have acquired substantial knowledge in a specific subject area, you may consider an exam as a substitute for completing the usual classroom requirements of a course.
College Level Examination Program (CLEP)
Administered by the College Board, CLEP provides college credit for examinations that test college-level knowledge in specific disciplines. Work with your adviser to see if a CLEP exam fulfills a degree requirement. CLEP centers are conveniently located on or near several Penn State campuses across the state.
CLEP for Military and Veterans
DANTES Subject Standardized Test (DSST)
DSST exams may provide additional coursework credits for your program of study, depending on your major. Work with your adviser to review the possibilities.
Credit by Exam with Penn State
Some academic departments and programs have made these exams available. Contact your adviser to start the process. The links below explain other rules about grading, not taking an exam if you've already taken the course, and completing forms. A $30/per credit fee is charged, regardless of final grade. The examples below are not the only exams available but have links for you to reference.
Getting Started with Credit by Exam
Prior Learning Assessment Application Form
- Calculus (University Park)
- Chemistry (University Park)
- Energy and Sustainability Policy
- English 015: Contact Lynn Setzler firstname.lastname@example.com/814-863-3066
- Foreign Languages (University Park)
- Mathematics (Harrisburg): contact your adviser
- NURS 251 (Altoona)


text:
Tuesday, January 10, 2006
8 comments:
- Elliot Cowan said...
Yes, Kong is quite remarkable.
That's a real monkey up there on screen.
I lived in my hometown of Melbourne for 22 years, and have been returning regularly in the 9 years since.
I can remember no time when the skyline there was not punctuated with cranes...
- 11:52 pm GMT
- alberto mielgo said...
If you just look at the colors, you forget what it is, and it become Beauty!.How is posible?
I love it.
- 1:32 pm GMT
- Oscar Grillo said...
- This comment has been removed by a blog administrator.
- 4:09 pm GMT
- Oscar Grillo said...
Dear Limbó.
If it wasn't that today I am in a lousy mood I would write something funny about London's blue sky.
-All the best.
PS...Have you seen the Rousseau's exhibition at the Tate Modern..Is wonderful!!!
- 4:11 pm GMT
- limbolo said...
The Rousseau is just below the cranes...
Yes...is wonderful!!!
- 8:07 pm GMT
- Oscar Grillo said...
Am I crazy or this picture is moving away from the text more and more every day?
- 4:43 pm GMT
- limbolo said...
No, I think it must be you that's moving further away everyday, Oscar.
- 9:51 am GMT
- Oscar Grillo said...
Astigmatism...I see the world like a Delaunay painting
- 4:01 am GMT


text:
Audi will soon be joining the list of manufacturers, such as Jaguar and Renault, to have a Formula E team. The German marque has recently completed their works status by finalizing the takeover of the Abt Schaeffler team. With the current season still on-going, the Abt group will continue to use the same name. Beginning next season however, the team will run under the Audi Sport Abt Schaeffler banner.
"We've been supporting the Formula E commitment with increasing intensity in recent months – on the race days, in the development of the new powertrain and in numerous off-track activities as well," said Dr. Peter Martens, an Audi board member.
Following the takeover, Audi will be the first German automobile manufacturer to join the all-electric series. Audi previously had a partnership deal with the Abt team, but has been increasing their involvement with the group until the recent takeover. Following the takeover, the Abt team will still remain active and will handle tasks such as maintenance of the racecars. Audi meanwhile will be handling the technical development.
"We're proud that as one of the founding members we've added a chapter to motorsport's history books. Within the space of just a few years, Formula E has seen such a strong development that a team can no longer be competitive without the backing of an automobile manufacturer," said Hans-Jurgen Abt, Abt team owner.
The Abt team is known for winning the first ever Formula E race back in 2014 with driver Lucas di Grassi. Since then, they have come close to winning two titles, but have always evaded them. This season, the team is currently running 2nd in the constructor's championship, with di Grassi currently in 2nd place in overall driver standings. Beginning next season, it is believed di Grassi will retain his seat. His teammate, Daniel Abt's seat is still unknown, but is said to likely be extended.
Season 4 of Formula E takes place in Hong Kong on December 4, where we will see Audi's debut in the all-electric series.


text:
In the stage illumination industry, LED technology is promising both in terms of energy use and novel features, but it also has inherent issues. This paper presents a solution to the poor color homogeneity arising when multiple rectangular images formed from LED dies are combined into a circular spot profile. Using ray tracing, a nonrotationally symmetric collimating lens was optimized to round off such die images. The result is a high-output lens with an almost perfectly circular spot. In a simulated red green blue color mixing projector with seven LEDs, the lens reduced measurable color inhomogeneity by , with a 5.3% luminous gain, compared to the best rotationally symmetric benchmark lens.
© 2011 Optical Society of AmericaFull Article | PDF Article
OSA Recommended Articles
Jesper Gadegaard, Thøger Kari Jensen, Dennis Thykjær Jørgensen, Peter Kjær Kristensen, Thomas Søndergaard, Thomas Garm Pedersen, and Kjeld Pedersen
Appl. Opt. 55(6) 1356-1365 (2016)
Wen-Shing Sun, Chuen-Lin Tien, Chao-Hui Ma, and Jui-Wen Pan
Appl. Opt. 53(29) H227-H232 (2014)
Shuang Zhao, Kai Wang, Fei Chen, Zong Qin, and Sheng Liu
Appl. Opt. 52(13) 2985-2993 (2013)


text: Home / Adidas T16 Team Youth Track Polo Tee Red Adidas T16 Team Youth Track Polo Tee Red £11.20 RRP: £22.40 You save £11.20 that's 50% off! Stock Status: In Stock Size: XS S M L XL 2XL Information Product Code:SSS-ADI-AJ5247power red / whiteRecycled fabrics: Made with environmentally advanced materialsIntegrated name tag for player IDFree space on front and back for easy embellishmentColour block inserts on the lower front, back and sleeve cuffsFit: Regular100% rec.Polyester Specifications Product Code: SSS-ADI-AJ5247-6Y Reviews Not yet reviewed Write an online review and share your thoughts with other shoppers! Be the first to review this product


text:
Michel-Richard de Lalande
Aliases: Delalande, Michel Richard; de La Lande, Michel Richard; La Lande, Michel Richard de
Born: 15 December 1657
Died: 18 June 1726
Delalande is mainly associated with the grand motet and with Versailles where he is buried, but held posts in several Paris churches before becoming organist du Roi; his Leçons de Ténèbres (1711) were written for Ste-Chapelle. In all 77 grands motets, 9 élévations (S. 78-86), Miserere & O filii (with lost works S. 87-90), 16 extracted petits motets (after grands, S.91-106), 9 Leçons de ténèbres (S.107-124), Messe en plainchant musical (S.126) Cantique (Racine, S.127), Tandis que Babylone (S.128) & numerous stage works (opera, intermedes, cantates, ballets) and instrumental works. He wrote two versions of Super flumina Babilonis.
View the Wikipedia article on Michel-Richard de Lalande.
List of choral works
- Cantate Domino, S.55
- De profundis clamavi, S.23
- Laudate Dominum, S. 57
- Super flumina Babilonis, S.13
Click here to search for this composer on CPDL
- ms. Philidor et al. (27 grand motets, c. 1690)
- ms. Philidor for Ct. de Toulouse (11 motets, c. 1705)
- 40 Motets (engraved in short score, 1729-34)
- ms. Cauvin (41 grands motets in full score c. 1741)
External links
- Works by Michel-Richard de Lalande in the Petrucci Music Library (IMSLP)


text:
CTO, Quanticate
Nick began contributing to Apache projects in 2003, and hasn't looked back since! Most of the projects Nick has worked in belong in the "Content" space, such as Apache POI (ex-PMC Chair), Apache Tika and Apache Chemistry. As well as coding projects, Nick is also involved in a number of foundation-wide activities, including Conferences, Travel Assistance, Community Development and the Incubator.
Nick works as the CTO at Quanticate, a Clinical Research Organisation (CRO) with a strong focus on data, statistics and medical writing.


text:
I'm not a professional plant grower, but I've spent parts of the past three years working on vegetable farms around the Midwest, so I think that qualifies me somewhat. I'm quite knowledgeable about common garden vegetables including tomatoes, peppers, squash, potatoes, you name it, plus a number of Asian greens and gourds. I've done everything from drive a tractor to sow hundreds (thousands?) of seeds to sell at farmers markets. I also know a thing or two about raising chickens. In addition to traditional farmwork, I've grown my own plants in patio/container gardens (woohoo apartment living), and this year I've been fortunate enough to have a friend let me put a raised bed garden in his yard.
Finally, I should add that I also wildcraft — wildcrafting is the art of identifying and gathering wild plants for edible, medicinal, etc. purposes. In other words, I can tell you which weeds are good for eating.
If you have a question about gardening, whether in the ground or in containers, or wild edibles, let me know.


text:
Our international outreach programs are designed to grant our members, friends and families opportunity to extend and demonstrate God's love in a more practical fashion. Our actions include building bore hole water project in rural areas, providing clothing and medical support to disadvantaged individuals to mention just few.
Our ministry annually teams up with Charismatic Evangelical Ministries (CEM) in Ghana where crusades are held and practical love demonstrated through various services.
Support Power House International Ministries
You can Support Power House International Ministries by making a single or monthly donation.
Send a secure gift to us today. Your contribution helps this ministry to bring the good news of Christ to the world,
through our Community Outreaches, Missions and Media broadcast.
We accept all major credit cards payments through PayPal.


text:
It's not every day you meet a Medal of Honor recipient, and it's rarer still to jump out of a plane with one.
But that's what a cadet at the Air Force Academy will get to do tomorrow when Medal of Honor recipient Army Staff Sgt. Salvatore Giunta performs a tandem jump with a member of the Academy's Wings of Blue parachute team. Giunta also will receive an orientation flight in one of the Academy's T-10B gliders, the academy says in a release.
Giunta's primary reason for stopping by is to speak at the academy's National Character & Leadership Symposium.
In 2007, then Specialist Salvatore A. Giunta distinguished himself by acts of gallantry at the risk of his life above and beyond the call of duty while serving as a rifle team leader with Company B, 2d Battalion (Airborne), 503d Infantry Regiment, during combat operations against an armed enemy in the Korengal Valley, Afghanistan on October 25, 2007.
The 18th annual National Character & Leadership Symposium takes place tomorrow through Friday. His wife, Mrs. Jennifer Giunta, will also speak at NCLS.


text:
Digital Oilfields Forum 2013
WhenJun 04, 2013 08:00 AM to
Jun 05, 2013 06:00 PM
Key benefits:
- Learn from excellent CASE STUDIES delivered by oil&gas majors
- Meet your peers and LEADING EXPERTS in oil&gas industry
- Ultimate BENCHMARKING opportunity
- Find SOLUTIONS for the most actual challenges
- Be part of INTERACTIVE pannel discussions
In a constant quest of reducing costs and increasing production, oil and gas companies are becoming more dependent on digital technologies. Implementation of digital oilfields' practices is always a crucial change and still remains to be a challenging task.
Efficient data management and evaluation, new workflow strategies, change management, cyber security and automation initiatives are some of the key challenges, which need to be constantly addressed regardless of the implementation level.
Digital Oilfields Forum 2013 presents a great networking opportunity for industry professionals to meet leaders in the field of exploration and production and to keep themselves up to date with the newest technologies and strategies. The event offers a unique chance to benchmark and learn from practical solutions and numerous case studies presented.
Join us at our event in London and discover how digital oilfield innovations will help to improve your business.
More information about this event…


text:
GASB Requests Input on Revenue and Expense Recognition
February 19, 2018
Deadline to Provide Input is April 27, 2018
The Governmental Accounting Standards Board (GASB) has issued an Invitation to Comment from tribal governments and others on the development of a comprehensive revenue and expense recognition model.
One potential change for tribal governments could be the performance model for recognizing revenue for contracts. Some tribal governments that have healthcare facilities may find the proposal burdensome and cost prohibitive. NAFOA strongly suggests that tribal governments with a significant number of contracts should review the proposal and comment.
Written comments should be addressed to the Director of Research and Technical Activities, Project No. 4-6I, and either emailed to email@example.com.
Other Projects Needing Tribal Input:
NAFOA Survey on Financial Reporting: NAFOA understands that tribal governments need responsive financial accounting and reporting standards that provide useful information to all stakeholders. Providing data to accounting standard setters will demonstrate that current policy of selecting the commercial (FASB) financial reporting framework in some circumstances for tribal entities (gaming enterprises, tribally-owned banks, tribal pension plans, 501(c)(3) non-profits, and other business enterprises) that meet the definition of a government is necessary.
Capitalization of Interest Cost: Does your tribe have an opinion on whether capitalization should defer depending on if a borrowing is taxable or tax exempt? What criteria should be used to determine capitalization?
Implementation Guidance: This project proposes changes to a range of topics, including pensions, other post-employment benefits, the statistical section, regulatory reporting, and tax abatement disclosures.
For questions or comments please contact Jennifer Parisien at email@example.com (202) 558-8040.
Revenue and Expense Recognition Project
NAFOA Survey on Financial Reporting


text:
Author(s): Vasanti Unka
When the words in a tedious tome decide that life is just too dull, they escape. The world will never be the same again. The words jump into street signs, they leap onto shop signs, they decorate pathways and roadways and ponds. But one day they go too far...Award-winning illustrator Vasanti Unka has created a picture book complete with lift-the-flap inserts which is as ingenious as it is delightful. The Boring Book explores the importance of books and words in a fun and imaginative way. Children and adults alike will love it. The Boring Book is NOT a boring book.
Winner - New Zealand Post Margaret Mahy Book of the Year and winner of Best Picture Book category 2014.
Finalist: New Zealand Post Book Awards for Children & Young Adults 2014
"A remarkable book that exceeds any expectations of its genre. It exhibits the highest quality of design and its presentation is thoroughly original. The story takes delightful unexpected turns that charm afresh with each reading. Small children and older readers alike will be delighted by its subversive touches and entertained by its warmth and fun. The risks taken by the author perfectly illustrate the dangers of being careless with those powerful things words. For a long time to come, a well-loved companion for readers of all ages is sure to be"The Boring Book."" Judges' Report, "New Zealand Post"Book Awards for Children and Young Adults"
Vasanti Unka is a designer and illustrator based in Auckland. She is the illustrator of The Bean's Story, which was a 2008 Storylines notable book, and Hill & Hole by Kyle Mewburn. Hill & Hole was shortlisted for the 2011 New Zealand Post Book Awards for Children and Young Adults. It won the LIANZA Russell Clarke award the same year and was also the first children's book to win the Gerard Reid Award for Best Book at the PANZ Book Design Awards.


text:
This next series of blog posts will be a trilogy, as I've signed up to take a 3-week crash course in Electroforming at Craft Alliance. Electroforming can be described as a process that lets you create metal jewelry elements out of an organic object or keepsake. Cool, right? (I had originally planned to take a class on Wood and Found Objects Jewelry that was cancelled at the last minute. All of the metals classes sounded fun, so finding a replacement wasn't tough.) I had no clue what to expect, but brought a bunch of random trinkets to my first class to see what could be electroformed.
I've got baby on the brain for obvious reasons, but this stuff is so adorable! Now, which pieces would make fun jewelry?
The class was small – only about 5 ladies of various ages and experience in jewelry-making. The teacher, Jen Bradford, immediately put everybody at ease with her disarming, quirky personality. She has years of experience in all types of jewelry-making (her earthy, handmade pieces are amazing). Although she described electroforming as "finicky," she said it's her favorite medium. If it's not obvious from the name (which is wasn't to me – preggo brain, perhaps), electroforming involves electricity. A device called a rectifier converts alternating electric currents. You suspend an object that's been painted with metal into a "bath" of copper solution. The wires from the rectifier run electric currents through the bath and several hours later, you've got a custom piece of metal jewelry. (If this still sounds confusing, I feel you. Simple version? I painted an object with copperizing paint, let it dry, and then had it suspended into the bath. When I come back next week, we'll retrieve the items from the bath and see how they look all Metallica'd out.)
|The white radio-looking box is the rectifier. The cooler will house our jewelry materials while the rectifier does its thing.
I chose the stork and the baby bottle toys for my first crack at this. I super-glued little rings on top so the toys can be hung from a necklace or earring.
|Our pieces are going to look something like these, hopefully,
|Lots of machinery in here. A crafty gal could get into lots of trouble here. LOL
P.S. - Thank you, Craft Alliance and ALIVE Influencer Network for making my crafty dreams come true!


text:
Source: The Night Time Podcast
The Story of Lindsay Souvannarath – Part 2 – Life Before Choosing Death
In 2015, on the eve of Valentine's day, the people of Halifax would learn that they aren't exempt from the type of nightmares that play out on American news stations.
A local 19 year old James Gamble and his girlfriend, 23 year old American Lindsay Souvannarath, had taken the first steps in a plot to shoot and kill as many people as possible in the Halifax Shopping Centre food court before taking their own lives, just like the murderous pair they idolized… the Columbine shooters.
In part two of a series exploring the life and crime of the surviving would be shooter, the enigmatic Lindsay Souvannarath will finally break the silence she has maintained since boarding a plane to Nova Scotia with murderous intentions.
In 'Life Before Choosing Death' Nighttime will present portions of an extended discussion with Lindsay that walk us through the life she lived before she began planning her death. Throughout the conversation, Lindsay will provide background on many of the defining moments that formed her evolution from an above average kid in a loving family to a young women with an unwavering believe in nazism, a strong affinity towards all things Columbine, and a willingness to kill and die alongside a young man who shared her antisocial beliefs.
My Pet Skeleton by Lindsay Souvannarath
Come Ressurrection by Lindsay Souvannarath
Musical Theme: Shadowpasser by Vox Somnia https://voxsomniamusic.bandcamp.com/
Ambient Theme: Fall Asleep by Paragon Cause https://paragoncause.bandcamp.com/
Website: https://www.nighttimepodcast.com
Twitter: https://twitter.com/NightTimePod
Facebook: https://www.facebook.com/NightTimePod
Instagram: https://www.instagram.com/nighttimepod
Email: email@example.com
Support the show: https://www.patreon.com/nighttimepodcast


text:
God has been blowing my mind with revelation recently and I think I just might explode if I don't share it.
I've been thinking about physical vs spiritual reality a lot and yesterday as I was meditating, worshipping and journalling YHWH gave me insight into the equation E = MC². I was so blown away that I recorded a podcast then and there (watch out for it in the next few weeks, it's a powerful one but this is also something that I will talk about in the upcoming Vision Breakthrough Workshop on the 15th – unashamed plug)
This equation actually is all about the physical world and the spiritual world. For example, it explains that all matter in existence was created by energy. Yes, scientists have called this energy the Big Bang, but they KNOW that it wasn't a Big Bang that started everything at least NOT in the way that they want it to be understood and accepted.
They know this because there is a physical law that says energy can't be CREATED or DESTROYED it can only change from one form to another. So it begs the question if energy can't be created, where did the "Energy" come from? Let's say there was a big flash of Light from which existence came into being, where did the energy for The Big Bang come from? Did it just decide to randomly show up one day just because?
Evidence that there is a God
This creates two issues:
- The Issue of Spiritual Reality – if energy can't be created and it has to have always existed prior to any physical matter (creation) then we are left with one logical conclusion. There is more beyond what we can physically experience. There HAD to have been something prior to physical matter that was the Originator and Creator of it all.
- The issue of Intelligence – there also has to be some kind of Intelligence at work, with the ability to think and decide because there is NO RANDOMNESS in creation, nothing is out of order and there is a reason behind everything.
Humanistic Scientists would have you believe that it was totally random and that there is NO DESIGN, that we are just lucky and that by process of evolution and natural selection we came to have all the traits and characteristics that enable us to function so adequately and in harmony with other aspects of creation.
To me, that sounds like grasping or flawed logic. There is a problem-solving principle called Occam's razor which basically states that the simplest explanation is probably the most accurate. Unfortunately, that's not the case here. The E = MC² equation clearly shows that there must be a God, that is why many scientists who have previously believed in no God can't help but agree that there must be one in the face of the truth of creation that confronts them. In fact, God's Word says:
But there still remains an obvious problem, that the spiritual rulers really don't want people to believe in God let alone know WHO He really is. So they came up with a solution, a socially acceptable solution to appease the searching hunger and curiosity of a human race that was infilled with a desire to know their Creator more fully.
It is less threatening to accept that there is an Intelligent Energy or "Divine Force" that has always existed if we call it "The Universe" or "Spirit" or anything else right? It answers the flawed logic of no God whilst still being totally disempowering by separating those who hunger to know more of He who Was, Is and Is to Come.
And it's not just about non-Believers, nope – this affects Christians too because far too many of us still don't REALLY KNOW the God we serve. We still believe with our physical senses much more than we should over our spiritual senses, from a young age we have been taught HOW to view the world and how it operates and it boggles our minds to think otherwise. But who is that really helping? You, God, the enemy?
I feel YHWH is waking us up and shaking things up and out of our complacent physical reality existence because you NEED to know who you are in Him. I can feel Him doing a NEW thing and I'm totally in awe of every revelation He gives to me. I Know that HE wants me to teach this to people who know that deep down there is MORE than what we physically perceive.
When Albert Einstein was asked about God, he replied:
But I believe that God does want us to know and understand Him more fully so that we can go out powerfully into the world, in fact, this is exactly what His Word says. We as believers are at the forefront of being able to show the world who He is.
I know this isn't for everyone and I know some people might think I'm crazy, but I know that God is looking to transform the lives of people who are willing to step out of the mould so that they can transform the lives of others.
The first step for me is the workshop I'm running on the 15th, in this workshop I will go more deeply into how the spiritual and physical align but also – I really want to start working consistently with women who want to live totally transformed lives and go out into the world make an impact and change lives for God.
If you have a hunger to know yourself and God more fully, to live an empowered, impactful and truly abundant life, then you are absolutely the kind of person I'd love to work with.
Register for the workshop to start the journey with me.


text: Thank you to our Parents' Association for organizing such a wonderful evening full of good company, delicious food and friendly competition at Trivia Night! Our PA is a vital part of the Brookwood community, providing essential support through volunteering, fundraising, and providing parents with ways to connect with one another. Friday night was no exception! Joyful camaraderie thanks to brain-stumping trivia proved to be a highlight of the evening. Thank you to all who planned, organized and attended our annual fundraiser, and especially Riversbend restaurant in Essex for hosting us.


text:
The doctrine of vocation is a natural lead into a discussion on work. Work is one facet of vocation. It is one context where God calls an individual to worship him, serve his neighbor, provide for his family, utilize his heart, head, and hands and benefit humanity. Robert Barnett is a pastor who teaches a course on work at Gordon Conwell Theological Seminary. In a helpful article, he boils down the contents of his class for easy reading. He begins the article with this statement.
"If we are to help ourselves and others integrate Christian faith with the daily activities of the workaday world, the purpose of work and vocation must be adequately understood within the larger contours of our theology and world view. Therefore, I have identified and briefly summarized several 'theologies of work' that, in my view, represent various evangelical and mainline Protestant and Roman Catholic traditions."
Barnett identifies the following models of work and seeks to briefly describe each of them.VOCATIONAL MODEL (LUTHERAN)
Selected article Veith, Gene Edward. "The Doctrine of Vocation: How God Hides in Human Work." Modern Reformation 8:3 (May/June 1999). Quote from article "The Reformation doctrine of vocation teaches that God himself is active in everyday human labor, family responsibilities, and social interactions." Key points of the article
- God uses every day work to providentially care for human beings through their talents, opportunities, and stations in life; Luther called this the "mask of God."
- People are providentially called in to various vocations based on the God-ordained circumstances of their life. For example, a man may be simultaneously a farmer, citizen, churchman, husband, and father, and is thus called by God to those vocations.
- The purpose of one's vocation is to serve other people.
Selected article Hart, D. G. "Work as (Spiritual) Discipline." Modern Reformation 11:4 (July/August 2002). Quote from article "The doctrine of creation and providence, in the reformers' hands, elevated work that was once thought to be tainted because of its "worldliness" into a calling blessed by God." Key points of the article
- Work is founded upon Providence: God cares for His creation through our work, thus all legitimate vocations are significant to God.
- Work involves Worship: We worship God through obedience toHim in all areas of life; thus our attitude makes work meaningful.
- Work provides a context for Sanctification: Work cultivates godliness (especially moderation and self-control); thus any job can transform us.
Selected article Meeks, M. Douglas. "God and Work." In God the Economist: The Doctrine of God and Political Economy. Fortress Press, 1998. Quote from article "A humanizing economy depends on the creation of meaningful work for every person who is able and wants to work. This is necessary for the formation of a community that can realize human rights and redistribute wealth." Key points of the article
- Each person of the Trinity engages in distinctive personal work- the Father creates,the Son redeems, and the Spirit empowers the mission of the Father and Son. Thus, all people have a right to meaningful work according to one's abilities.
- The Trinity engages in cooperative work; each Person of the Trinity engages in work that coinheres in the work other the other Persons. Thus, human work must contribute to the life of the community.
- The Trinity engages in egalitarian work- the work of one Person of the Trinity is not elevated higher than that of the other Persons. Thus, all forms of work that exploit or dominate are wrong.
- The Trinity engages in self-giving love toward each other. Incentives to work that are dehumanizing are wrong (e.g., denigration of toilsome work over and above leisure; or exaltation of success without regard for the position or welfare of others in the community).
Selected article Volf, Miroslav. "Human Work, Divine Spirit, and New Creation: Toward a Pneumatological Understanding of Work." Pneuma 9 (1987):173-193. Quote from article "When God calls people to become God's children the Spirit gives them both callings and capabilities in the form of charismas to do particular tasks either in the Christian fellowship or in the world." Key points of the article
- Work is the exercise of one's Charisma (spiritual gifts, talents, and abilities) toaccomplish God's purposes both inside and outside of the Church; both Christians and non-Christians are given such spiritual gifts.
- Work can have lasting significance when it is involved in the Spirit's instrumental purpose to transform creation (there is continuity between the old and new creation). Thus, work does not have significance if it is not clearly transforming culture.
- Work has an ethical implication: "Occupation should create the social space for the free exercise of one's gifts in the service of one's neighbor; occupations that do not meet such criteria should be changed." Hardy, "Review of Work in the Spirit." 193.
Selected article Cosden, Darrell. "The Threefold Definition of Work and Its Application," pp. 153-161. In Theology of Work. Ph.D. thesis. St. Andrews University, 1998. Quote from article "Human work is a transformative activity essentially consisting of dynamically interrelated instrumental, relational, and ontological dimensions: whereby, along with work being an end in itself, the worker's and others' needs are providentially met; believers' sanctification is occasioned; and workers express, explore and develop their humanness while building up their natural, social and cultural environments thereby contributing protectively and productively to the order of this world and the one to come." Key points of the article
- Work is instrumental (work is a means to an end).Work provides sustenance to the worker and to society and enables personal spiritual formation.
- Work is relational (work is a means to an end). Work provides for personal self-fulfillment and is a context for social relationships. Work enables the development and improvement of societal structures.
- Work is ontological (work is an end itself). Work has value through its relationship to creation. Since we are created in the image of God (who is a worker), our work is significant because we model God's nature. Thus, all legitimate work has significance, no matter how mundane or ordinary. Work has value through its eschatological status (its relationship to the new creation as work is transformed and glorified along with all of creation in the consummation). Thus, work has significance because it is related to God's ultimate purposes.
Selected article John Paul II. "Work and Man" and "Elements for a Spirituality of Work." Chapters in Laborem Exercens: Encyclical Letter of the Supreme Pontif John Paul II on Human Work. Catholic Truth Society, 1981. Quote from article "Sweat and toil, which work necessarily involves in the present condition of the human race, present the Christian and everyone who is called to follow Christ with the possibility of sharing lovingly in the work that Christ came to do. This work of salvation came about through suffering and death on a Cross. By enduring the toil of work in union with Christ crucified for us, man in a way collaborates with the Son of God for the redemption of humanity. He shows himself a true disciple of Christ by carrying the cross in his turn every day in the activity that he is called upon to perform." Key points of the article
- Work has an objective meaning. Humans share in the activity of the Creator through cultural and economic activity to sustain and improve the worker, the worker's family, and the community. Thus ordinary activities and work contribute to God's work.
- Work has a subjective meaning. Humans are created in the image of God and are persons capable of self-realization – work is valued because of the worker rather than the product of work. Thus, work has meaning only when it allows men and women to realize their humanity.
- All work is linked with toil and difficulty. Through work, men and women are able to collaborate with Christ in His labor to redeem humanity.


text:
Most of our clients are tech or services firms that are looking to enter new markets or bring new products to market. Even for some of our largest clients, strategic market development had not been a priority. However, as customers get more sophisticated and demanding, our clients have needed to adopt a more focused and strategic approach. We help them put the right plans in place to grow vertical markets and revenue opportunities. We are often hired to create a sound, smart, and effective go-to-market plan that will help accelerate the sales and business development efforts.
DIAMOND Strategic Marketing helps firms more effectively enter new vertical and industry markets, integrate sales and marketing programs, and develop effective go-to-market plans. Vertical marketing strategies are critical to help keep a growing firm on target and focused. Customers are looking for companies that understand their business needs. They want partners who understand their challenges be they compliance, regulations, or other unique market needs. We always work with our clients to ascertain the most likely vertical markets to pursue and then develop the plan to make them a leader in the market. The vertical marketing plan includes messaging, communications strategies, and sales acceleration and integration programs. The intention is to help establish the firm as a leader in one or more vertical markets.


text:
Bundle home and auto to save
Bundle home and auto and save.
Or call 1-866-439-5633.
From tornadoes in the summer to blizzards in the winter, North Dakota condo owners have a lot to pay attention to when it comes to protecting their property. Fortunately, Esurance can help you find affordable condo insurance that can pay repair or replacement bills if your valuables are damaged or stolen, safeguard against risks that your Homeowners Association (HOA) insurance might not cover, and more.
Simply get a free North Dakota condo insurance quote through us to see how reliable coverage from our partner can give you the financial protection you need if things in the Peace Garden State ever take a turn for the worse.
In addition to repairing or replacing your furniture, electronics, clothes, and more following theft or damage, condo insurance helps protect you in ways your HOA's master policy typically doesn't. Here are just a few examples:
While condo insurance is generally very affordable — considering your policy only needs to protect your unit's interior and your belongings, not an entire building — it doesn't hurt to be able to save a little more in North Dakota. Depending on your condo insurer, you could save on coverage if your condo building is equipped with a central fire alarm system or wind-resistant features.
Though a first snowfall or a breezy summer day are part of what make North Dakota heavenly, it's the extremes that can harm residents of the Peace Garden State. In fact, North Dakota averages 32 tornadoes a year, with the season peaking in June.
While your HOA is responsible for repairing exterior damage and making sure your building's in tip-top shape, their insurance doesn't extend to your unit's interior. Good thing your personal condo insurance has you covered in case, say, an icicle breaks a window or a burst pipe floods your bathroom.
Or speak with a licensed agent at 1-866-439-5633.
Condo insurance quotes are provided by Answer Financial, Inc., or Security First Insurance Company for FL residents. Esurance does not underwrite, provide customer service, or pay claims for any condo policies sold by Answer Financial or Security First Insurance Company.
Coverages, discounts, and billing options are subject to state availability, individual qualification, and/or the insuring company's underwriting guidelines. Terms, conditions, limits, and exclusions will apply. Rates are subject to change.


text:
Ever wondered how good your dog would be at photography? No? Us neither, to be honest. But Nikon has come up with a way of finding out, which piques our interest a little more.
Through its Heartography technology concept, Nikon has devised a dog camera mount - for the Nikon Coolpix L31 - that senses when a pooch's heart rate increases and takes a picture whenever it peaks.
That means it will technically take an image every time the dog is most excited, hopefully of something interesting.
An owner can also get an idea of when the camera will fire as the mount comes with a small OLED panel that shows the dog's heart rate. The baseline rate can also be adjusted so you don't just get a stack of pics of food or another dog's backside.
Nikon has provided some of the shots taken by Grizzler, a collie it calls the "world's first canine photographer", and some of the results, we have to admit, are quite impressive. However, whether Nikon Asia wants to make the Heartography kit into a real-life consumer product is unclear.
Until then, you can always just strap a GoPro to your pet and take grabs from the resulting footage, if that's what floats your boat.


text:
Jade IPA | Foothills Brewing Company | Part 2 of 2
I rolled into Asheville in December 1999 after leaving Clearwater, FL. It was a bit of a culture shock due to the friendly people, the weather and the beer choices. Up until then, the best craft offering I had was a Samuel Adams so you can imagine what it was like for this beer-virgin in the up-and-coming beer city USA. I since have a love and deep respect for beer brewed next door in North Carolina. My liver has never been quite the same and probably never will.
While exploring Asheville I also attended my first beer festival, Brewgrass. Not only did Asheville expand my beer exploration it also introduced me to jam bands such as The Dead, Widespread and also created a deep love for bluegrass music. It was also at Brewgrass that I was first introduced to Foothills Brewing, to Jade IPA and to my favorite Foothills beer, Seeing Double IPA. Now, at this time I didn't know much about the brewing process or the complex brews that can be created from simply changing ingredients, mash temperature and fermentation. I have learned much since as it was events like this that fueled my interest in homebrewing.
I felt it fitting to do this post here at the beginning of 2017 as Knoxville, and all of Tennessee, will be seeing an enhanced selection of beer at both the local bottle stores like The Casual Pint and at our local breweries, which now are too many to count on two hands! What is this of which I speak? The definition of beer has changed from 6.25% to 10.1% ABV. This means places like The Casual Pint and Bearden Beer Market will be able to carry a whole list of beer that, while we may have been able to find at the liquor store, was not allowed to be sold in these types of spots due to licensing and how the state defined "beer." While breweries like Foothills Brewing Company have been in our market for a while, they haven't been able to offer their complete lineup in all of our local spots – well the bar has changed my friends! WOOT!!!
On to the beer! This beer pours a great hazy pale color with a moderate head that is easily agitated. The aroma is heavenly; mango, tangerine and a touch of pepper. The flavor is dominated by the Jade hops which start off with hints of tropical fruits, pine and then a slight peppery finish from the dry hop additions of Citra and Chinook. This intense hop profile is balanced by a nice malty sweetness – biscuit perhaps – creating one hell of a great beer. Clocking in at 7.4% ABV you can easily have two glasses on a Tuesday night and be just fine. It is very hard to be jaded with such a wonderful beer like this!
Final snobs: I remember a time when we would bring beer like this back from out of state. It's hard to believe that beer like this is not only available in Tennessee but is now more accessible than ever. Cheers to Foothills Brewing Company for a fabulous, bold, citrusy mouthful of an IPA and cheers to all of us for what lies ahead in 2017 and beyond. If it's beer like this, it's going to be an incredible year.
Prost, folks!


text:
Privacy Policy
Privacy Policy
Trees For Hosting ("we") are committed to protecting and respecting your privacy.
This policy (together with our terms of use http://www.treesforhosting.com/terms, terms and conditions of supply http://www.treesforhosting.com/supply and any other documents referred to on it) sets out the basis on which any personal data we collect from you, or that you provide to us, will be processed by us. Please read the following carefully to understand our views and practices regarding your personal data and how we will treat it.
For the purposes of the Data Protection Act 1998 (the "Act"), the data controller is Trees For Hosting of Apsley HP3 9SW.
1. Information we may collect from you
1.1 We may collect and process the following data about you:
1.1.1 information that you provide by filling in forms on our website https://www.treesforhosting.com (our "site"). This includes information provided at the time of registering an account, purchasing services from us or requesting further services. We may also ask you for information when you report a problem with our site or the services you have purchased;
1.1.2 if you contact us letter or email, we may keep a record of that correspondence;
1.1.3 if you contact us by telephone, we may record our telephone conversation for training purposes and, if you are asking us to provide you with the use of a dedicated hosting server, for the purposes of proving your request;
1.1.4 we may also ask you to complete surveys that we use for research purposes, although you do not have to respond to them;
1.1.5 details of transactions you carry out through our site and of the fulfilment and administration of your orders; and
1.1.6 details of your visits to our site including, but not limited to, traffic data, location data, weblogs and other communication data, whether this is required for our own billing purposes or otherwise and the resources that you access and use.
2. IP addresses and cookies
2.1 We may collect information about your computer, including where available your IP address, operating system and browser type, for system administration and to report aggregate information to our advertisers. This is statistical data about our users' browsing actions and patterns, and does not identify any individual.
2.2 For the same reason, we may obtain information about your general Internet usage by using a cookie file which is stored on the hard drive of your computer. Cookies contain information that is transferred to your computer's hard drive. They help us to improve our site and to deliver a better and more personalised service. They enable us:
2.2.1 to estimate our audience size and usage pattern;
2.2.2 to store information about your preferences, and so allow us to customise our site according to your individual interests;
2.2.3 to speed up your searches; and
2.2.4 to recognise you when you return to our site.
2.3 You may refuse to accept cookies by activating the setting on your browser which allows you to refuse the setting of cookies. However, if you select this setting you may be unable to access certain parts of our site. Unless you have adjusted your browser setting so that it will refuse cookies, our system will issue cookies when you log on to our site.
3. Where we store your personal data
3.1 The personal data that we collect from you will be stored on our servers inside the European Economic Area ("EEA"). We will take all steps reasonably necessary to ensure that your data is treated securely and in accordance with this privacy policy.
3.2 Where we have given you (or where you have chosen) a password which enables you to access certain parts of our site, you are responsible for keeping this password confidential. We ask you not to share a password with anyone.
3.3 Unfortunately, the transmission of information via the Internet is not completely secure. Although we will do our best to protect your personal data, we cannot guarantee the security of your data transmitted to our site; any transmission is at your own risk. Once we have received your information, we will use strict procedures and security features to try to prevent unauthorised access. Specifically, your personal data will be stored in accordance with the Payment Card Industry Data Security Standard.
4. Uses made of the information
4.1 We use information held about you in the following ways:
4.1.1 to ensure that content from our site is presented in the most effective manner for you and for your computer;
4.1.2 to provide you with information, products or services that you request from us or which we feel may interest you, where you have consented to be contacted for such purposes;
4.1.3 to carry out our obligations arising from any contracts entered into between you and us;
4.1.4 to allow you to participate in interactive features of our service, when you choose to do so;
4.1.5 to notify you about changes to our service.
4.2 If you have placed an order for our services, we will use the information we hold to send you our regular newsletter. This newsletter is our primary method of communicating with you and will inform you of changes to our site, notify you of planned outages and updates to our services, and keep you informed about our services generally. By placing an order for our services, you consent to us using the information we hold about you in this way.
4.3 If you are an existing customer, we will only contact you by electronic means (e-mail or SMS) with information about goods and services similar to those which were the subject of a previous sale to you.
5. Disclosure of your information
5.1 We will not sell, share or discoles you information.
5.2 We will only disclose your personal information to third parties if legaly obliged:
5.2.1 if we are under a duty to disclose or share your personal data in order to comply with any legal obligation, or in order to enforce or apply our terms of use http://www.treesforhosting.com/websiteuse.shtml or terms and conditions of supply http://www.treesforhosting.com/termshi.shtml and other agreements; or to protect our rights, property, or safety, or that of our customers, or others. This includes exchanging information with other companies and organisations for the purposes of fraud protection and credit risk reduction.
6. Disclosure of your information
6.2 Our site may, from time to time, contain links to and from the websites of our partner networks, advertisers and affiliates. If you follow a link to any of these websites, please note that these websites have their own privacy policies and that we do not accept any responsibility or liability for these policies. Please check these policies before you submit any personal data to these websites.
7. Access to information
7.1 The Act gives you the right to access information held about you. Your right of access can be exercised in accordance with the Act. Any access request may be subject to a fee of £10 to meet our costs in providing you with details of the information we hold about you.
8. Changes to our privacy policy
8.1 Any changes we may make to our privacy policy in the future will be posted on this page and, where appropriate, notified to you by e-mail.
9. Contact
Hosting Features
The easiest control panel ever
1 click install Joomla / Wordpress and loads more
Latest spec server hardware
UK based servers
Instant activation
Free ecommerce software
iPhone control panel access
Extensive help database built in
Stunning support