tests
This commit is contained in:
@@ -1,67 +1,144 @@
|
|||||||
require "ruby_algebra"
|
require "ruby_algebra"
|
||||||
|
|
||||||
RSpec.configure do |config|
|
|
||||||
config.expect_with :rspec do |expectations|
|
|
||||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
RSpec.describe RubyAlgebra::Parser do
|
RSpec.describe RubyAlgebra::Parser do
|
||||||
describe "#parse" do
|
# Хелпер для быстрой сборки ожидаемых многочленов в тестах
|
||||||
it "returns nil for an empty string" do
|
def build_poly(terms_array)
|
||||||
expect(RubyAlgebra::Parser.parse("")).to eq nil
|
terms = terms_array.map do |t|
|
||||||
|
RubyAlgebra::Term.new(t[:coeff], t[:vars] || {})
|
||||||
|
end
|
||||||
|
RubyAlgebra::Polynomial.new(terms)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.parse_polynomial' do
|
||||||
|
let(:tokenizer) { ->(str) { RubyAlgebra::Parser::Tokenizer.new(str) } }
|
||||||
|
|
||||||
|
it 'парсит простое число как константный многочлен' do
|
||||||
|
result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("42"))
|
||||||
|
expect(result).to eq(build_poly([{ coeff: 42 }]))
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns Constant(a) for a" do
|
it 'парсит одиночную переменную' do
|
||||||
[10, 100, 343843, 180.1, 777, 0.52242].each do |a|
|
result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("x"))
|
||||||
expect(RubyAlgebra::Parser.parse(a.to_s)).to eq RubyAlgebra::Constant.new(a)
|
expect(result).to eq(build_poly([{ coeff: 1, vars: { "x" => 1 } }]))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'парсит многочлен с несколькими термами и степенями' do
|
||||||
|
# 2x^2 + 3x - 5
|
||||||
|
result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("2x^2 + 3x - 5"))
|
||||||
|
expected = build_poly([
|
||||||
|
{ coeff: 2, vars: { "x" => 2 } },
|
||||||
|
{ coeff: 3, vars: { "x" => 1 } },
|
||||||
|
{ coeff: -5, vars: {} }
|
||||||
|
])
|
||||||
|
expect(result).to eq(expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'обрабатывает отрицательный первый терм' do
|
||||||
|
result = RubyAlgebra::Parser.parse_polynomial(tokenizer.call("-x + 1"))
|
||||||
|
expect(result).to eq(build_poly([
|
||||||
|
{ coeff: -1, vars: { "x" => 1 } },
|
||||||
|
{ coeff: 1 }
|
||||||
|
]))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.parse_command' do
|
||||||
|
context 'Арифметические операции (взаимодействие многочленов)' do
|
||||||
|
it 'парсит команду сложения: C := A + B' do
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("C := A + B")
|
||||||
|
expect(cmd).to be_a(RubyAlgebra::AssignmentCommand)
|
||||||
|
expect(cmd.operation).to eq(:add)
|
||||||
|
expect(cmd.lhs).to eq("C")
|
||||||
|
expect(cmd.operand1).to eq("A")
|
||||||
|
expect(cmd.operand2).to eq("B")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'парсит команду вычитания: Result := P1 - P2' do
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("Result := P1 - P2")
|
||||||
|
expect(cmd.operation).to eq(:sub)
|
||||||
|
expect(cmd.operand1).to eq("P1")
|
||||||
|
expect(cmd.operand2).to eq("P2")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'парсит команду умножения: M := Poly1 * Poly2' do
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("M := Poly1 * Poly2")
|
||||||
|
expect(cmd.operation).to eq(:mult)
|
||||||
|
expect(cmd.operand1).to eq("Poly1")
|
||||||
|
expect(cmd.operand2).to eq("Poly2")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'парсит деление с остатком: Q, R := A / B' do
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("Q, R := A / B")
|
||||||
|
expect(cmd.operation).to eq(:div)
|
||||||
|
expect(cmd.lhs).to eq(["Q", "R"])
|
||||||
|
expect(cmd.operand1).to eq("A")
|
||||||
|
expect(cmd.operand2).to eq("B")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns Variable(x) for x" do
|
context 'Операции с числами (Scales)' do
|
||||||
["x", "y", "z", "coolVariable"].each do |x|
|
it 'парсит умножение на число как :scale' do
|
||||||
expect(RubyAlgebra::Parser.parse(x)).to eq RubyAlgebra::Variable.new(x)
|
cmd = RubyAlgebra::Parser.parse_command("A := B * 10")
|
||||||
|
expect(cmd.operation).to eq(:scale)
|
||||||
|
expect(cmd.operand2).to eq(10)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'парсит деление на число как :scale с инверсией' do
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("A := B / 2")
|
||||||
|
expect(cmd.operation).to eq(:scale)
|
||||||
|
expect(cmd.operand2).to eq(0.5)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns Addition(Constant(5), Variable(x)) for 5 + x" do
|
context 'Специальные методы' do
|
||||||
expect(RubyAlgebra::Parser.parse("5 + x")).to eq RubyAlgebra::Addition.new(RubyAlgebra::Constant.new(5), RubyAlgebra::Variable.new("x"))
|
it 'парсит дифференцирование: D := Diff(P, x)' do
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("D := Diff(P, x)")
|
||||||
|
expect(cmd.operation).to eq(:diff)
|
||||||
|
expect(cmd.operand1).to eq("P")
|
||||||
|
expect(cmd.operand2).to eq(["x"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'парсит подстановку: S := Subs(P, x=2, y=3)' do
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("S := Subs(P, x=2, y=3)")
|
||||||
|
expect(cmd.operation).to eq(:subs)
|
||||||
|
expect(cmd.operand1).to eq("P")
|
||||||
|
expect(cmd.operand2).to eq({ "x" => 2, "y" => 3 })
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns Subtraction(Variable(z), Variable(h)) for z - h" do
|
it 'парсит команду вывода (Display)' do
|
||||||
expect(RubyAlgebra::Parser.parse("z - h")).to eq RubyAlgebra::Subtraction.new(RubyAlgebra::Variable.new("z"), RubyAlgebra::Variable.new("h"))
|
cmd = RubyAlgebra::Parser.parse_command("A")
|
||||||
end
|
expect(cmd).to be_a(RubyAlgebra::DisplayCommand)
|
||||||
|
expect(cmd.item).to eq("A")
|
||||||
it "returns Multiplication(Constant(5), Constant(8)) for 60 * 8" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("60 * 8")).to eq RubyAlgebra::Multiplication.new(RubyAlgebra::Constant.new(60), RubyAlgebra::Constant.new(8))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns Division(Constant(3), Variable(j)) for 3/j" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("3/j")).to eq RubyAlgebra::Division.new(RubyAlgebra::Constant.new(3), RubyAlgebra::Variable.new("j"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns Division(Constant(3), Variable(j)) for 3/j" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("3/j")).to eq RubyAlgebra::Division.new(RubyAlgebra::Constant.new(3), RubyAlgebra::Variable.new("j"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns Power(Constant(2), Constant(24)) for 2^24" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("2^24")).to eq RubyAlgebra::Power.new(RubyAlgebra::Constant.new(2), RubyAlgebra::Constant.new(24))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns Multiplication(Constant(-1), Variable(x)) for -x" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("-x")).to eq RubyAlgebra::Multiplication.new(RubyAlgebra::Constant.new(-1), RubyAlgebra::Variable.new("x"))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns Variable(x) for +x" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("x")).to eq RubyAlgebra::Variable.new("x")
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns Addition(Addition(Constant(3), Constant(30)), Constant(300)) for 3 + 30 + 300" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("3 + 30 + 300")).to eq RubyAlgebra::Addition.new(RubyAlgebra::Addition.new(RubyAlgebra::Constant.new(3), RubyAlgebra::Constant.new(30)), RubyAlgebra::Constant.new(300))
|
|
||||||
end
|
|
||||||
|
|
||||||
it "returns Power(Constant(10), Power(Constant(10), Constant(10))) for 10 ^ 10 ^ 10" do
|
|
||||||
expect(RubyAlgebra::Parser.parse("10 ^ 10 ^ 10")).to eq RubyAlgebra::Power.new(RubyAlgebra::Constant.new(10), RubyAlgebra::Power.new(RubyAlgebra::Constant.new(10), RubyAlgebra::Constant.new(10)))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
RSpec.describe RubyAlgebra::Interpreter do
|
||||||
|
let(:interpreter) { RubyAlgebra::Interpreter.new }
|
||||||
|
|
||||||
|
it 'выполняет цепочку: присваивание и сложение' do
|
||||||
|
# Создаем полиномы через парсер и выполняем команды через интерпретатор
|
||||||
|
p1_cmd = RubyAlgebra::Parser.parse_command("A := 2x")
|
||||||
|
p2_cmd = RubyAlgebra::Parser.parse_command("B := 3x + 1")
|
||||||
|
add_cmd = RubyAlgebra::Parser.parse_command("C := A + B")
|
||||||
|
|
||||||
|
interpreter.execute(p1_cmd)
|
||||||
|
interpreter.execute(p2_cmd)
|
||||||
|
result_str = interpreter.execute(add_cmd)
|
||||||
|
|
||||||
|
expect(result_str).to include("5x + 1")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'выполняет деление с остатком' do
|
||||||
|
# (x^2 - 1) / (x - 1) = x + 1, остаток 0
|
||||||
|
interpreter.execute(RubyAlgebra::Parser.parse_command("A := 1x^2 - 1"))
|
||||||
|
interpreter.execute(RubyAlgebra::Parser.parse_command("B := 1x - 1"))
|
||||||
|
|
||||||
|
# В вашей грамматике деление: Q, R := A / B
|
||||||
|
cmd = RubyAlgebra::Parser.parse_command("Q, R := A / B")
|
||||||
|
interpreter.execute(cmd)
|
||||||
|
|
||||||
|
expect(interpreter.execute(RubyAlgebra::Parser.parse_command("Q"))).to eq("1.0x + 1.0")
|
||||||
|
expect(interpreter.execute(RubyAlgebra::Parser.parse_command("R"))).to eq("0")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user