Giter VIP home page Giter VIP logo

rizza's Introduction

rizza

An increasingly intelligent method to test RH Satellite.

Installation

pip install . or python setup.py install

Rizza will add a 'rizza' directory to your home directory, as well as a config directory with example config. After installation copy/rename the example configuration, located in ~/rizza/config/ to ~/rizza/config/rizza.yaml

Usage

rizza [-h] {brute,genetic,config,list,test}

Brute Force Testing

Rizza's most basic, and time consuming, operation is a brute force method of testing entities. It will try every combination of an entity's methods, fields, arguments, and available input methods. It is highly recommended that you limit the scope of this kind of test with --max-field, --max-inputs, and the exclude options available. An unlimited test can easily generate trillions of combinations and will likely take longer than the lifecycle of your product. -i, --input and -o, --output use relative paths only. Note: Using --async will load all tests into memory, so it is advised to limit the numbers to tests by either breaking them up into separate files, or limiting the scope of the methods and fields.

Examples: rizza brute --help

rizza brute -e Product -o tester.txt --max-fields 2 --max-inputs 1 --method-exclude raw search read get payload --async

rizza brute -i 10tests.txt -l stdout

Genetic Algorithm-Based Testing

Rizza is able to test entities (via their methods) using genetic algorithms to evolve toward a positive or negative goal. You can adjust the scoring criteria in config/rizza.yaml. Rizza, by default, will recursively try to create entities it both does and doesn't know how to, in order to resolve dependencies. You can limit or turn this off both in the config or at run-time with cli args. Note that this recursive process adds a significant amount of time. Once a test completes, it is saved in ~/rizza/data/genetic_tests/

Examples: rizza genetic --help

rizza genetic -e Organization -m create

rizza genetic -e Organization -m create --max-generations 100 --seek-bad --fresh --disable-recursion --async

Configuration

Rizza's main configuration file is located in config/rizza.yaml. After cloning, you will need to copy the example file to rizza.yaml. Most of these configurations have CLI overrides, and there are even some limited support for environment variables (SATHOST, SATUSER, SATPASS, CONFILE). Additionally, there is support for modifying some configuration options through rizza's cli.

Examples: rizza config --help

rizza config nailgun -p demo

rizza config nailgun --show

List

Rizza can tell you all the information it knows about your product plugin using the list command. These results are currently unfiltered, so will show anything that meets rizza's criteria for what constitutes an entity.

Examples: rizza list entities

rizza list methods -e Organization

Test

Rizza is also able to test itself, using pytest. This is mainly useful for testing your container images, to verify everything is working before you begin using rizza. You can even pass in pytest args by adding the --args flag. Examples: rizza test

rizza test --args=-v

Docker

Rizza is also available with automatic builds on dockerhub. You can either pull down the latest, or a specific released version. Additionally, you can build your own image locally. You will want to mount the local rizza directory to provide your configuration and keep any data rizza creates.

Examples: docker build -t rizza . or docker pull jacobcallahan/rizza

docker run -it rizza brute --help

docker run -it -v $(pwd):/root/rizza/:Z rizza brute -e Product -o docker.txt --max-fields 2 --max-inputs 1 --method-exclude raw search read get payload

docker run --rm -v $(pwd):/root/rizza/:Z jacobcallahan/rizza genetic -e Organization

Note

This project only explicitly supports python 3.6+

rizza's People

Contributors

jacobcallahan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

rizza's Issues

flaky test test_positive_nested_reach_goal and test_positive_organism

Run 50 times test_rizza
5 times failed - test_positive_nested_reach_goal
2 times failed - test_positive_organism

______________________________ test_positive_nested_reach_goal ______________________________

    def test_positive_nested_reach_goal():
        """Create a population and breed them until one matches """
        test_pop = genetics.Population(
            gene_base=NESTED_GENOME, population_count=10)
        for i in range(10):
            test_pop.population[i].points = grade_nested_list(
                test_pop.population[i].genes
            )
        test_pop.sort_population()
        initial_points = test_pop.population[0].points
        generations = 1
        while test_pop.population[0].points > 0 and generations < 100:
            test_pop.breed_population()
            assert len(test_pop.population) == test_pop.population_count
            generations += 1
            for i in range(10):
                test_pop.population[i].points = grade_nested_list(
                    test_pop.population[i].genes
                )
        test_pop.sort_population()
>       assert test_pop.population[0].points < initial_points
E       assert 12749855292 < 9660187854
E        +  where 12749855292 = Organism(genes=[[11, 11, 11, 76, 99], [4, 92, 66, 66, 92], [16, 16, 25, 3, 3]], points=12749855292).points

tests/helpers/test_genetics.py:92: AssertionError
__________________________________ test_positive_organism ___________________________________

    def test_positive_organism():
        test_org = genetics.Organism(genes=BASE_GENOME)
        assert test_org.genes == BASE_GENOME
        test_org.generate_genes()
        # This assertion has a 1:3628800 chance of failing
        assert test_org.genes != BASE_GENOME
        previous = test_org.genes[:]
        # We will make the mutation chance 100% to force a mutation
        test_org.mutate(gene_base=BASE_GENOME, mutation_chance=1)
>       assert test_org.genes != previous
E       assert [1, 7, 6, 14, 2, 22, ...] != [1, 7, 6, 14, 2, 22, ...]
E        +  where [1, 7, 6, 14, 2, 22, ...] = Organism(genes=[1, 7, 6, 14, 2, 22, 13, 12, 16, 17, 0, 24, 19, 10, 21, 18, 3, 5, 4, 9, 20, 23, 15, 8, 11], points=0).genes

tests/helpers/test_genetics.py:104: AssertionError

Implement an encompassing configuration file.

The file should be the fallback for all configuration options not explicitly set at run-time or by the existing dependencies'.
For example, nailgun has a configuration file it goes to if nothing it set at run-time. Rizza should try to load the config from that file, if no information is passed in. If that file doesn't exist, or is blank, Rizza should fall back to this file proposed in this issue.
Yaml is probably the best way to go for this.

the ideas on how to improve the judge function and selection process

def _judge(self, result=None, mock=False):

In the beginning, we only care about finding the correct solution. It is always easier to improve it later on.

yake

  • keyword extraction with probabilities to all words,
  • the lower the probability the more important word
    example.
hammer activation-key create --name 'abc'
>> Error: Could not find organization, please set one of options --organization-id, --organization, --organization-title, --organization-label.

usage:

import yake
error_message = "output string"
kw_extractor = yake.KeywordExtractor()
keywords = kw_extractor.extract_keywords(doc)
>>> 
[('find organization', 0.025580763661104764),
 ('Error', 0.0528063806271324),
 ('organization-id', 0.0528063806271324),
 ('organization-title', 0.0528063806271324),
 ('organization-label', 0.0528063806271324),
 ('organization', 0.06839635777587466),
 ('options', 0.11145728654016383),
 ('find', 0.1823394614884183),
 ('set', 0.1823394614884183)]

The most important words sorted from the top, starting with find organization , Error and organization-id and so on.

  • change the probability to seek maximum not a minimum (1 - np.array(data)
  • can be easily installed via pip

for API/nailgun:
it can match some whether a word in the error message is one of the fields or arguments and if it is give it high probability (>0.8), so the organism is likely to change.

for CLI:
By using roullete during the selection process, or rather stochastic roulete, it is probable that we will find the correct keyword, that hammer requires. The another important question would how to match a type (str, list, int, ...) to those keywords, randomly, naah that takes a lot of time. Another option is to create a matching scheme between API and CLI, this option is also unsatisfying.

  • the judge process can use additional information hammer -d
  • the keyword extractor can be fine-tuned with the satellite error messages.

The fitness function:
Nailgun is using error states, which is a good start.
We can burst the learning with heuristics like, if the error changed from the previous one/ones, get obtain a better score.

hammer can use error states as well, if debug option is used.

Before this is done is worth to think about general genetic algorithm and map the steps to those components. It was more complicated than I thought as these terms have different naming in rizza.

Create a prune flag for genetic tests

This option, in the form of a --prune flag, would go through the saved positive tests for an entity and remove any that no longer work.
This function would mainly be used for removing tests were saved due to reaching their max generations, instead of actually passing.
The function should check all positive tests saved in an entity's file.

Usage

$ rizza genetic -e Organization --prune
Organization create positive has been removed.
Organization delete positive has been removed.

Refactor CLI to use click

The current argparsr-based cli is a bit busy. Refactoring it to use click would allow for a more simple and dynamic flow.

Allow rizza to run from any directory

When rizza is run from any directory, outside of it's own main directory, the config class is unable to load the config.

FileNotFoundError: [Errno 2] No such file or directory: 'config/rizza.yaml'

Appending rizza's project directory to the config file path should fix this issue.

Improvement on debugging

entity = EntityTester.pull_entities()[self.entity](**self.field_dict)
result = getattr(entity, self.method)(**self.arg_dict)
if not isinstance(result, dict):
result = result.to_json_dict()
logger.debug('pass: {}'.format(result))
return {'pass': result}
except Exception as e:
handled = handle_exception(e)
logger.debug('fail: {}'.format(handled))
return {'fail': handled}

What would help for debugging is actual request send to API, so it's easy to compare it with request that is used inside the robottelo/foreman/api tests.

Any ideas on how to achieve the desired state ?

Same applies for a hammer, the constructed command can make life easier.

Update Readme

Readme need to be updated to include all the changes since it was last pushed.

New additions

  • config
  • genetic
  • list

Also, a description for the purpose of each would be nice.

Add a comprehensive logging solution

Logging implementation should be able to allow a user to write logs to a specified or default file, stdout, etc. All modules should be able to easily use the logger to handle output and feedback. Once implemented, the project will need to be gone through to identify areas where logging information would be valuable.

All of this should be configurable by the standard config file and at run-time via the cli.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.