Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Сазонов Александр #237

Open
wants to merge 52 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
ad2d818
Initial TagsCloudVisualization commit
AlexxSaz Nov 9, 2024
e68c53d
Custom classes raplaced by system drawing lib
AlexxSaz Nov 11, 2024
f5e166b
Inited points generator class
AlexxSaz Nov 11, 2024
55e34ba
Added implementation to GetNewPoint and tests
AlexxSaz Nov 12, 2024
6d20961
PointGenerator refactored
AlexxSaz Nov 12, 2024
8056773
Implementation changed to use PointGenerator
AlexxSaz Nov 12, 2024
d667276
Refactored CircularCLoudLayouter
AlexxSaz Nov 12, 2024
9e1ec6f
Created extention method for Point
AlexxSaz Nov 12, 2024
898414c
Point generator refactored
AlexxSaz Nov 12, 2024
7e04cfb
Solution changed to tdd.sln
AlexxSaz Nov 13, 2024
903e69b
Point extension removed
AlexxSaz Nov 13, 2024
86704ff
Tests moved to special namespace
AlexxSaz Nov 13, 2024
d0636b7
Point generator tests refactored
AlexxSaz Nov 13, 2024
891e73d
Interface created
AlexxSaz Nov 13, 2024
8fdf444
Added new tests
AlexxSaz Nov 13, 2024
1320a4a
Created new project for tests
AlexxSaz Nov 15, 2024
91a0388
Created new interface
AlexxSaz Nov 15, 2024
fd798c6
Point generator tests moved to new project
AlexxSaz Nov 15, 2024
53157f1
Cloud layouter test moved and renamed
AlexxSaz Nov 15, 2024
9047c0e
TagCloud added
AlexxSaz Nov 16, 2024
e71f57f
Cherry picked extension for point
AlexxSaz Nov 12, 2024
0ac9619
Added extension for rectangle
AlexxSaz Nov 16, 2024
3ad22ea
Changed point extensions
AlexxSaz Nov 16, 2024
3b25de2
Fixed getting new rectangle in CircularCloudLayouter
AlexxSaz Nov 16, 2024
18aa897
TagCloud refactored
AlexxSaz Nov 16, 2024
0e7de68
PointGenerator refactored
AlexxSaz Nov 16, 2024
3843478
Some tests refactored
AlexxSaz Nov 16, 2024
e42563c
Added new tests to tag cloud
AlexxSaz Nov 17, 2024
055b888
Added test to check that layouter has circular form
AlexxSaz Nov 17, 2024
02a9b74
Added class that creates tag cloud example
AlexxSaz Nov 17, 2024
574bcc8
Installation of default objects has been changed
AlexxSaz Nov 17, 2024
f983fe4
Angle step changed
AlexxSaz Nov 17, 2024
692ce6c
Reworked layouter tests for new angle step
AlexxSaz Nov 17, 2024
677cdf9
Added visualization class
AlexxSaz Nov 17, 2024
5f6471e
Created samples and readme
AlexxSaz Nov 17, 2024
0647fae
GenereatePoint method reworked to pure method
AlexxSaz Nov 17, 2024
99b191c
Added teardown to save failed pictures
AlexxSaz Nov 17, 2024
7ee7523
Refactored layouter tests
AlexxSaz Nov 17, 2024
a777a93
CloudLayouter tests reworked
AlexxSaz Nov 17, 2024
2b4a1ed
Test replaced by program.cs
AlexxSaz Nov 17, 2024
72851ba
TagCloud properties reworked to constant time. But addRectangle isnt …
AlexxSaz Nov 17, 2024
a1d4e86
Replaced sample to random rectangles
AlexxSaz Nov 17, 2024
af5b600
PointGenerator test for spiral is reworked
AlexxSaz Nov 17, 2024
1acce94
Some things refactored
AlexxSaz Nov 17, 2024
936f24c
Rework method that returns new color
AlexxSaz Nov 18, 2024
20fbb7f
Added new class to generate sizes
AlexxSaz Nov 18, 2024
ceda81c
Fluent style changed
AlexxSaz Nov 19, 2024
8482ee9
CloudLayouter test fixed
AlexxSaz Nov 19, 2024
a18455d
Parallelizable accepted to whole project
AlexxSaz Nov 19, 2024
19ea2dc
Removed virtual method
AlexxSaz Nov 19, 2024
25352da
Tag cloud properties reworked to expression body
AlexxSaz Nov 19, 2024
57390e8
Fixed drawing lib problem
AlexxSaz Nov 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions cs/TagsCloudTests/CloudLayouterShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using FluentAssertions;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не нашел тестов на :
image

Если такие есть, отпиши в этом комменте их названия и логику работы. Потому что те, что я нашел, как будто не проверяют все эти требования

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Переписал тесты. В новых коммитах:
тест PutNextRectangle_ReturnRectanglesInCircle_AfterManyExecution проверяет, что сумма площади всех прямоугольников примерно равна площади окружности, в которой прямоугольники находятся. А также, что расстояние от каждого прямоугольника до центра лейаута меньше, чем радиус окружности. Этот тест говорит о том, что форма облака - окружность, а также, что облако максимально плотное.

тест PutNextRectangle_ReturnRectangleThatNotIntersectsWithOther_AfterManyExecution проверяет, что каждый из прямоугольников на лейауте не пересекается со всеми остальными прямоугольниками, кроме себя самого.

using NUnit.Framework.Interfaces;
using System.Drawing;
using TagsCloudVisualization;
using TagsCloudVisualization.Extensions;
using TagsCloudVisualization.Interfaces;

namespace TagsCloudTests;

[TestFixture]
[Parallelizable(scope: ParallelScope.All)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А можно ли этот атрибут применить на всю сборку? Чтобы на каждый класс не вешать его

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

да, если использовать наследование, где базовый класс будет иметь все необходимые нам атрибуты

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А еще варианты? Можем в шарпе есть решение?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно через таски. Условно сделать массив тасок со всеми тестами и запустить их параллельно

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Можно через атрибут на всю сборку - [assembly: Parallelizable(ParallelScope.Children)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Атрибут - ок) Также могу порекомендовать такие глобальные штуки выносить в самостоятельные файлы, т.к. они не принадлежат конкретному файлу с тестами, а всем)

public class CloudLayouterShould
{
private readonly Point _defaultCenter = new(0, 0);
AlexxSaz marked this conversation as resolved.
Show resolved Hide resolved
private readonly Random _random = new();

public virtual ICloudLayouter GetCloudLayouter(Point center) =>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем virtual? И также зачем public ?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

идея в том, чтобы было возможно наследуя класс, переопределить этот метод, где он будет возвращать другой cloudLayouter

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если сделать другой cloudLayouter форма которого - окружность. То можно будет унаследовать тесты и добавить какие-то специфические к конкретному layouter

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Но зачем это решать наследованием?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А как это решается? через DI?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Лучше стараться избегать наследования, т.к. с ним ооочень легко наплутать
Можно решить, например, через в TestFixture тип указывать. При условии, что мы ожидаем, что реализации этого интерфейса должны проходить тесты успешно

Можно через DI и делегирование) вариантов много разных

new CircularCloudLayouter(center);

[Test]
[Repeat(5)]
public void PutNextRectangle_ReturnRectangleWithExpectedLocation_AfterFirstExecution()
{
var expectedCenter = new Point(_random.Next(-10, 10), _random.Next(-10, 10));
var rectangleWidth = _random.Next(5, 100);
var rectangleSize = new Size(rectangleWidth, rectangleWidth / 2);
AlexxSaz marked this conversation as resolved.
Show resolved Hide resolved
var cloudLayouter = GetCloudLayouter(expectedCenter);

var actualRectangle = cloudLayouter.PutNextRectangle(rectangleSize);

actualRectangle.GetCentralPoint().Should().BeEquivalentTo(expectedCenter);
}

[TestCase(-1, 1)]
[TestCase(1, -1)]
[TestCase(0, 0)]
public void PutNextRectangle_ThrowArgumentOutOfRangeException_AfterExecutionWith(int width, int height)
{
var rectangleSize = new Size(width, height);
var circularCloudLayouter = new CircularCloudLayouter(_defaultCenter);

var executePutNewRectangle = () => circularCloudLayouter.PutNextRectangle(rectangleSize);

executePutNewRectangle.Should().Throw<ArgumentOutOfRangeException>();
}

[Test]
[Repeat(5)]
public void PutNextRectangle_ReturnRectangleThatNotIntersectsWithOther_AfterManyExecution()
{
var seenRectangles = new HashSet<Rectangle>();
var rectangleSizes = GetSizes(_random.Next(10, 100), _random.Next(100, 200));
var cloudLayouter = GetCloudLayouter(_defaultCenter);

var rectangleList = rectangleSizes
.Select(size => cloudLayouter.PutNextRectangle(size));

foreach (var rectangle in rectangleList)
{
seenRectangles.Add(rectangle);
rectangleList
.Where(rect => !seenRectangles.Contains(rect))
.All(rect => rect.IntersectsWith(rectangle))
.Should().BeFalse();
AlexxSaz marked this conversation as resolved.
Show resolved Hide resolved
}
}

[Test]
[Repeat(5)]
public void PutNextRectangle_ReturnLastRectanglesWithCloseRadius_AfterManyExecution()
{
var largestSide = _random.Next(100, 200);
var rectangleSizes = GetSizes(_random.Next(5, 10), largestSide);
var radii = new List<double>();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что такое radii?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

гугл сказал, что это множественное число от radius=)

var circularCloudLayouter = new CircularCloudLayouter(_defaultCenter);
var lastIndex = (int)(largestSide * 0.9);
var expectedDifference = (int)(largestSide * 0.05);

foreach (var rectangleSize in rectangleSizes)
{
var currSquare = circularCloudLayouter.PutNextRectangle(rectangleSize);
var squareCenter = currSquare.GetCentralPoint();
radii.Add(Math.Round(squareCenter.GetDistanceTo(_defaultCenter)));
}

for (var i = lastIndex; i < largestSide; i++)
{
(radii[i] - radii[i - 1]).Should().BeLessOrEqualTo(expectedDifference);
}
}

[Test]
[Repeat(5)]
public void PutNextRectangle_ReturnRectangleWithMaximumDensity_AfterManyExecution()
{
var rectangleWidth = _random.Next(5, 1000);
var rectangleSize = new Size(rectangleWidth, rectangleWidth / 2);
var diagonal = Math.Sqrt(Math.Pow(rectangleSize.Height, 2) + Math.Pow(rectangleSize.Width, 2));
var circularCloudLayouter = new CircularCloudLayouter(_defaultCenter);
var radii = new List<double>();
var rectangleCount = _random.Next(10, 200);

for (var i = 0; i < rectangleCount; i++)
{
var currSquare = circularCloudLayouter.PutNextRectangle(rectangleSize);
var squareCenter = currSquare.GetCentralPoint();
radii.Add(Math.Round(squareCenter.GetDistanceTo(_defaultCenter)));
}

var radiusDifferences = radii
.Skip(1)
.Zip(radii, (current, previous) => current - previous);
foreach (var difference in radiusDifferences)
difference.Should().BeLessOrEqualTo(diagonal);
}

private static IEnumerable<Size> GetSizes(int lowest, int largest) =>
Enumerable.Range(lowest, largest)
.Select(number => new Size(number, number / 2))
.Reverse();
}
39 changes: 39 additions & 0 deletions cs/TagsCloudTests/PointExtensionShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Drawing;
using FluentAssertions;
using TagsCloudVisualization.Extensions;

namespace TagsCloudTests;

[TestFixture]
[Parallelizable(scope: ParallelScope.All)]
public class PointExtensionShould
{
[TestCase(0, 0, 1, 2)]
[TestCase(0, 0, 1, 0)]
[TestCase(3, 5, 0, 5)]
public void PointShiftTo_ReturnedMovedPoint_WhenSet(int pointX, int pointY, int shiftX, int shiftY)
{
var point = new Point(pointX, pointY);
var movementDirection = new Size(shiftX, shiftY);

var movedPoint = Point.Add(point, movementDirection);

MoveTo_CheckShift(point, movementDirection, movedPoint);
}

[Test]
public void MoveTo_ReturnedNotMovedPoint_WhenSetZeroDirection()
{
var point = new Point(5, 6);

MoveTo_CheckShift(point, new Size(0, 0), point);
}

public void MoveTo_CheckShift(Point point, Size movementDirection, Point expectedPoint)
AlexxSaz marked this conversation as resolved.
Show resolved Hide resolved
{
var movedPoint = point.MoveTo(movementDirection);

movedPoint.Should().BeEquivalentTo(expectedPoint);
}
}

60 changes: 60 additions & 0 deletions cs/TagsCloudTests/PointGeneratorShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Drawing;
using FluentAssertions;
using TagsCloudVisualization;
using TagsCloudVisualization.Extensions;
using TagsCloudVisualization.Interfaces;

namespace TagsCloudTests;

[TestFixture]
[Parallelizable(scope: ParallelScope.All)]
public class PointGeneratorShould
{
private readonly Point _defaultCenter = new(1, 1);
private readonly Random _random = new();

public virtual IPointGenerator GetPointGenerator(Point center) =>
new SpiralPointGenerator(center);

[Test]
public void GetNewPoint_ReturnCenter_AfterFirstExecution()
{
var pointGenerator = GetPointGenerator(_defaultCenter);
var newPointIterator = pointGenerator.GeneratePoint().GetEnumerator();
AlexxSaz marked this conversation as resolved.
Show resolved Hide resolved
newPointIterator.MoveNext();
var point = newPointIterator.Current;

point.Should().BeEquivalentTo(_defaultCenter);
}

[TestCase(0)]
[TestCase(-1)]
public void ThrowArgumentOutOfRangeException_AfterExecutionWith(double radiusStep)
{
var pointGeneratorCreate = () => new SpiralPointGenerator(_defaultCenter, radiusStep);

pointGeneratorCreate.Should().Throw<ArgumentOutOfRangeException>();
}

[Test]
[Repeat(5)]
public void GetNewPoint_ReturnPointWithGreaterRadius_AfterManyExecutions()
{
const double radiusStep = 0.02;
const double radiusCheckPeriod = 1 / radiusStep;
var newPointGenerator = new SpiralPointGenerator(_defaultCenter, radiusStep);
var pointIterator = newPointGenerator.GeneratePoint().GetEnumerator();
var prevSpiralRadius = 0;
var pointsCount = radiusCheckPeriod * _random.Next(10, 100);

for (var i = 1; i <= pointsCount; i++)
{
pointIterator.MoveNext();
var currPoint = pointIterator.Current;
if (i % radiusCheckPeriod != 0) continue;
var currSpiralRadius = (int)currPoint.GetDistanceTo(_defaultCenter);
currSpiralRadius.Should().BeGreaterThanOrEqualTo(prevSpiralRadius);
prevSpiralRadius = currSpiralRadius;
}
}
}
25 changes: 25 additions & 0 deletions cs/TagsCloudTests/RectangleExtensionShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Drawing;
using FluentAssertions;
using TagsCloudVisualization.Extensions;

namespace TagsCloudTests;

[TestFixture]
[Parallelizable(scope: ParallelScope.All)]
public class RectangleExtensionShould
{
[Test]
[Repeat(5)]
public void GetCentralPoint_ReturnExpectedCenter_AfterExecutionWithRandomRectangle()
{
var rectangleLocation = new Point(0, 0);
var random = new Random();
var rectangleSize = new Size(random.Next(1, 100), random.Next(1, 100));
var rectangle = new Rectangle(rectangleLocation, rectangleSize);
var expectedCentralPoint = new Point(rectangleLocation.X + rectangleSize.Width / 2,
rectangleLocation.Y - rectangleSize.Height / 2);

rectangle.GetCentralPoint().Should().Be(expectedCentralPoint);
}
}

30 changes: 30 additions & 0 deletions cs/TagsCloudTests/TagCloudCreatorShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System.Drawing;
using FluentAssertions;
using TagsCloudVisualization;

namespace TagsCloudTests;

[TestFixture]
[Parallelizable(ParallelScope.All)]
public class TagCloudCreatorShould
{
private readonly Point _defaultCenter = new(0, 0);
private readonly Random _random = new();

[Test]
[Repeat(5)]
public void Create_ReturnTagCloudEquivalentToConstructor_AfterExecution()
{
var rectangleSizes = Enumerable.Range(_random.Next(2, 10), _random.Next(20, 100)).
Select(width => new Size(width, width / 2)).Reverse();
var currCloudLayouter = new CircularCloudLayouter(_defaultCenter);
var expectedCloudLayouter = new CircularCloudLayouter(_defaultCenter);
var defaultTagCloud = new TagCloud(currCloudLayouter);
foreach (var rectangleSize in rectangleSizes)
defaultTagCloud.AddNextRectangleWith(rectangleSize);

var expectedTagCloud = TagCloudCreator.Create(rectangleSizes, expectedCloudLayouter);
AlexxSaz marked this conversation as resolved.
Show resolved Hide resolved

defaultTagCloud.Should().BeEquivalentTo(expectedTagCloud);
}
}
Loading