<commit_before># xRuby

[![Build Status](https://travis-ci.org/exercism/xruby.svg?branch=master)](https://travis-ci.org/exercism/xruby)
[![Join the chat at https://gitter.im/exercism/xruby](https://badges.gitter.im/exercism/xruby.svg)](https://gitter.im/exercism/xruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Exercism Exercises in Ruby

## Setup

You'll need a recent (2.1+) version of Ruby, but that's it. Minitest
ships
with the language, so you're all set.

## Working on Test Suites

Each problem should have a test suite and an example solution.
The example solution should be named `example.rb`.

**Some test suites are generated from shared inputs/outputs, see
[Generated Test Suites](#generated-test-suites) below.** In short, if
a `lib/<problem>_cases.rb` file exists, then it's a generated problem.

### Hard-coded Test Suites

Run the test with `ruby path/to/the_test.rb`.

At the moment the Ruby problems `skip` all but the first test, in order
to not overwhelm people with errors.

If you want to temporarily disable the skips while working on a test
suite, you can run the file with a shim that temporarily disables them:

```sh
ruby -I./lib -rdisable_skip exercise/exercise/filename_test.rb
```

It is simpler to use the `rake` tool which is available in the project
root.  It will disable the skip calls for you automatically, it does the
same thing as the above.

If you would like to use the `rake` tool to run a single test while
developing clock, for example, you can do something like this:

```sh
rake test:clock
```

To pass arguments to the test command, like `-p` for example, you can run
the following:
```sh
rake test:clock -- -p
```

To show an example of running a limited number of tests, we will use the
"hamming" exercise with a pattern of "identical" to run (currently) two tests:
```sh
rake test:hamming -- -p -n="/identical/"
```

Note that flags which have an attached value, like above, must take the form
`-flag=value` and if `value` has spaces `-flag="value with spaces"`.


### Generated Test Suites

If you find a `<problem_name>_cases.rb` file in `lib/`, then the test suite is
generated from shared data, which can be found in the exercise definition in the [x-common][]
repository.

Typically you will want to do one of the following:

* [Regenerate the test suite](#regenerating-an-exercise) based on updated canonical data
* [Make changes to a generated exercise](#changing-a-generated-exercise)
* [Implement a new generator](#implementing-a-generator)

Generated exercises depend on the [the shared metadata][x-common], which must be
cloned to the same directory that contains your clone of the xruby repository:

```
tree -L 1 ~/code/exercism
├── x-common
└── xruby
```

#### Regenerating an Exercise

From within the xruby directory, run the following command, where $PROBLEM is the slug
of the exercise, e.g. `clock` or `atbash-cipher`:

```
bin/generate $PROBLEM
```

#### Changing a Generated Exercise

Do not edit `$PROBLEM/$PROBLEM_test.rb`. Any changes you make will be overwritten when
the file is generated the next time.

There are two reasons why a test suite might change:

1. the tests are wrong (an incorrect expectation, a missing edge case, etc)
1. there might be issues with the style or boilerplate

In the first case, the changes need to be made to the `canonical-data.json` file for
the exercise, which lives in the x-common repository.

```
../x-common/exercises/$PROBLEM/
├── canonical-data.json
├── description.md
└── metadata.yml
```

This change will need to be submitted as a pull request to the x-common repository. This pull
request needs to be merged before you can regenerate the exercise.

Changes that don't have to do directly with the test inputs and outputs should
be made to `lib/$PROBLEM_cases.rb`. Then you can regenerate the exercise with
`bin/generate $PROBLEM`.

#### Implementing a Generator

You will need to write code to produce the code that goes inside the test methods. Your
code will live in `lib/$PROBLEM_cases.rb`.

`lib/$PROBLEM_cases.rb` contains a derived class of `ExerciseCase` (in `lib/generator/exercise_cases.rb`)
which wraps the JSON for a single test case. The default version looks something like this:

```
class ProblemNameCase < ExerciseCase

  def workload
    # Example workload:
    "#{assert} Problem.call(#{input.inspect})"
  end

end
```

Instead of `ProblemName` use the CamelCased name of the actual problem. This is important, since
the generator script will infer the name of the class from the argument that is passed.

This class must provide the methods used by `lib/generator/test_template.erb`. The base class provides methods
for the default template for everything except `workload`.

`workload` generates the code for the body of a test, including the assertion
and any setup required. The base class provides a variety of assertion and
helper methods. Beyond that, you can implement any helper methods that you need
as private methods in your derived class. See below for more information about [the intention of workload](#workload-philosophy)

If you really must add additional logic to the view template, you can use a custom
template. Copy `lib/generator/test_template.erb` to your exercise directory, name it
`exercise.tt`, and customize.

You will not need to touch the top-level script, `bin/generate`.

The `bin/generate` command relies on some common logic implemented in `lib/generator.rb`.
You won't need to touch that, either.


### Workload philosophy.

Prioritize educational value over expert comprehension and make sure that
things are clear to people who may not be familiar with Minitest and even Ruby.

Provide the information the student needs to derive the code to pass the test
in a clear and consistent manner. Illustrate the purpose of the individual
elements of the assertion by using meaningful variable names.

Example output from the `workload` method:<commit_msg>overhaul 'hard-coded test suites' section of README<commit_after># xRuby

[![Build Status](https://travis-ci.org/exercism/xruby.svg?branch=master)](https://travis-ci.org/exercism/xruby)
[![Join the chat at https://gitter.im/exercism/xruby](https://badges.gitter.im/exercism/xruby.svg)](https://gitter.im/exercism/xruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Exercism Exercises in Ruby

## Setup

You'll need a recent (2.1+) version of Ruby, but that's it. Minitest
ships
with the language, so you're all set.

## Working on Test Suites

Each problem should have a test suite and an example solution.  The example
solution should be named `example.rb`.

**Some test suites are generated from shared inputs/outputs, see
[Generated Test Suites](#generated-test-suites) below.** In short, if
a `lib/<problem>_cases.rb` file exists, then it's a generated problem.

Run the tests using `rake`, rather than `ruby path/to/the_test.rb`. `rake`
knows to look for `example.rb` and to disable skips. Just tell `rake` the
name of your problem and you are set:

```sh
rake test:clock
```

To pass arguments to the test command, like `-p` for example, you can run
the following:
```sh
rake test:clock -- -p
```

To run a subset of the tests, use a regular expression:

```sh
rake test:hamming -- -p -n="/identical/"
```

Note that flags which have an attached value, like above, must take the form
`-flag=value` and if `value` has spaces `-flag="value with spaces"`.


### Generated Test Suites

If you find a `<problem_name>_cases.rb` file in `lib/`, then the test suite is
generated from shared data, which can be found in the exercise definition in the [x-common][]
repository.

Typically you will want to do one of the following:

* [Regenerate the test suite](#regenerating-an-exercise) based on updated canonical data
* [Make changes to a generated exercise](#changing-a-generated-exercise)
* [Implement a new generator](#implementing-a-generator)

Generated exercises depend on the [the shared metadata][x-common], which must be
cloned to the same directory that contains your clone of the xruby repository:

```
tree -L 1 ~/code/exercism
├── x-common
└── xruby
```

#### Regenerating an Exercise

From within the xruby directory, run the following command, where $PROBLEM is the slug
of the exercise, e.g. `clock` or `atbash-cipher`:

```
bin/generate $PROBLEM
```

#### Changing a Generated Exercise

Do not edit `$PROBLEM/$PROBLEM_test.rb`. Any changes you make will be overwritten when
the file is generated the next time.

There are two reasons why a test suite might change:

1. the tests are wrong (an incorrect expectation, a missing edge case, etc)
1. there might be issues with the style or boilerplate

In the first case, the changes need to be made to the `canonical-data.json` file for
the exercise, which lives in the x-common repository.

```
../x-common/exercises/$PROBLEM/
├── canonical-data.json
├── description.md
└── metadata.yml
```

This change will need to be submitted as a pull request to the x-common repository. This pull
request needs to be merged before you can regenerate the exercise.

Changes that don't have to do directly with the test inputs and outputs should
be made to `lib/$PROBLEM_cases.rb`. Then you can regenerate the exercise with
`bin/generate $PROBLEM`.

#### Implementing a Generator

You will need to write code to produce the code that goes inside the test methods. Your
code will live in `lib/$PROBLEM_cases.rb`.

`lib/$PROBLEM_cases.rb` contains a derived class of `ExerciseCase` (in `lib/generator/exercise_cases.rb`)
which wraps the JSON for a single test case. The default version looks something like this:

```
class ProblemNameCase < ExerciseCase

  def workload
    # Example workload:
    "#{assert} Problem.call(#{input.inspect})"
  end

end
```

Instead of `ProblemName` use the CamelCased name of the actual problem. This is important, since
the generator script will infer the name of the class from the argument that is passed.

This class must provide the methods used by `lib/generator/test_template.erb`. The base class provides methods
for the default template for everything except `workload`.

`workload` generates the code for the body of a test, including the assertion
and any setup required. The base class provides a variety of assertion and
helper methods. Beyond that, you can implement any helper methods that you need
as private methods in your derived class. See below for more information about [the intention of workload](#workload-philosophy)

If you really must add additional logic to the view template, you can use a custom
template. Copy `lib/generator/test_template.erb` to the `.meta` directory under your
exercise directory and customize. You may need to create `.meta` if you have not yet run
`bin/generate` on your problem.

You will not need to touch the top-level script, `bin/generate`.

The `bin/generate` command relies on some common logic implemented in `lib/generator.rb`.
You won't need to touch that, either.


### Workload philosophy.

Prioritize educational value over expert comprehension and make sure that
things are clear to people who may not be familiar with Minitest and even Ruby.

Provide the information the student needs to derive the code to pass the test
in a clear and consistent manner. Illustrate the purpose of the individual
elements of the assertion by using meaningful variable names.

Example output from the `workload` method:
{'fraction_non_alphanumeric': 0.0840034965034965, 'fraction_numerical': 0.0008741258741258741, 'mean_word_length': 4.505774783445621, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2665066', 'n_tokens_mistral': 3352, 'n_tokens_neox': 3205, 'n_words': 1580}